blob: 1a683d569887d7ad11693a1256da38a68cb6d683 [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"
38#endif /* !MBEDTLS_MD_C */
39
Neil Armstrong0d763412022-08-11 10:32:22 +020040#include "hash_info.h"
41
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020042#include <string.h>
43
Hanno Becker616d1ca2018-01-24 10:25:05 +000044#if !defined(MBEDTLS_ECJPAKE_ALT)
45
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020046/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020047 * Convert a mbedtls_ecjpake_role to identifier string
48 */
49static const char * const ecjpake_id[] = {
50 "client",
51 "server"
52};
53
Gilles Peskine449bd832023-01-11 14:50:10 +010054#define ID_MINE (ecjpake_id[ctx->role])
55#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020056
Neil Armstrongecaba1c2022-08-11 10:47:08 +020057/**
Gilles Peskine449bd832023-01-11 14:50:10 +010058 * Helper to Compute a hash from md_type
59 */
60static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
61 const unsigned char *input, size_t ilen,
62 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020063{
64#if defined(MBEDTLS_MD_C)
Gilles Peskine449bd832023-01-11 14:50:10 +010065 return mbedtls_md(mbedtls_md_info_from_type(md_type),
66 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020067#else
Gilles Peskine449bd832023-01-11 14:50:10 +010068 psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020069 psa_status_t status;
Gilles Peskine449bd832023-01-11 14:50:10 +010070 size_t out_size = PSA_HASH_LENGTH(alg);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020071 size_t out_len;
72
Gilles Peskine449bd832023-01-11 14:50:10 +010073 status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020074
Gilles Peskine449bd832023-01-11 14:50:10 +010075 return mbedtls_md_error_from_psa(status);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020076#endif /* !MBEDTLS_MD_C */
77}
78
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020079/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020080 * Initialize context
81 */
Gilles Peskine449bd832023-01-11 14:50:10 +010082void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020083{
Neil Armstrong0d763412022-08-11 10:32:22 +020084 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010085 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020086 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020087
Gilles Peskine449bd832023-01-11 14:50:10 +010088 mbedtls_ecp_point_init(&ctx->Xm1);
89 mbedtls_ecp_point_init(&ctx->Xm2);
90 mbedtls_ecp_point_init(&ctx->Xp1);
91 mbedtls_ecp_point_init(&ctx->Xp2);
92 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020093
Gilles Peskine449bd832023-01-11 14:50:10 +010094 mbedtls_mpi_init(&ctx->xm1);
95 mbedtls_mpi_init(&ctx->xm2);
96 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097}
98
99/*
100 * Free context
101 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100102void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200103{
Gilles Peskine449bd832023-01-11 14:50:10 +0100104 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200105 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200107
Neil Armstrong0d763412022-08-11 10:32:22 +0200108 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100109 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200110
Gilles Peskine449bd832023-01-11 14:50:10 +0100111 mbedtls_ecp_point_free(&ctx->Xm1);
112 mbedtls_ecp_point_free(&ctx->Xm2);
113 mbedtls_ecp_point_free(&ctx->Xp1);
114 mbedtls_ecp_point_free(&ctx->Xp2);
115 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 mbedtls_mpi_free(&ctx->xm1);
118 mbedtls_mpi_free(&ctx->xm2);
119 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200120}
121
122/*
123 * Setup context
124 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100125int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
126 mbedtls_ecjpake_role role,
127 mbedtls_md_type_t hash,
128 mbedtls_ecp_group_id curve,
129 const unsigned char *secret,
130 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200131{
Janos Follath24eed8d2019-11-22 13:21:35 +0000132 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000133
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
135 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
136 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200137
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200138 ctx->role = role;
139
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200140#if defined(MBEDTLS_MD_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 if ((mbedtls_md_info_from_type(hash)) == NULL) {
142 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
143 }
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200144#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) {
146 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
147 }
Neil Armstrongecaba1c2022-08-11 10:47:08 +0200148#endif
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200149
Neil Armstrong0d763412022-08-11 10:32:22 +0200150 ctx->md_type = hash;
151
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200155
156cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100157 if (ret != 0) {
158 mbedtls_ecjpake_free(ctx);
159 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200160
Gilles Peskine449bd832023-01-11 14:50:10 +0100161 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200162}
163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
165 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200166{
Gilles Peskine449bd832023-01-11 14:50:10 +0100167 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200168 case MBEDTLS_ECP_PF_UNCOMPRESSED:
169 case MBEDTLS_ECP_PF_COMPRESSED:
170 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100171 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200172 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200174 }
175}
176
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200177/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200178 * Check if context is ready for use
179 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100180int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200181{
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200183 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 ctx->s.p == NULL) {
185 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200186 }
187
Gilles Peskine449bd832023-01-11 14:50:10 +0100188 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200189}
190
191/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200192 * Write a point plus its length to a buffer
193 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100194static int ecjpake_write_len_point(unsigned char **p,
195 const unsigned char *end,
196 const mbedtls_ecp_group *grp,
197 const int pf,
198 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200199{
Janos Follath24eed8d2019-11-22 13:21:35 +0000200 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200201 size_t len;
202
203 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 if (end < *p || end - *p < 5) {
205 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
206 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207
Gilles Peskine449bd832023-01-11 14:50:10 +0100208 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
209 &len, *p + 4, end - (*p + 4));
210 if (ret != 0) {
211 return ret;
212 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200215
216 *p += 4 + len;
217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219}
220
221/*
222 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200223 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200224 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100225#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200226
227/*
228 * Compute hash for ZKP (7.4.2.2.2.1)
229 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100230static int ecjpake_hash(const mbedtls_md_type_t md_type,
231 const mbedtls_ecp_group *grp,
232 const int pf,
233 const mbedtls_ecp_point *G,
234 const mbedtls_ecp_point *V,
235 const mbedtls_ecp_point *X,
236 const char *id,
237 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200238{
Janos Follath24eed8d2019-11-22 13:21:35 +0000239 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200240 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
241 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 const unsigned char *end = buf + sizeof(buf);
243 const size_t id_len = strlen(id);
Przemek Stekiel51669542022-09-13 12:57:05 +0200244 unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200245
246 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
248 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
249 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200250
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 if (end - p < 4) {
252 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
253 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100256 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200257
Gilles Peskine449bd832023-01-11 14:50:10 +0100258 if (end < p || (size_t) (end - p) < id_len) {
259 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
260 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200261
Gilles Peskine449bd832023-01-11 14:50:10 +0100262 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200263 p += id_len;
264
265 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
267 buf, p - buf, hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200268
269 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
271 mbedtls_hash_info_get_size(md_type)));
272 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200273
274cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200276}
277
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200278/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200279 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
280 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100281static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
282 const mbedtls_ecp_group *grp,
283 const int pf,
284 const mbedtls_ecp_point *G,
285 const mbedtls_ecp_point *X,
286 const char *id,
287 const unsigned char **p,
288 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200289{
Janos Follath24eed8d2019-11-22 13:21:35 +0000290 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200291 mbedtls_ecp_point V, VV;
292 mbedtls_mpi r, h;
293 size_t r_len;
294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 mbedtls_ecp_point_init(&V);
296 mbedtls_ecp_point_init(&VV);
297 mbedtls_mpi_init(&r);
298 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299
300 /*
301 * struct {
302 * ECPoint V;
303 * opaque r<1..2^8-1>;
304 * } ECSchnorrZKP;
305 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 if (end < *p) {
307 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
308 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200313 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
314 goto cleanup;
315 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200316
317 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200318
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200320 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
321 goto cleanup;
322 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200325 *p += r_len;
326
327 /*
328 * Verification
329 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
331 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
332 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200335 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
336 goto cleanup;
337 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200338
339cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 mbedtls_ecp_point_free(&V);
341 mbedtls_ecp_point_free(&VV);
342 mbedtls_mpi_free(&r);
343 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200346}
347
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200348/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200349 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
350 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100351static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
352 const mbedtls_ecp_group *grp,
353 const int pf,
354 const mbedtls_ecp_point *G,
355 const mbedtls_mpi *x,
356 const mbedtls_ecp_point *X,
357 const char *id,
358 unsigned char **p,
359 const unsigned char *end,
360 int (*f_rng)(void *, unsigned char *, size_t),
361 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200362{
Janos Follath24eed8d2019-11-22 13:21:35 +0000363 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200364 mbedtls_ecp_point V;
365 mbedtls_mpi v;
366 mbedtls_mpi h; /* later recycled to hold r */
367 size_t len;
368
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 if (end < *p) {
370 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
371 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200372
Gilles Peskine449bd832023-01-11 14:50:10 +0100373 mbedtls_ecp_point_init(&V);
374 mbedtls_mpi_init(&v);
375 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200376
377 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
379 G, &v, &V, f_rng, p_rng));
380 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
381 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
382 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
383 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200384
385 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100386 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
387 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200388 *p += len;
389
Gilles Peskine449bd832023-01-11 14:50:10 +0100390 len = mbedtls_mpi_size(&h); /* actually r */
391 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200392 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
393 goto cleanup;
394 }
395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 *(*p)++ = MBEDTLS_BYTE_0(len);
397 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200398 *p += len;
399
400cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 mbedtls_ecp_point_free(&V);
402 mbedtls_mpi_free(&v);
403 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200404
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200406}
407
408/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200409 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
410 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200411 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100412static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
413 const mbedtls_ecp_group *grp,
414 const int pf,
415 const mbedtls_ecp_point *G,
416 mbedtls_ecp_point *X,
417 const char *id,
418 const unsigned char **p,
419 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200420{
Janos Follath24eed8d2019-11-22 13:21:35 +0000421 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 if (end < *p) {
424 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
425 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200426
427 /*
428 * struct {
429 * ECPoint X;
430 * ECSchnorrZKP zkp;
431 * } ECJPAKEKeyKP;
432 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
434 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200435 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
436 goto cleanup;
437 }
438
Gilles Peskine449bd832023-01-11 14:50:10 +0100439 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200440
441cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200443}
444
445/*
446 * Generate an ECJPAKEKeyKP
447 * Output: the serialized structure, plus private/public key pair
448 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
450 const mbedtls_ecp_group *grp,
451 const int pf,
452 const mbedtls_ecp_point *G,
453 mbedtls_mpi *x,
454 mbedtls_ecp_point *X,
455 const char *id,
456 unsigned char **p,
457 const unsigned char *end,
458 int (*f_rng)(void *, unsigned char *, size_t),
459 void *p_rng)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200460{
Janos Follath24eed8d2019-11-22 13:21:35 +0000461 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200462 size_t len;
463
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (end < *p) {
465 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
466 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200467
468 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
470 f_rng, p_rng));
471 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
472 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200473 *p += len;
474
475 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
477 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200478
479cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200481}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200482
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200483/*
484 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800485 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200486 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100487static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
488 const mbedtls_ecp_group *grp,
489 const int pf,
490 const mbedtls_ecp_point *G,
491 mbedtls_ecp_point *Xa,
492 mbedtls_ecp_point *Xb,
493 const char *id,
494 const unsigned char *buf,
495 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200496{
Janos Follath24eed8d2019-11-22 13:21:35 +0000497 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200498 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200499 const unsigned char *end = buf + len;
500
501 /*
502 * struct {
503 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
504 * } ECJPAKEKeyKPPairList;
505 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
507 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200510 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100511 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200512
513cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200515}
516
517/*
518 * Generate a ECJPAKEKeyKPPairList
519 * Outputs: the serialized structure, plus two private/public key pairs
520 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100521static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
522 const mbedtls_ecp_group *grp,
523 const int pf,
524 const mbedtls_ecp_point *G,
525 mbedtls_mpi *xm1,
526 mbedtls_ecp_point *Xa,
527 mbedtls_mpi *xm2,
528 mbedtls_ecp_point *Xb,
529 const char *id,
530 unsigned char *buf,
531 size_t len,
532 size_t *olen,
533 int (*f_rng)(void *, unsigned char *, size_t),
534 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200535{
Janos Follath24eed8d2019-11-22 13:21:35 +0000536 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200537 unsigned char *p = buf;
538 const unsigned char *end = buf + len;
539
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
541 &p, end, f_rng, p_rng));
542 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
543 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200544
545 *olen = p - buf;
546
547cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200549}
550
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200551/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200552 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200553 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100554int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
555 const unsigned char *buf,
556 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200557{
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
559 &ctx->grp.G,
560 &ctx->Xp1, &ctx->Xp2, ID_PEER,
561 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200562}
563
564/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200565 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200566 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100567int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
568 unsigned char *buf, size_t len, size_t *olen,
569 int (*f_rng)(void *, unsigned char *, size_t),
570 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200571{
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
573 &ctx->grp.G,
574 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
575 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200576}
577
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200578/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200579 * Compute the sum of three points R = A + B + C
580 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100581static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
582 const mbedtls_ecp_point *A,
583 const mbedtls_ecp_point *B,
584 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200585{
Janos Follath24eed8d2019-11-22 13:21:35 +0000586 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200587 mbedtls_mpi one;
588
Gilles Peskine449bd832023-01-11 14:50:10 +0100589 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200590
Gilles Peskine449bd832023-01-11 14:50:10 +0100591 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
592 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
593 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200594
595cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100596 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200599}
600
601/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 * 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 +0200603 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100604int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
605 const unsigned char *buf,
606 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607{
Janos Follath24eed8d2019-11-22 13:21:35 +0000608 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200609 const unsigned char *p = buf;
610 const unsigned char *end = buf + len;
611 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200612 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000613
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 mbedtls_ecp_group_init(&grp);
615 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200616
617 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200618 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
619 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
620 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200621 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200622 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
624 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200625
626 /*
627 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200628 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200629 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200630 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200631 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
633 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
634 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200635 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
636 goto cleanup;
637 }
638 }
639
Gilles Peskine449bd832023-01-11 14:50:10 +0100640 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
641 ctx->point_format,
642 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200645 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
646 goto cleanup;
647 }
648
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200649cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100650 mbedtls_ecp_group_free(&grp);
651 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200654}
655
656/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200657 * Compute R = +/- X * S mod N, taking care not to leak S
658 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100659static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
660 const mbedtls_mpi *X,
661 const mbedtls_mpi *S,
662 const mbedtls_mpi *N,
663 int (*f_rng)(void *, unsigned char *, size_t),
664 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200665{
Janos Follath24eed8d2019-11-22 13:21:35 +0000666 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200667 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
668
Gilles Peskine449bd832023-01-11 14:50:10 +0100669 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200670
671 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
673 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
674 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200675
676 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200678 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200680
681cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100682 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200683
Gilles Peskine449bd832023-01-11 14:50:10 +0100684 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200685}
686
687/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200688 * 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 +0200689 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100690int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
691 unsigned char *buf, size_t len, size_t *olen,
692 int (*f_rng)(void *, unsigned char *, size_t),
693 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200694{
Janos Follath24eed8d2019-11-22 13:21:35 +0000695 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200696 mbedtls_ecp_point G; /* C: GA, S: GB */
697 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
698 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699 unsigned char *p = buf;
700 const unsigned char *end = buf + len;
701 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000702
Gilles Peskine449bd832023-01-11 14:50:10 +0100703 mbedtls_ecp_point_init(&G);
704 mbedtls_ecp_point_init(&Xm);
705 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200706
707 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200708 * 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 +0200709 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200710 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
711 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
712 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200713 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
715 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
716 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
717 &ctx->grp.N, f_rng, p_rng));
718 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200719
720 /*
721 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200722 *
723 * struct {
724 * ECParameters curve_params; // only server writing its message
725 * ECJPAKEKeyKP ecjpake_key_kp;
726 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200727 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
729 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200730 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
731 goto cleanup;
732 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100733 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
734 p, end - p));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200735 p += ec_len;
736 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200737
Gilles Peskine449bd832023-01-11 14:50:10 +0100738 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200739 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
740 goto cleanup;
741 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100742 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
743 ctx->point_format, &ec_len, p, end - p));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200744 p += ec_len;
745
Gilles Peskine449bd832023-01-11 14:50:10 +0100746 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
747 ctx->point_format,
748 &G, &xm, &Xm, ID_MINE,
749 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200750
751 *olen = p - buf;
752
753cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100754 mbedtls_ecp_point_free(&G);
755 mbedtls_ecp_point_free(&Xm);
756 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200757
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200759}
760
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200761/*
762 * Derive PMS (7.4.2.7 / 7.4.2.8)
763 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100764static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
765 mbedtls_ecp_point *K,
766 int (*f_rng)(void *, unsigned char *, size_t),
767 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200768{
Janos Follath24eed8d2019-11-22 13:21:35 +0000769 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200770 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000771
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 mbedtls_mpi_init(&m_xm2_s);
773 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200774
Gilles Peskine449bd832023-01-11 14:50:10 +0100775 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200776
777 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200778 * Client: K = ( Xs - X4 * x2 * s ) * x2
779 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200780 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100782 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
783 &ctx->grp.N, f_rng, p_rng));
784 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
785 &one, &ctx->Xp,
786 &m_xm2_s, &ctx->Xp2));
787 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
788 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200789
Neil Armstrong12663092022-06-15 16:00:00 +0200790cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 mbedtls_mpi_free(&m_xm2_s);
792 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200793
Gilles Peskine449bd832023-01-11 14:50:10 +0100794 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200795}
796
Gilles Peskine449bd832023-01-11 14:50:10 +0100797int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
798 unsigned char *buf, size_t len, size_t *olen,
799 int (*f_rng)(void *, unsigned char *, size_t),
800 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200801{
802 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
803 mbedtls_ecp_point K;
804 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
805 size_t x_bytes;
806
Gilles Peskine449bd832023-01-11 14:50:10 +0100807 *olen = mbedtls_hash_info_get_size(ctx->md_type);
808 if (len < *olen) {
809 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
810 }
Neil Armstrong12663092022-06-15 16:00:00 +0200811
Gilles Peskine449bd832023-01-11 14:50:10 +0100812 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200813
814 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200816 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 }
Neil Armstrong12663092022-06-15 16:00:00 +0200818
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200819 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 x_bytes = (ctx->grp.pbits + 7) / 8;
821 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
822 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
823 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200824
825cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100826 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200827
Gilles Peskine449bd832023-01-11 14:50:10 +0100828 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200829}
830
Gilles Peskine449bd832023-01-11 14:50:10 +0100831int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
832 unsigned char *buf, size_t len, size_t *olen,
833 int (*f_rng)(void *, unsigned char *, size_t),
834 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200835{
836 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
837 mbedtls_ecp_point K;
838
Gilles Peskine449bd832023-01-11 14:50:10 +0100839 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200840
841 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100842 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200843 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100844 }
Neil Armstrong12663092022-06-15 16:00:00 +0200845
Gilles Peskine449bd832023-01-11 14:50:10 +0100846 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
847 olen, buf, len);
848 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200849 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100850 }
Neil Armstrong12663092022-06-15 16:00:00 +0200851
852cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100853 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200854
Gilles Peskine449bd832023-01-11 14:50:10 +0100855 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200856}
857
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200858#undef ID_MINE
859#undef ID_PEER
860
Hanno Becker616d1ca2018-01-24 10:25:05 +0000861#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200862
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200863#if defined(MBEDTLS_SELF_TEST)
864
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200865#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200866
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200867#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
868 !defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100869int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200870{
871 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100872 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200873}
874#else
875
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200876static const unsigned char ecjpake_test_password[] = {
877 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
878 0x65, 0x73, 0x74
879};
880
Steven Cooreman64f27732021-01-11 17:20:10 +0100881#if !defined(MBEDTLS_ECJPAKE_ALT)
882
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200883static const unsigned char ecjpake_test_x1[] = {
884 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
885 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
886 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
887};
888
889static const unsigned char ecjpake_test_x2[] = {
890 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
891 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
892 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
893};
894
895static const unsigned char ecjpake_test_x3[] = {
896 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
897 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
898 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
899};
900
901static const unsigned char ecjpake_test_x4[] = {
902 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
903 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
904 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
905};
906
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200907static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200908 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
909 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
910 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
911 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
912 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
913 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
914 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
915 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
916 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
917 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
918 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
919 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
920 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200921 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
922 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
923 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
924 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
925 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
926 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
927 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
928 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
929 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
930 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
931 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
932 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
933 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
934 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
935 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200936};
937
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200938static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200939 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
940 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
941 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
942 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
943 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
944 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
945 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
946 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
947 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
948 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
949 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
950 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
951 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
952 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
953 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
954 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
955 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
956 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
957 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
958 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
959 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
960 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
961 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
962 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
963 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
964 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
965 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
966 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
967};
968
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200969static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200970 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
971 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
972 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
973 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
974 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
975 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
976 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
977 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
978 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
979 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
980 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
981 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
982 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
983 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
984};
985
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200986static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200987 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
988 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
989 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
990 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
991 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
992 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
993 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
994 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
995 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
996 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
997 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
998 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
999 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
1000 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
1001};
1002
Neil Armstrong12663092022-06-15 16:00:00 +02001003static const unsigned char ecjpake_test_shared_key[] = {
1004 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
1005 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
1006 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
1007 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
1008 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
1009 0x17, 0xc3, 0xde, 0x27, 0xb4,
1010};
1011
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001012static const unsigned char ecjpake_test_pms[] = {
1013 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
1014 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
1015 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
1016};
1017
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001018/*
1019 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
1020 *
1021 * This is the linear congruential generator from numerical recipes,
1022 * except we only use the low byte as the output. See
1023 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
1024 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001025static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001026{
1027 static uint32_t state = 42;
1028
1029 (void) ctx;
1030
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001032 state = state * 1664525u + 1013904223u;
1033 out[i] = (unsigned char) state;
1034 }
1035
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001037}
1038
Antonin Décimo36e89b52019-01-23 15:24:37 +01001039/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +01001040static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1041 const unsigned char *xm1, size_t len1,
1042 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001043{
Janos Follath24eed8d2019-11-22 13:21:35 +00001044 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001045
Gilles Peskine449bd832023-01-11 14:50:10 +01001046 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1047 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1048 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1049 &ctx->grp.G, self_test_rng, NULL));
1050 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1051 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001052
1053cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001054 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001055}
1056
Steven Cooreman64f27732021-01-11 17:20:10 +01001057#endif /* ! MBEDTLS_ECJPAKE_ALT */
1058
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001059/* For tests we don't need a secure RNG;
1060 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001061static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001062{
1063 static uint32_t x = 42;
1064 (void) p;
1065
Gilles Peskine449bd832023-01-11 14:50:10 +01001066 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001067 size_t use_len = len > 4 ? 4 : len;
1068 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001069 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001070 out += use_len;
1071 len -= use_len;
1072 }
1073
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001075}
1076
Gilles Peskine449bd832023-01-11 14:50:10 +01001077#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001078 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001079 if (x) \
1080 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001081 else \
1082 { \
1083 ret = 1; \
1084 goto cleanup; \
1085 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001087
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001088/*
1089 * Checkup routine
1090 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001091int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001092{
Janos Follath24eed8d2019-11-22 13:21:35 +00001093 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001094 mbedtls_ecjpake_context cli;
1095 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001096 unsigned char buf[512], pms[32];
1097 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001098
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 mbedtls_ecjpake_init(&cli);
1100 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001101
Gilles Peskine449bd832023-01-11 14:50:10 +01001102 if (verbose != 0) {
1103 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1104 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1107 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1108 ecjpake_test_password,
1109 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001110
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1112 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1113 ecjpake_test_password,
1114 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001115
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 if (verbose != 0) {
1117 mbedtls_printf("passed\n");
1118 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001119
Gilles Peskine449bd832023-01-11 14:50:10 +01001120 if (verbose != 0) {
1121 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1122 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001123
Gilles Peskine449bd832023-01-11 14:50:10 +01001124 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1125 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001126
Gilles Peskine449bd832023-01-11 14:50:10 +01001127 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
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(&srv,
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(&cli, 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_two(&srv,
1135 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001136
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001138
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1140 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001141
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1143 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001144
Gilles Peskine449bd832023-01-11 14:50:10 +01001145 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001146
Gilles Peskine449bd832023-01-11 14:50:10 +01001147 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1148 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001149
Gilles Peskine449bd832023-01-11 14:50:10 +01001150 TEST_ASSERT(len == pmslen);
1151 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001152
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 if (verbose != 0) {
1154 mbedtls_printf("passed\n");
1155 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001156
Steven Cooreman64f27732021-01-11 17:20:10 +01001157#if !defined(MBEDTLS_ECJPAKE_ALT)
1158 /* 'reference handshake' tests can only be run against implementations
1159 * for which we have 100% control over how the random ephemeral keys
1160 * are generated. This is only the case for the internal mbed TLS
1161 * implementation, so these tests are skipped in case the internal
1162 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001163 if (verbose != 0) {
1164 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1165 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001166
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001167 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001168 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1169 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1170 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001171
Gilles Peskine449bd832023-01-11 14:50:10 +01001172 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1173 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1174 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001175
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001176 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1178 ecjpake_test_cli_one,
1179 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001180
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1182 ecjpake_test_srv_one,
1183 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001184
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001185 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1187 ecjpake_test_srv_two,
1188 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001189
Gilles Peskine449bd832023-01-11 14:50:10 +01001190 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1191 ecjpake_test_cli_two,
1192 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001193
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001194 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1196 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001197
Gilles Peskine449bd832023-01-11 14:50:10 +01001198 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1199 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001200
Neil Armstrong12663092022-06-15 16:00:00 +02001201 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001202 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1203 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001204
Gilles Peskine449bd832023-01-11 14:50:10 +01001205 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1206 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001207
Gilles Peskine449bd832023-01-11 14:50:10 +01001208 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001209
1210 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001211 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1212 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001213
Gilles Peskine449bd832023-01-11 14:50:10 +01001214 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1215 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001216
Neil Armstrong12663092022-06-15 16:00:00 +02001217 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001218 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1219 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001220
Gilles Peskine449bd832023-01-11 14:50:10 +01001221 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1222 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001223
Gilles Peskine449bd832023-01-11 14:50:10 +01001224 if (verbose != 0) {
1225 mbedtls_printf("passed\n");
1226 }
Steven Cooreman64f27732021-01-11 17:20:10 +01001227#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001228
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001229cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001230 mbedtls_ecjpake_free(&cli);
1231 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001232
Gilles Peskine449bd832023-01-11 14:50:10 +01001233 if (ret != 0) {
1234 if (verbose != 0) {
1235 mbedtls_printf("failed\n");
1236 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001237
1238 ret = 1;
1239 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001240
Gilles Peskine449bd832023-01-11 14:50:10 +01001241 if (verbose != 0) {
1242 mbedtls_printf("\n");
1243 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001244
Gilles Peskine449bd832023-01-11 14:50:10 +01001245 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001246}
1247
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001248#undef TEST_ASSERT
1249
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001250#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
1251
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001252#endif /* MBEDTLS_SELF_TEST */
1253
1254#endif /* MBEDTLS_ECJPAKE_C */