blob: 628fb65a59f78cdb10dbfc8ab28b96402442af18 [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
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02006 */
7
8/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +02009 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020010 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020011 */
12
Gilles Peskinedb09ef62020-06-03 01:43:33 +020013#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020014
15#if defined(MBEDTLS_ECJPAKE_C)
16
17#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000018#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000019#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020020
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020021#include <string.h>
22
23/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020024 * Convert a mbedtls_ecjpake_role to identifier string
25 */
26static const char * const ecjpake_id[] = {
27 "client",
28 "server"
29};
30
Gilles Peskine449bd832023-01-11 14:50:10 +010031#define ID_MINE (ecjpake_id[ctx->role])
32#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020033
Neil Armstrongecaba1c2022-08-11 10:47:08 +020034/**
Gilles Peskine449bd832023-01-11 14:50:10 +010035 * Helper to Compute a hash from md_type
36 */
37static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
38 const unsigned char *input, size_t ilen,
39 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020040{
Gilles Peskine449bd832023-01-11 14:50:10 +010041 return mbedtls_md(mbedtls_md_info_from_type(md_type),
42 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020043}
44
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020045/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020046 * Initialize context
47 */
Gilles Peskine449bd832023-01-11 14:50:10 +010048void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020049{
Neil Armstrong0d763412022-08-11 10:32:22 +020050 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010051 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020052 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020053
Gilles Peskine449bd832023-01-11 14:50:10 +010054 mbedtls_ecp_point_init(&ctx->Xm1);
55 mbedtls_ecp_point_init(&ctx->Xm2);
56 mbedtls_ecp_point_init(&ctx->Xp1);
57 mbedtls_ecp_point_init(&ctx->Xp2);
58 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020059
Gilles Peskine449bd832023-01-11 14:50:10 +010060 mbedtls_mpi_init(&ctx->xm1);
61 mbedtls_mpi_init(&ctx->xm2);
62 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020063}
64
65/*
66 * Free context
67 */
Gilles Peskine449bd832023-01-11 14:50:10 +010068void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020069{
Gilles Peskine449bd832023-01-11 14:50:10 +010070 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020071 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010072 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020073
Neil Armstrong0d763412022-08-11 10:32:22 +020074 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010075 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020076
Gilles Peskine449bd832023-01-11 14:50:10 +010077 mbedtls_ecp_point_free(&ctx->Xm1);
78 mbedtls_ecp_point_free(&ctx->Xm2);
79 mbedtls_ecp_point_free(&ctx->Xp1);
80 mbedtls_ecp_point_free(&ctx->Xp2);
81 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020082
Gilles Peskine449bd832023-01-11 14:50:10 +010083 mbedtls_mpi_free(&ctx->xm1);
84 mbedtls_mpi_free(&ctx->xm2);
85 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020086}
87
88/*
89 * Setup context
90 */
Gilles Peskine449bd832023-01-11 14:50:10 +010091int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
92 mbedtls_ecjpake_role role,
93 mbedtls_md_type_t hash,
94 mbedtls_ecp_group_id curve,
95 const unsigned char *secret,
96 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020097{
Janos Follath24eed8d2019-11-22 13:21:35 +000098 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +000099
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
101 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
102 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200103
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200104 ctx->role = role;
105
Gilles Peskine449bd832023-01-11 14:50:10 +0100106 if ((mbedtls_md_info_from_type(hash)) == NULL) {
107 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
108 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200109
Neil Armstrong0d763412022-08-11 10:32:22 +0200110 ctx->md_type = hash;
111
Gilles Peskine449bd832023-01-11 14:50:10 +0100112 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200115
116cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 if (ret != 0) {
118 mbedtls_ecjpake_free(ctx);
119 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200122}
123
Gilles Peskine449bd832023-01-11 14:50:10 +0100124int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
125 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200126{
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200128 case MBEDTLS_ECP_PF_UNCOMPRESSED:
129 case MBEDTLS_ECP_PF_COMPRESSED:
130 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200132 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200134 }
135}
136
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200137/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200138 * Check if context is ready for use
139 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100140int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200141{
Gilles Peskine449bd832023-01-11 14:50:10 +0100142 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200143 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 ctx->s.p == NULL) {
145 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200146 }
147
Gilles Peskine449bd832023-01-11 14:50:10 +0100148 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200149}
150
151/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200152 * Write a point plus its length to a buffer
153 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154static int ecjpake_write_len_point(unsigned char **p,
155 const unsigned char *end,
156 const mbedtls_ecp_group *grp,
157 const int pf,
158 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200159{
Janos Follath24eed8d2019-11-22 13:21:35 +0000160 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161 size_t len;
162
163 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100164 if (end < *p || end - *p < 5) {
165 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
166 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000169 &len, *p + 4, (size_t) (end - (*p + 4)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 if (ret != 0) {
171 return ret;
172 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200173
Gilles Peskine449bd832023-01-11 14:50:10 +0100174 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200175
176 *p += 4 + len;
177
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200179}
180
181/*
182 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200183 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200184 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100185#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200186
187/*
188 * Compute hash for ZKP (7.4.2.2.2.1)
189 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100190static int ecjpake_hash(const mbedtls_md_type_t md_type,
191 const mbedtls_ecp_group *grp,
192 const int pf,
193 const mbedtls_ecp_point *G,
194 const mbedtls_ecp_point *V,
195 const mbedtls_ecp_point *X,
196 const char *id,
197 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200198{
Janos Follath24eed8d2019-11-22 13:21:35 +0000199 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
201 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100202 const unsigned char *end = buf + sizeof(buf);
203 const size_t id_len = strlen(id);
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +0200204 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200205
206 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100207 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
208 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
209 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200210
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 if (end - p < 4) {
212 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
213 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100216 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 if (end < p || (size_t) (end - p) < id_len) {
219 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
220 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200223 p += id_len;
224
225 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100226 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000227 buf, (size_t) (p - buf), hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200228
229 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100230 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200231 mbedtls_md_get_size_from_type(md_type)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200233
234cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200236}
237
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200238/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200239 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
240 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100241static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
242 const mbedtls_ecp_group *grp,
243 const int pf,
244 const mbedtls_ecp_point *G,
245 const mbedtls_ecp_point *X,
246 const char *id,
247 const unsigned char **p,
248 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200249{
Janos Follath24eed8d2019-11-22 13:21:35 +0000250 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200251 mbedtls_ecp_point V, VV;
252 mbedtls_mpi r, h;
253 size_t r_len;
254
Gilles Peskine449bd832023-01-11 14:50:10 +0100255 mbedtls_ecp_point_init(&V);
256 mbedtls_ecp_point_init(&VV);
257 mbedtls_mpi_init(&r);
258 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200259
260 /*
261 * struct {
262 * ECPoint V;
263 * opaque r<1..2^8-1>;
264 * } ECSchnorrZKP;
265 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 if (end < *p) {
267 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
268 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200269
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000270 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200271
Gilles Peskine449bd832023-01-11 14:50:10 +0100272 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200273 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
274 goto cleanup;
275 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200276
277 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200280 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
281 goto cleanup;
282 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200285 *p += r_len;
286
287 /*
288 * Verification
289 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
291 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
292 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200295 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
296 goto cleanup;
297 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200298
299cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 mbedtls_ecp_point_free(&V);
301 mbedtls_ecp_point_free(&VV);
302 mbedtls_mpi_free(&r);
303 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200306}
307
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200308/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200309 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
310 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100311static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
312 const mbedtls_ecp_group *grp,
313 const int pf,
314 const mbedtls_ecp_point *G,
315 const mbedtls_mpi *x,
316 const mbedtls_ecp_point *X,
317 const char *id,
318 unsigned char **p,
319 const unsigned char *end,
320 int (*f_rng)(void *, unsigned char *, size_t),
321 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200322{
Janos Follath24eed8d2019-11-22 13:21:35 +0000323 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200324 mbedtls_ecp_point V;
325 mbedtls_mpi v;
326 mbedtls_mpi h; /* later recycled to hold r */
327 size_t len;
328
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 if (end < *p) {
330 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
331 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200332
Gilles Peskine449bd832023-01-11 14:50:10 +0100333 mbedtls_ecp_point_init(&V);
334 mbedtls_mpi_init(&v);
335 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200336
337 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100338 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
339 G, &v, &V, f_rng, p_rng));
340 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
341 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
342 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
343 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200344
345 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100346 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000347 pf, &len, *p, (size_t) (end - *p)));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200348 *p += len;
349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 len = mbedtls_mpi_size(&h); /* actually r */
351 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200352 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
353 goto cleanup;
354 }
355
Gilles Peskine449bd832023-01-11 14:50:10 +0100356 *(*p)++ = MBEDTLS_BYTE_0(len);
357 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200358 *p += len;
359
360cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 mbedtls_ecp_point_free(&V);
362 mbedtls_mpi_free(&v);
363 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200364
Gilles Peskine449bd832023-01-11 14:50:10 +0100365 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200366}
367
368/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200369 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
370 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200371 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100372static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
373 const mbedtls_ecp_group *grp,
374 const int pf,
375 const mbedtls_ecp_point *G,
376 mbedtls_ecp_point *X,
377 const char *id,
378 const unsigned char **p,
379 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200380{
Janos Follath24eed8d2019-11-22 13:21:35 +0000381 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200382
Gilles Peskine449bd832023-01-11 14:50:10 +0100383 if (end < *p) {
384 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
385 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200386
387 /*
388 * struct {
389 * ECPoint X;
390 * ECSchnorrZKP zkp;
391 * } ECJPAKEKeyKP;
392 */
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000393 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100394 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200395 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
396 goto cleanup;
397 }
398
Gilles Peskine449bd832023-01-11 14:50:10 +0100399 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200400
401cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200403}
404
405/*
406 * Generate an ECJPAKEKeyKP
407 * Output: the serialized structure, plus private/public key pair
408 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100409static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
410 const mbedtls_ecp_group *grp,
411 const int pf,
412 const mbedtls_ecp_point *G,
413 mbedtls_mpi *x,
414 mbedtls_ecp_point *X,
415 const char *id,
416 unsigned char **p,
417 const unsigned char *end,
418 int (*f_rng)(void *, unsigned char *, size_t),
419 void *p_rng)
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 size_t len;
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 if (end < *p) {
425 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
426 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200427
428 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100429 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
430 f_rng, p_rng));
431 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000432 pf, &len, *p, (size_t) (end - *p)));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200433 *p += len;
434
435 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
437 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200438
439cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200441}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200442
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200443/*
444 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800445 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200446 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100447static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
448 const mbedtls_ecp_group *grp,
449 const int pf,
450 const mbedtls_ecp_point *G,
451 mbedtls_ecp_point *Xa,
452 mbedtls_ecp_point *Xb,
453 const char *id,
454 const unsigned char *buf,
455 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200456{
Janos Follath24eed8d2019-11-22 13:21:35 +0000457 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200458 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200459 const unsigned char *end = buf + len;
460
461 /*
462 * struct {
463 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
464 * } ECJPAKEKeyKPPairList;
465 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100466 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
467 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200468
Gilles Peskine449bd832023-01-11 14:50:10 +0100469 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200470 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472
473cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200475}
476
477/*
478 * Generate a ECJPAKEKeyKPPairList
479 * Outputs: the serialized structure, plus two private/public key pairs
480 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100481static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
482 const mbedtls_ecp_group *grp,
483 const int pf,
484 const mbedtls_ecp_point *G,
485 mbedtls_mpi *xm1,
486 mbedtls_ecp_point *Xa,
487 mbedtls_mpi *xm2,
488 mbedtls_ecp_point *Xb,
489 const char *id,
490 unsigned char *buf,
491 size_t len,
492 size_t *olen,
493 int (*f_rng)(void *, unsigned char *, size_t),
494 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200495{
Janos Follath24eed8d2019-11-22 13:21:35 +0000496 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200497 unsigned char *p = buf;
498 const unsigned char *end = buf + len;
499
Gilles Peskine449bd832023-01-11 14:50:10 +0100500 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
501 &p, end, f_rng, p_rng));
502 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
503 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200504
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000505 *olen = (size_t) (p - buf);
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200506
507cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100508 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200509}
510
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200511/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200512 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200513 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100514int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
515 const unsigned char *buf,
516 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200517{
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
519 &ctx->grp.G,
520 &ctx->Xp1, &ctx->Xp2, ID_PEER,
521 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200522}
523
524/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200525 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200526 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100527int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
528 unsigned char *buf, size_t len, size_t *olen,
529 int (*f_rng)(void *, unsigned char *, size_t),
530 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200531{
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
534 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
535 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200536}
537
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200538/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200539 * Compute the sum of three points R = A + B + C
540 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100541static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
542 const mbedtls_ecp_point *A,
543 const mbedtls_ecp_point *B,
544 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200545{
Janos Follath24eed8d2019-11-22 13:21:35 +0000546 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200547 mbedtls_mpi one;
548
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
552 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
553 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200554
555cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200557
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200559}
560
561/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200562 * 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 +0200563 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100564int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
565 const unsigned char *buf,
566 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200567{
Janos Follath24eed8d2019-11-22 13:21:35 +0000568 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569 const unsigned char *p = buf;
570 const unsigned char *end = buf + len;
571 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200572 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000573
Gilles Peskine449bd832023-01-11 14:50:10 +0100574 mbedtls_ecp_group_init(&grp);
575 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200576
577 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200578 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
579 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
580 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200581 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200582 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100583 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
584 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200585
586 /*
587 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200588 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200589 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200590 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200591 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100592 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
593 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
594 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200595 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
596 goto cleanup;
597 }
598 }
599
Gilles Peskine449bd832023-01-11 14:50:10 +0100600 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
601 ctx->point_format,
602 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200603
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
606 goto cleanup;
607 }
608
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200609cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 mbedtls_ecp_group_free(&grp);
611 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200612
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200614}
615
616/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200617 * Compute R = +/- X * S mod N, taking care not to leak S
618 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100619static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
620 const mbedtls_mpi *X,
621 const mbedtls_mpi *S,
622 const mbedtls_mpi *N,
623 int (*f_rng)(void *, unsigned char *, size_t),
624 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200625{
Janos Follath24eed8d2019-11-22 13:21:35 +0000626 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200627 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
628
Gilles Peskine449bd832023-01-11 14:50:10 +0100629 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200630
631 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100632 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
633 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
634 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200635
636 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200638 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200640
641cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100642 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200643
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200645}
646
647/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200648 * 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 +0200649 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100650int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
651 unsigned char *buf, size_t len, size_t *olen,
652 int (*f_rng)(void *, unsigned char *, size_t),
653 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200654{
Janos Follath24eed8d2019-11-22 13:21:35 +0000655 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200656 mbedtls_ecp_point G; /* C: GA, S: GB */
657 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
658 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200659 unsigned char *p = buf;
660 const unsigned char *end = buf + len;
661 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000662
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 mbedtls_ecp_point_init(&G);
664 mbedtls_ecp_point_init(&Xm);
665 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200666
667 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200668 * 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 +0200669 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
671 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
672 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200673 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100674 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
675 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
676 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
677 &ctx->grp.N, f_rng, p_rng));
678 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200679
680 /*
681 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200682 *
683 * struct {
684 * ECParameters curve_params; // only server writing its message
685 * ECJPAKEKeyKP ecjpake_key_kp;
686 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200687 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
689 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200690 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
691 goto cleanup;
692 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100693 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000694 p, (size_t) (end - p)));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200695 p += ec_len;
696 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200697
Gilles Peskine449bd832023-01-11 14:50:10 +0100698 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
700 goto cleanup;
701 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000703 ctx->point_format, &ec_len, p, (size_t) (end - p)));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200704 p += ec_len;
705
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
707 ctx->point_format,
708 &G, &xm, &Xm, ID_MINE,
709 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200710
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000711 *olen = (size_t) (p - buf);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200712
713cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 mbedtls_ecp_point_free(&G);
715 mbedtls_ecp_point_free(&Xm);
716 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200719}
720
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200721/*
722 * Derive PMS (7.4.2.7 / 7.4.2.8)
723 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100724static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
725 mbedtls_ecp_point *K,
726 int (*f_rng)(void *, unsigned char *, size_t),
727 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200728{
Janos Follath24eed8d2019-11-22 13:21:35 +0000729 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200730 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000731
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 mbedtls_mpi_init(&m_xm2_s);
733 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200734
Gilles Peskine449bd832023-01-11 14:50:10 +0100735 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200736
737 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200738 * Client: K = ( Xs - X4 * x2 * s ) * x2
739 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200740 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200741 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100742 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
743 &ctx->grp.N, f_rng, p_rng));
744 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
745 &one, &ctx->Xp,
746 &m_xm2_s, &ctx->Xp2));
747 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
748 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200749
Neil Armstrong12663092022-06-15 16:00:00 +0200750cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100751 mbedtls_mpi_free(&m_xm2_s);
752 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200753
Gilles Peskine449bd832023-01-11 14:50:10 +0100754 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200755}
756
Gilles Peskine449bd832023-01-11 14:50:10 +0100757int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
758 unsigned char *buf, size_t len, size_t *olen,
759 int (*f_rng)(void *, unsigned char *, size_t),
760 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200761{
762 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
763 mbedtls_ecp_point K;
764 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
765 size_t x_bytes;
766
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200767 *olen = mbedtls_md_get_size_from_type(ctx->md_type);
Gilles Peskine449bd832023-01-11 14:50:10 +0100768 if (len < *olen) {
769 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
770 }
Neil Armstrong12663092022-06-15 16:00:00 +0200771
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200773
774 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100775 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200776 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 }
Neil Armstrong12663092022-06-15 16:00:00 +0200778
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200779 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100780 x_bytes = (ctx->grp.pbits + 7) / 8;
781 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
782 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
783 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200784
785cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200787
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200789}
790
Gilles Peskine449bd832023-01-11 14:50:10 +0100791int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
792 unsigned char *buf, size_t len, size_t *olen,
793 int (*f_rng)(void *, unsigned char *, size_t),
794 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200795{
796 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
797 mbedtls_ecp_point K;
798
Gilles Peskine449bd832023-01-11 14:50:10 +0100799 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200800
801 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100802 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200803 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100804 }
Neil Armstrong12663092022-06-15 16:00:00 +0200805
Gilles Peskine449bd832023-01-11 14:50:10 +0100806 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
807 olen, buf, len);
808 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200809 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100810 }
Neil Armstrong12663092022-06-15 16:00:00 +0200811
812cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100813 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200814
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200816}
817
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200818#undef ID_MINE
819#undef ID_PEER
820
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200821#if defined(MBEDTLS_SELF_TEST)
822
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200823#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200824
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200825#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +0100826 !defined(MBEDTLS_MD_CAN_SHA256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100827int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200828{
829 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100830 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200831}
832#else
833
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200834static const unsigned char ecjpake_test_password[] = {
835 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
836 0x65, 0x73, 0x74
837};
838
839static const unsigned char ecjpake_test_x1[] = {
840 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
841 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
842 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
843};
844
845static const unsigned char ecjpake_test_x2[] = {
846 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
847 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
848 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
849};
850
851static const unsigned char ecjpake_test_x3[] = {
852 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855};
856
857static const unsigned char ecjpake_test_x4[] = {
858 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
859 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
860 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
861};
862
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200863static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200864 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
865 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
866 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
867 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
868 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
869 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
870 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
871 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
872 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
873 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
874 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
875 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
876 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200877 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
878 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
879 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
880 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
881 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
882 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
883 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
884 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
885 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
886 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
887 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
888 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
889 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
890 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
891 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200892};
893
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200894static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200895 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
896 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
897 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
898 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
899 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
900 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
901 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
902 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
903 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
904 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
905 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
906 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
907 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
908 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
909 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
910 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
911 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
912 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
913 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
914 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
915 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
916 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
917 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
918 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
919 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
920 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
921 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
922 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
923};
924
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200925static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200926 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
927 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
928 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
929 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
930 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
931 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
932 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
933 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
934 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
935 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
936 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
937 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
938 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
939 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
940};
941
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200942static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200943 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
944 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
945 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
946 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
947 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
948 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
949 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
950 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
951 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
952 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
953 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
954 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
955 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
956 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
957};
958
Neil Armstrong12663092022-06-15 16:00:00 +0200959static const unsigned char ecjpake_test_shared_key[] = {
960 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
961 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
962 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
963 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
964 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
965 0x17, 0xc3, 0xde, 0x27, 0xb4,
966};
967
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200968static const unsigned char ecjpake_test_pms[] = {
969 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
970 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
971 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
972};
973
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200974/*
975 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
976 *
977 * This is the linear congruential generator from numerical recipes,
978 * except we only use the low byte as the output. See
979 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
980 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100981static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200982{
983 static uint32_t state = 42;
984
985 (void) ctx;
986
Gilles Peskine449bd832023-01-11 14:50:10 +0100987 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200988 state = state * 1664525u + 1013904223u;
989 out[i] = (unsigned char) state;
990 }
991
Gilles Peskine449bd832023-01-11 14:50:10 +0100992 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200993}
994
Antonin Décimo36e89b52019-01-23 15:24:37 +0100995/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +0100996static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
997 const unsigned char *xm1, size_t len1,
998 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +0200999{
Janos Follath24eed8d2019-11-22 13:21:35 +00001000 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001001
Gilles Peskine449bd832023-01-11 14:50:10 +01001002 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1003 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1004 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1005 &ctx->grp.G, self_test_rng, NULL));
1006 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1007 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001008
1009cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001011}
1012
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001013/* For tests we don't need a secure RNG;
1014 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001015static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001016{
1017 static uint32_t x = 42;
1018 (void) p;
1019
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001021 size_t use_len = len > 4 ? 4 : len;
1022 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001023 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001024 out += use_len;
1025 len -= use_len;
1026 }
1027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001029}
1030
Gilles Peskine449bd832023-01-11 14:50:10 +01001031#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001032 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001033 if (x) \
1034 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001035 else \
1036 { \
1037 ret = 1; \
1038 goto cleanup; \
1039 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001040 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001041
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001042/*
1043 * Checkup routine
1044 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001045int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001046{
Janos Follath24eed8d2019-11-22 13:21:35 +00001047 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001048 mbedtls_ecjpake_context cli;
1049 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001050 unsigned char buf[512], pms[32];
1051 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001052
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 mbedtls_ecjpake_init(&cli);
1054 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001055
Gilles Peskine449bd832023-01-11 14:50:10 +01001056 if (verbose != 0) {
1057 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1058 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001059
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1061 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1062 ecjpake_test_password,
1063 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001064
Gilles Peskine449bd832023-01-11 14:50:10 +01001065 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1066 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1067 ecjpake_test_password,
1068 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001069
Gilles Peskine449bd832023-01-11 14:50:10 +01001070 if (verbose != 0) {
1071 mbedtls_printf("passed\n");
1072 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001073
Gilles Peskine449bd832023-01-11 14:50:10 +01001074 if (verbose != 0) {
1075 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1076 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077
Gilles Peskine449bd832023-01-11 14:50:10 +01001078 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1079 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001080
Gilles Peskine449bd832023-01-11 14:50:10 +01001081 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001082
Gilles Peskine449bd832023-01-11 14:50:10 +01001083 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1084 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001087
Gilles Peskine449bd832023-01-11 14:50:10 +01001088 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1089 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001092
Gilles Peskine449bd832023-01-11 14:50:10 +01001093 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1094 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001095
Gilles Peskine449bd832023-01-11 14:50:10 +01001096 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1097 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001098
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001100
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1102 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 TEST_ASSERT(len == pmslen);
1105 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001106
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 if (verbose != 0) {
1108 mbedtls_printf("passed\n");
1109 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001110
Steven Cooreman64f27732021-01-11 17:20:10 +01001111 /* 'reference handshake' tests can only be run against implementations
1112 * for which we have 100% control over how the random ephemeral keys
Gilles Peskinee820c0a2023-08-03 17:45:20 +02001113 * are generated. This is only the case for the internal Mbed TLS
Steven Cooreman64f27732021-01-11 17:20:10 +01001114 * implementation, so these tests are skipped in case the internal
1115 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 if (verbose != 0) {
1117 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1118 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001119
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001120 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1122 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1123 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001124
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1126 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1127 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001128
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001129 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1131 ecjpake_test_cli_one,
1132 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1135 ecjpake_test_srv_one,
1136 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001137
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001138 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1140 ecjpake_test_srv_two,
1141 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001142
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1144 ecjpake_test_cli_two,
1145 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001146
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001147 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1149 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001150
Gilles Peskine449bd832023-01-11 14:50:10 +01001151 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1152 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001153
Neil Armstrong12663092022-06-15 16:00:00 +02001154 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1156 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001157
Gilles Peskine449bd832023-01-11 14:50:10 +01001158 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1159 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001160
Gilles Peskine449bd832023-01-11 14:50:10 +01001161 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001162
1163 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1165 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001166
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1168 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001169
Neil Armstrong12663092022-06-15 16:00:00 +02001170 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001171 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1172 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001173
Gilles Peskine449bd832023-01-11 14:50:10 +01001174 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1175 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001176
Gilles Peskine449bd832023-01-11 14:50:10 +01001177 if (verbose != 0) {
1178 mbedtls_printf("passed\n");
1179 }
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001180
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001181cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001182 mbedtls_ecjpake_free(&cli);
1183 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001184
Gilles Peskine449bd832023-01-11 14:50:10 +01001185 if (ret != 0) {
1186 if (verbose != 0) {
1187 mbedtls_printf("failed\n");
1188 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001189
1190 ret = 1;
1191 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001192
Gilles Peskine449bd832023-01-11 14:50:10 +01001193 if (verbose != 0) {
1194 mbedtls_printf("\n");
1195 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001196
Gilles Peskine449bd832023-01-11 14:50:10 +01001197 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001198}
1199
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001200#undef TEST_ASSERT
1201
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +01001202#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001203
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001204#endif /* MBEDTLS_SELF_TEST */
1205
1206#endif /* MBEDTLS_ECJPAKE_C */