blob: 6f448b0301cefd499e921d06ddce9bacba822990 [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 Armstrong0d763412022-08-11 10:32:22 +020033#include "hash_info.h"
34
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020035#include <string.h>
36
Hanno Becker616d1ca2018-01-24 10:25:05 +000037#if !defined(MBEDTLS_ECJPAKE_ALT)
38
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020039/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020040 * Convert a mbedtls_ecjpake_role to identifier string
41 */
42static const char * const ecjpake_id[] = {
43 "client",
44 "server"
45};
46
Gilles Peskine449bd832023-01-11 14:50:10 +010047#define ID_MINE (ecjpake_id[ctx->role])
48#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020049
Neil Armstrongecaba1c2022-08-11 10:47:08 +020050/**
Gilles Peskine449bd832023-01-11 14:50:10 +010051 * Helper to Compute a hash from md_type
52 */
53static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
54 const unsigned char *input, size_t ilen,
55 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020056{
Gilles Peskine449bd832023-01-11 14:50:10 +010057 return mbedtls_md(mbedtls_md_info_from_type(md_type),
58 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020059}
60
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020061/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020062 * Initialize context
63 */
Gilles Peskine449bd832023-01-11 14:50:10 +010064void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020065{
Neil Armstrong0d763412022-08-11 10:32:22 +020066 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010067 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020068 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020069
Gilles Peskine449bd832023-01-11 14:50:10 +010070 mbedtls_ecp_point_init(&ctx->Xm1);
71 mbedtls_ecp_point_init(&ctx->Xm2);
72 mbedtls_ecp_point_init(&ctx->Xp1);
73 mbedtls_ecp_point_init(&ctx->Xp2);
74 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020075
Gilles Peskine449bd832023-01-11 14:50:10 +010076 mbedtls_mpi_init(&ctx->xm1);
77 mbedtls_mpi_init(&ctx->xm2);
78 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020079}
80
81/*
82 * Free context
83 */
Gilles Peskine449bd832023-01-11 14:50:10 +010084void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020085{
Gilles Peskine449bd832023-01-11 14:50:10 +010086 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020087 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010088 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020089
Neil Armstrong0d763412022-08-11 10:32:22 +020090 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010091 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020092
Gilles Peskine449bd832023-01-11 14:50:10 +010093 mbedtls_ecp_point_free(&ctx->Xm1);
94 mbedtls_ecp_point_free(&ctx->Xm2);
95 mbedtls_ecp_point_free(&ctx->Xp1);
96 mbedtls_ecp_point_free(&ctx->Xp2);
97 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 mbedtls_mpi_free(&ctx->xm1);
100 mbedtls_mpi_free(&ctx->xm2);
101 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200102}
103
104/*
105 * Setup context
106 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100107int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
108 mbedtls_ecjpake_role role,
109 mbedtls_md_type_t hash,
110 mbedtls_ecp_group_id curve,
111 const unsigned char *secret,
112 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200113{
Janos Follath24eed8d2019-11-22 13:21:35 +0000114 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
117 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
118 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200119
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200120 ctx->role = role;
121
Gilles Peskine449bd832023-01-11 14:50:10 +0100122 if ((mbedtls_md_info_from_type(hash)) == NULL) {
123 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
124 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200125
Neil Armstrong0d763412022-08-11 10:32:22 +0200126 ctx->md_type = hash;
127
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200131
132cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 if (ret != 0) {
134 mbedtls_ecjpake_free(ctx);
135 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200138}
139
Gilles Peskine449bd832023-01-11 14:50:10 +0100140int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
141 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200142{
Gilles Peskine449bd832023-01-11 14:50:10 +0100143 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200144 case MBEDTLS_ECP_PF_UNCOMPRESSED:
145 case MBEDTLS_ECP_PF_COMPRESSED:
146 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200148 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200150 }
151}
152
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200153/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200154 * Check if context is ready for use
155 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100156int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200157{
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200159 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 ctx->s.p == NULL) {
161 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200162 }
163
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200165}
166
167/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200168 * Write a point plus its length to a buffer
169 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100170static int ecjpake_write_len_point(unsigned char **p,
171 const unsigned char *end,
172 const mbedtls_ecp_group *grp,
173 const int pf,
174 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200175{
Janos Follath24eed8d2019-11-22 13:21:35 +0000176 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200177 size_t len;
178
179 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 if (end < *p || end - *p < 5) {
181 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
182 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200183
Gilles Peskine449bd832023-01-11 14:50:10 +0100184 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
185 &len, *p + 4, end - (*p + 4));
186 if (ret != 0) {
187 return ret;
188 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200191
192 *p += 4 + len;
193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200195}
196
197/*
198 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200199 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100201#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200202
203/*
204 * Compute hash for ZKP (7.4.2.2.2.1)
205 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100206static int ecjpake_hash(const mbedtls_md_type_t md_type,
207 const mbedtls_ecp_group *grp,
208 const int pf,
209 const mbedtls_ecp_point *G,
210 const mbedtls_ecp_point *V,
211 const mbedtls_ecp_point *X,
212 const char *id,
213 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214{
Janos Follath24eed8d2019-11-22 13:21:35 +0000215 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
217 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 const unsigned char *end = buf + sizeof(buf);
219 const size_t id_len = strlen(id);
Przemek Stekiel51669542022-09-13 12:57:05 +0200220 unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200221
222 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100223 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
224 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
225 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 if (end - p < 4) {
228 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
229 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100232 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200233
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 if (end < p || (size_t) (end - p) < id_len) {
235 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
236 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200237
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200239 p += id_len;
240
241 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
243 buf, p - buf, hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200244
245 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200247 mbedtls_md_get_size_from_type(md_type)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200249
250cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200252}
253
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200254/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200255 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100257static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
258 const mbedtls_ecp_group *grp,
259 const int pf,
260 const mbedtls_ecp_point *G,
261 const mbedtls_ecp_point *X,
262 const char *id,
263 const unsigned char **p,
264 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200265{
Janos Follath24eed8d2019-11-22 13:21:35 +0000266 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200267 mbedtls_ecp_point V, VV;
268 mbedtls_mpi r, h;
269 size_t r_len;
270
Gilles Peskine449bd832023-01-11 14:50:10 +0100271 mbedtls_ecp_point_init(&V);
272 mbedtls_ecp_point_init(&VV);
273 mbedtls_mpi_init(&r);
274 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200275
276 /*
277 * struct {
278 * ECPoint V;
279 * opaque r<1..2^8-1>;
280 * } ECSchnorrZKP;
281 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100282 if (end < *p) {
283 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
284 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200287
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200289 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290 goto cleanup;
291 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200292
293 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200296 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
297 goto cleanup;
298 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200301 *p += r_len;
302
303 /*
304 * Verification
305 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100306 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
307 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
308 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200309
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200311 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
312 goto cleanup;
313 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200314
315cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100316 mbedtls_ecp_point_free(&V);
317 mbedtls_ecp_point_free(&VV);
318 mbedtls_mpi_free(&r);
319 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200320
Gilles Peskine449bd832023-01-11 14:50:10 +0100321 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200322}
323
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200324/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200325 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
326 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100327static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
328 const mbedtls_ecp_group *grp,
329 const int pf,
330 const mbedtls_ecp_point *G,
331 const mbedtls_mpi *x,
332 const mbedtls_ecp_point *X,
333 const char *id,
334 unsigned char **p,
335 const unsigned char *end,
336 int (*f_rng)(void *, unsigned char *, size_t),
337 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200338{
Janos Follath24eed8d2019-11-22 13:21:35 +0000339 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200340 mbedtls_ecp_point V;
341 mbedtls_mpi v;
342 mbedtls_mpi h; /* later recycled to hold r */
343 size_t len;
344
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 if (end < *p) {
346 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
347 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 mbedtls_ecp_point_init(&V);
350 mbedtls_mpi_init(&v);
351 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200352
353 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
355 G, &v, &V, f_rng, p_rng));
356 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
357 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
358 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
359 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200360
361 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100362 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
363 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200364 *p += len;
365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 len = mbedtls_mpi_size(&h); /* actually r */
367 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200368 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
369 goto cleanup;
370 }
371
Gilles Peskine449bd832023-01-11 14:50:10 +0100372 *(*p)++ = MBEDTLS_BYTE_0(len);
373 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200374 *p += len;
375
376cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100377 mbedtls_ecp_point_free(&V);
378 mbedtls_mpi_free(&v);
379 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200380
Gilles Peskine449bd832023-01-11 14:50:10 +0100381 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200382}
383
384/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200385 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
386 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200387 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100388static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
389 const mbedtls_ecp_group *grp,
390 const int pf,
391 const mbedtls_ecp_point *G,
392 mbedtls_ecp_point *X,
393 const char *id,
394 const unsigned char **p,
395 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200396{
Janos Follath24eed8d2019-11-22 13:21:35 +0000397 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 if (end < *p) {
400 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
401 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200402
403 /*
404 * struct {
405 * ECPoint X;
406 * ECSchnorrZKP zkp;
407 * } ECJPAKEKeyKP;
408 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
410 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200411 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
412 goto cleanup;
413 }
414
Gilles Peskine449bd832023-01-11 14:50:10 +0100415 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200416
417cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100418 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200419}
420
421/*
422 * Generate an ECJPAKEKeyKP
423 * Output: the serialized structure, plus private/public key pair
424 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100425static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
426 const mbedtls_ecp_group *grp,
427 const int pf,
428 const mbedtls_ecp_point *G,
429 mbedtls_mpi *x,
430 mbedtls_ecp_point *X,
431 const char *id,
432 unsigned char **p,
433 const unsigned char *end,
434 int (*f_rng)(void *, unsigned char *, size_t),
435 void *p_rng)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200436{
Janos Follath24eed8d2019-11-22 13:21:35 +0000437 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200438 size_t len;
439
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 if (end < *p) {
441 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
442 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200443
444 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100445 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
446 f_rng, p_rng));
447 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
448 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200449 *p += len;
450
451 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100452 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
453 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200454
455cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200457}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200458
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200459/*
460 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800461 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200462 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100463static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
464 const mbedtls_ecp_group *grp,
465 const int pf,
466 const mbedtls_ecp_point *G,
467 mbedtls_ecp_point *Xa,
468 mbedtls_ecp_point *Xb,
469 const char *id,
470 const unsigned char *buf,
471 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472{
Janos Follath24eed8d2019-11-22 13:21:35 +0000473 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200474 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200475 const unsigned char *end = buf + len;
476
477 /*
478 * struct {
479 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
480 * } ECJPAKEKeyKPPairList;
481 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100482 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
483 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200484
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200486 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200488
489cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200491}
492
493/*
494 * Generate a ECJPAKEKeyKPPairList
495 * Outputs: the serialized structure, plus two private/public key pairs
496 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100497static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
498 const mbedtls_ecp_group *grp,
499 const int pf,
500 const mbedtls_ecp_point *G,
501 mbedtls_mpi *xm1,
502 mbedtls_ecp_point *Xa,
503 mbedtls_mpi *xm2,
504 mbedtls_ecp_point *Xb,
505 const char *id,
506 unsigned char *buf,
507 size_t len,
508 size_t *olen,
509 int (*f_rng)(void *, unsigned char *, size_t),
510 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200511{
Janos Follath24eed8d2019-11-22 13:21:35 +0000512 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200513 unsigned char *p = buf;
514 const unsigned char *end = buf + len;
515
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
517 &p, end, f_rng, p_rng));
518 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
519 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200520
521 *olen = p - buf;
522
523cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100524 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200525}
526
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200527/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200528 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200529 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100530int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
531 const unsigned char *buf,
532 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200533{
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
535 &ctx->grp.G,
536 &ctx->Xp1, &ctx->Xp2, ID_PEER,
537 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200538}
539
540/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200541 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200542 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100543int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
544 unsigned char *buf, size_t len, size_t *olen,
545 int (*f_rng)(void *, unsigned char *, size_t),
546 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200547{
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
549 &ctx->grp.G,
550 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
551 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200552}
553
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200554/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200555 * Compute the sum of three points R = A + B + C
556 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100557static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
558 const mbedtls_ecp_point *A,
559 const mbedtls_ecp_point *B,
560 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200561{
Janos Follath24eed8d2019-11-22 13:21:35 +0000562 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200563 mbedtls_mpi one;
564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200566
Gilles Peskine449bd832023-01-11 14:50:10 +0100567 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
568 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
569 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200570
571cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200575}
576
577/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578 * 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 +0200579 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100580int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
581 const unsigned char *buf,
582 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583{
Janos Follath24eed8d2019-11-22 13:21:35 +0000584 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200585 const unsigned char *p = buf;
586 const unsigned char *end = buf + len;
587 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200588 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000589
Gilles Peskine449bd832023-01-11 14:50:10 +0100590 mbedtls_ecp_group_init(&grp);
591 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200592
593 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200594 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
595 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
596 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200597 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200598 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100599 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
600 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200601
602 /*
603 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200606 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100608 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
609 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
610 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200611 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
612 goto cleanup;
613 }
614 }
615
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
617 ctx->point_format,
618 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200619
Gilles Peskine449bd832023-01-11 14:50:10 +0100620 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200621 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
622 goto cleanup;
623 }
624
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200625cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100626 mbedtls_ecp_group_free(&grp);
627 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200630}
631
632/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200633 * Compute R = +/- X * S mod N, taking care not to leak S
634 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100635static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
636 const mbedtls_mpi *X,
637 const mbedtls_mpi *S,
638 const mbedtls_mpi *N,
639 int (*f_rng)(void *, unsigned char *, size_t),
640 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200641{
Janos Follath24eed8d2019-11-22 13:21:35 +0000642 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200643 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200646
647 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100648 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
649 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
650 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200651
652 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200654 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100655 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200656
657cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200659
Gilles Peskine449bd832023-01-11 14:50:10 +0100660 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200661}
662
663/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200664 * 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 +0200665 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100666int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
667 unsigned char *buf, size_t len, size_t *olen,
668 int (*f_rng)(void *, unsigned char *, size_t),
669 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200670{
Janos Follath24eed8d2019-11-22 13:21:35 +0000671 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200672 mbedtls_ecp_point G; /* C: GA, S: GB */
673 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
674 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200675 unsigned char *p = buf;
676 const unsigned char *end = buf + len;
677 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000678
Gilles Peskine449bd832023-01-11 14:50:10 +0100679 mbedtls_ecp_point_init(&G);
680 mbedtls_ecp_point_init(&Xm);
681 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200682
683 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 * 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 +0200685 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200686 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
687 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
688 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100690 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
691 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
692 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
693 &ctx->grp.N, f_rng, p_rng));
694 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200695
696 /*
697 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200698 *
699 * struct {
700 * ECParameters curve_params; // only server writing its message
701 * ECJPAKEKeyKP ecjpake_key_kp;
702 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200703 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
705 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200706 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
707 goto cleanup;
708 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100709 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
710 p, end - p));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200711 p += ec_len;
712 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200713
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200715 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
716 goto cleanup;
717 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
719 ctx->point_format, &ec_len, p, end - p));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200720 p += ec_len;
721
Gilles Peskine449bd832023-01-11 14:50:10 +0100722 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
723 ctx->point_format,
724 &G, &xm, &Xm, ID_MINE,
725 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200726
727 *olen = p - buf;
728
729cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100730 mbedtls_ecp_point_free(&G);
731 mbedtls_ecp_point_free(&Xm);
732 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200735}
736
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200737/*
738 * Derive PMS (7.4.2.7 / 7.4.2.8)
739 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100740static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
741 mbedtls_ecp_point *K,
742 int (*f_rng)(void *, unsigned char *, size_t),
743 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200744{
Janos Follath24eed8d2019-11-22 13:21:35 +0000745 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200746 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000747
Gilles Peskine449bd832023-01-11 14:50:10 +0100748 mbedtls_mpi_init(&m_xm2_s);
749 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200750
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200752
753 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200754 * Client: K = ( Xs - X4 * x2 * s ) * x2
755 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200756 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200757 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100758 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
759 &ctx->grp.N, f_rng, p_rng));
760 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
761 &one, &ctx->Xp,
762 &m_xm2_s, &ctx->Xp2));
763 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
764 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200765
Neil Armstrong12663092022-06-15 16:00:00 +0200766cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100767 mbedtls_mpi_free(&m_xm2_s);
768 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200769
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200771}
772
Gilles Peskine449bd832023-01-11 14:50:10 +0100773int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
774 unsigned char *buf, size_t len, size_t *olen,
775 int (*f_rng)(void *, unsigned char *, size_t),
776 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200777{
778 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
779 mbedtls_ecp_point K;
780 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
781 size_t x_bytes;
782
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200783 *olen = mbedtls_md_get_size_from_type(ctx->md_type);
Gilles Peskine449bd832023-01-11 14:50:10 +0100784 if (len < *olen) {
785 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
786 }
Neil Armstrong12663092022-06-15 16:00:00 +0200787
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200789
790 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200792 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100793 }
Neil Armstrong12663092022-06-15 16:00:00 +0200794
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200795 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100796 x_bytes = (ctx->grp.pbits + 7) / 8;
797 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
798 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
799 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200800
801cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100802 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200803
Gilles Peskine449bd832023-01-11 14:50:10 +0100804 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200805}
806
Gilles Peskine449bd832023-01-11 14:50:10 +0100807int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
808 unsigned char *buf, size_t len, size_t *olen,
809 int (*f_rng)(void *, unsigned char *, size_t),
810 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200811{
812 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
813 mbedtls_ecp_point K;
814
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200816
817 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100818 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200819 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 }
Neil Armstrong12663092022-06-15 16:00:00 +0200821
Gilles Peskine449bd832023-01-11 14:50:10 +0100822 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
823 olen, buf, len);
824 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200825 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100826 }
Neil Armstrong12663092022-06-15 16:00:00 +0200827
828cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100829 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200830
Gilles Peskine449bd832023-01-11 14:50:10 +0100831 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200832}
833
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200834#undef ID_MINE
835#undef ID_PEER
836
Hanno Becker616d1ca2018-01-24 10:25:05 +0000837#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200838
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200839#if defined(MBEDTLS_SELF_TEST)
840
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200841#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200842
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200843#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +0100844 !defined(MBEDTLS_MD_CAN_SHA256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100845int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200846{
847 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100848 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200849}
850#else
851
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200852static const unsigned char ecjpake_test_password[] = {
853 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
854 0x65, 0x73, 0x74
855};
856
Steven Cooreman64f27732021-01-11 17:20:10 +0100857#if !defined(MBEDTLS_ECJPAKE_ALT)
858
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200859static const unsigned char ecjpake_test_x1[] = {
860 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
861 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
862 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
863};
864
865static const unsigned char ecjpake_test_x2[] = {
866 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
867 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
868 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
869};
870
871static const unsigned char ecjpake_test_x3[] = {
872 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
873 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
874 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
875};
876
877static const unsigned char ecjpake_test_x4[] = {
878 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
879 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
880 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
881};
882
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200883static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200884 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
885 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
886 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
887 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
888 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
889 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
890 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
891 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
892 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
893 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
894 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
895 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
896 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200897 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
898 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
899 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
900 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
901 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
902 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
903 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
904 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
905 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
906 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
907 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
908 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
909 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
910 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
911 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200912};
913
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200914static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200915 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
916 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
917 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
918 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
919 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
920 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
921 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
922 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
923 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
924 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
925 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
926 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
927 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
928 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
929 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
930 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
931 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
932 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
933 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
934 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
935 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
936 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
937 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
938 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
939 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
940 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
941 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
942 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
943};
944
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200945static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200946 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
947 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
948 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
949 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
950 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
951 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
952 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
953 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
954 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
955 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
956 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
957 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
958 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
959 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
960};
961
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200962static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200963 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
964 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
965 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
966 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
967 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
968 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
969 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
970 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
971 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
972 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
973 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
974 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
975 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
976 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
977};
978
Neil Armstrong12663092022-06-15 16:00:00 +0200979static const unsigned char ecjpake_test_shared_key[] = {
980 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
981 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
982 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
983 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
984 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
985 0x17, 0xc3, 0xde, 0x27, 0xb4,
986};
987
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200988static const unsigned char ecjpake_test_pms[] = {
989 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
990 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
991 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
992};
993
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200994/*
995 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
996 *
997 * This is the linear congruential generator from numerical recipes,
998 * except we only use the low byte as the output. See
999 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
1000 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001001static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001002{
1003 static uint32_t state = 42;
1004
1005 (void) ctx;
1006
Gilles Peskine449bd832023-01-11 14:50:10 +01001007 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001008 state = state * 1664525u + 1013904223u;
1009 out[i] = (unsigned char) state;
1010 }
1011
Gilles Peskine449bd832023-01-11 14:50:10 +01001012 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001013}
1014
Antonin Décimo36e89b52019-01-23 15:24:37 +01001015/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +01001016static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1017 const unsigned char *xm1, size_t len1,
1018 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001019{
Janos Follath24eed8d2019-11-22 13:21:35 +00001020 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001021
Gilles Peskine449bd832023-01-11 14:50:10 +01001022 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1023 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1024 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1025 &ctx->grp.G, self_test_rng, NULL));
1026 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1027 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001028
1029cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001030 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001031}
1032
Steven Cooreman64f27732021-01-11 17:20:10 +01001033#endif /* ! MBEDTLS_ECJPAKE_ALT */
1034
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001035/* For tests we don't need a secure RNG;
1036 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001037static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001038{
1039 static uint32_t x = 42;
1040 (void) p;
1041
Gilles Peskine449bd832023-01-11 14:50:10 +01001042 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001043 size_t use_len = len > 4 ? 4 : len;
1044 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001045 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001046 out += use_len;
1047 len -= use_len;
1048 }
1049
Gilles Peskine449bd832023-01-11 14:50:10 +01001050 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001051}
1052
Gilles Peskine449bd832023-01-11 14:50:10 +01001053#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001054 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001055 if (x) \
1056 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001057 else \
1058 { \
1059 ret = 1; \
1060 goto cleanup; \
1061 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001062 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001063
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001064/*
1065 * Checkup routine
1066 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001067int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001068{
Janos Follath24eed8d2019-11-22 13:21:35 +00001069 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001070 mbedtls_ecjpake_context cli;
1071 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001072 unsigned char buf[512], pms[32];
1073 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001074
Gilles Peskine449bd832023-01-11 14:50:10 +01001075 mbedtls_ecjpake_init(&cli);
1076 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001077
Gilles Peskine449bd832023-01-11 14:50:10 +01001078 if (verbose != 0) {
1079 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1080 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1083 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1084 ecjpake_test_password,
1085 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001086
Gilles Peskine449bd832023-01-11 14:50:10 +01001087 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1088 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1089 ecjpake_test_password,
1090 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001091
Gilles Peskine449bd832023-01-11 14:50:10 +01001092 if (verbose != 0) {
1093 mbedtls_printf("passed\n");
1094 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001095
Gilles Peskine449bd832023-01-11 14:50:10 +01001096 if (verbose != 0) {
1097 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1098 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001099
Gilles Peskine449bd832023-01-11 14:50:10 +01001100 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1101 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001102
Gilles Peskine449bd832023-01-11 14:50:10 +01001103 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001104
Gilles Peskine449bd832023-01-11 14:50:10 +01001105 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1106 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001107
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001109
Gilles Peskine449bd832023-01-11 14:50:10 +01001110 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1111 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001114
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1116 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001117
Gilles Peskine449bd832023-01-11 14:50:10 +01001118 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1119 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001120
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001122
Gilles Peskine449bd832023-01-11 14:50:10 +01001123 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1124 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001125
Gilles Peskine449bd832023-01-11 14:50:10 +01001126 TEST_ASSERT(len == pmslen);
1127 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001128
Gilles Peskine449bd832023-01-11 14:50:10 +01001129 if (verbose != 0) {
1130 mbedtls_printf("passed\n");
1131 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001132
Steven Cooreman64f27732021-01-11 17:20:10 +01001133#if !defined(MBEDTLS_ECJPAKE_ALT)
1134 /* 'reference handshake' tests can only be run against implementations
1135 * for which we have 100% control over how the random ephemeral keys
1136 * are generated. This is only the case for the internal mbed TLS
1137 * implementation, so these tests are skipped in case the internal
1138 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 if (verbose != 0) {
1140 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1141 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001142
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001143 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001144 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1145 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1146 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001147
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1149 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1150 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001151
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001152 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001153 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1154 ecjpake_test_cli_one,
1155 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001156
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1158 ecjpake_test_srv_one,
1159 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001160
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001161 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001162 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1163 ecjpake_test_srv_two,
1164 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001165
Gilles Peskine449bd832023-01-11 14:50:10 +01001166 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1167 ecjpake_test_cli_two,
1168 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001169
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001170 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001171 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1172 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001173
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1175 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001176
Neil Armstrong12663092022-06-15 16:00:00 +02001177 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001178 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1179 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001180
Gilles Peskine449bd832023-01-11 14:50:10 +01001181 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1182 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001183
Gilles Peskine449bd832023-01-11 14:50:10 +01001184 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001185
1186 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001187 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1188 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001189
Gilles Peskine449bd832023-01-11 14:50:10 +01001190 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1191 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001192
Neil Armstrong12663092022-06-15 16:00:00 +02001193 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001194 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1195 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001196
Gilles Peskine449bd832023-01-11 14:50:10 +01001197 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1198 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001199
Gilles Peskine449bd832023-01-11 14:50:10 +01001200 if (verbose != 0) {
1201 mbedtls_printf("passed\n");
1202 }
Steven Cooreman64f27732021-01-11 17:20:10 +01001203#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001204
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001205cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001206 mbedtls_ecjpake_free(&cli);
1207 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001208
Gilles Peskine449bd832023-01-11 14:50:10 +01001209 if (ret != 0) {
1210 if (verbose != 0) {
1211 mbedtls_printf("failed\n");
1212 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001213
1214 ret = 1;
1215 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001216
Gilles Peskine449bd832023-01-11 14:50:10 +01001217 if (verbose != 0) {
1218 mbedtls_printf("\n");
1219 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001220
Gilles Peskine449bd832023-01-11 14:50:10 +01001221 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001222}
1223
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001224#undef TEST_ASSERT
1225
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +01001226#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001227
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001228#endif /* MBEDTLS_SELF_TEST */
1229
1230#endif /* MBEDTLS_ECJPAKE_C */