blob: cdf5d7ea46e5dd2a3ac4ffd1ac677c49b852ec02 [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
Hanno Becker616d1ca2018-01-24 10:25:05 +000023#if !defined(MBEDTLS_ECJPAKE_ALT)
24
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020025/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020026 * Convert a mbedtls_ecjpake_role to identifier string
27 */
28static const char * const ecjpake_id[] = {
29 "client",
30 "server"
31};
32
Gilles Peskine449bd832023-01-11 14:50:10 +010033#define ID_MINE (ecjpake_id[ctx->role])
34#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020035
Neil Armstrongecaba1c2022-08-11 10:47:08 +020036/**
Gilles Peskine449bd832023-01-11 14:50:10 +010037 * Helper to Compute a hash from md_type
38 */
39static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
40 const unsigned char *input, size_t ilen,
41 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020042{
Gilles Peskine449bd832023-01-11 14:50:10 +010043 return mbedtls_md(mbedtls_md_info_from_type(md_type),
44 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020045}
46
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020047/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020048 * Initialize context
49 */
Gilles Peskine449bd832023-01-11 14:50:10 +010050void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020051{
Neil Armstrong0d763412022-08-11 10:32:22 +020052 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010053 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020054 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020055
Gilles Peskine449bd832023-01-11 14:50:10 +010056 mbedtls_ecp_point_init(&ctx->Xm1);
57 mbedtls_ecp_point_init(&ctx->Xm2);
58 mbedtls_ecp_point_init(&ctx->Xp1);
59 mbedtls_ecp_point_init(&ctx->Xp2);
60 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020061
Gilles Peskine449bd832023-01-11 14:50:10 +010062 mbedtls_mpi_init(&ctx->xm1);
63 mbedtls_mpi_init(&ctx->xm2);
64 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020065}
66
67/*
68 * Free context
69 */
Gilles Peskine449bd832023-01-11 14:50:10 +010070void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020071{
Gilles Peskine449bd832023-01-11 14:50:10 +010072 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020073 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010074 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020075
Neil Armstrong0d763412022-08-11 10:32:22 +020076 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010077 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020078
Gilles Peskine449bd832023-01-11 14:50:10 +010079 mbedtls_ecp_point_free(&ctx->Xm1);
80 mbedtls_ecp_point_free(&ctx->Xm2);
81 mbedtls_ecp_point_free(&ctx->Xp1);
82 mbedtls_ecp_point_free(&ctx->Xp2);
83 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020084
Gilles Peskine449bd832023-01-11 14:50:10 +010085 mbedtls_mpi_free(&ctx->xm1);
86 mbedtls_mpi_free(&ctx->xm2);
87 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020088}
89
90/*
91 * Setup context
92 */
Gilles Peskine449bd832023-01-11 14:50:10 +010093int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
94 mbedtls_ecjpake_role role,
95 mbedtls_md_type_t hash,
96 mbedtls_ecp_group_id curve,
97 const unsigned char *secret,
98 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020099{
Janos Follath24eed8d2019-11-22 13:21:35 +0000100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000101
Gilles Peskine449bd832023-01-11 14:50:10 +0100102 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
103 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
104 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200105
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200106 ctx->role = role;
107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 if ((mbedtls_md_info_from_type(hash)) == NULL) {
109 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
110 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200111
Neil Armstrong0d763412022-08-11 10:32:22 +0200112 ctx->md_type = hash;
113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200115
Gilles Peskine449bd832023-01-11 14:50:10 +0100116 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200117
118cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 if (ret != 0) {
120 mbedtls_ecjpake_free(ctx);
121 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200122
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200124}
125
Gilles Peskine449bd832023-01-11 14:50:10 +0100126int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
127 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200128{
Gilles Peskine449bd832023-01-11 14:50:10 +0100129 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200130 case MBEDTLS_ECP_PF_UNCOMPRESSED:
131 case MBEDTLS_ECP_PF_COMPRESSED:
132 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100133 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200134 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200136 }
137}
138
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200139/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200140 * Check if context is ready for use
141 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100142int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200143{
Gilles Peskine449bd832023-01-11 14:50:10 +0100144 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200145 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 ctx->s.p == NULL) {
147 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200148 }
149
Gilles Peskine449bd832023-01-11 14:50:10 +0100150 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200151}
152
153/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200154 * Write a point plus its length to a buffer
155 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100156static int ecjpake_write_len_point(unsigned char **p,
157 const unsigned char *end,
158 const mbedtls_ecp_group *grp,
159 const int pf,
160 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200161{
Janos Follath24eed8d2019-11-22 13:21:35 +0000162 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200163 size_t len;
164
165 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100166 if (end < *p || end - *p < 5) {
167 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
168 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200169
Gilles Peskine449bd832023-01-11 14:50:10 +0100170 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000171 &len, *p + 4, (size_t) (end - (*p + 4)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100172 if (ret != 0) {
173 return ret;
174 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200175
Gilles Peskine449bd832023-01-11 14:50:10 +0100176 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200177
178 *p += 4 + len;
179
Gilles Peskine449bd832023-01-11 14:50:10 +0100180 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181}
182
183/*
184 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200185 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200186 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100187#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200188
189/*
190 * Compute hash for ZKP (7.4.2.2.2.1)
191 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100192static int ecjpake_hash(const mbedtls_md_type_t md_type,
193 const mbedtls_ecp_group *grp,
194 const int pf,
195 const mbedtls_ecp_point *G,
196 const mbedtls_ecp_point *V,
197 const mbedtls_ecp_point *X,
198 const char *id,
199 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200{
Janos Follath24eed8d2019-11-22 13:21:35 +0000201 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200202 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100204 const unsigned char *end = buf + sizeof(buf);
205 const size_t id_len = strlen(id);
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +0200206 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200207
208 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
210 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
211 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212
Gilles Peskine449bd832023-01-11 14:50:10 +0100213 if (end - p < 4) {
214 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
215 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200216
Gilles Peskine449bd832023-01-11 14:50:10 +0100217 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100218 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 if (end < p || (size_t) (end - p) < id_len) {
221 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
222 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200223
Gilles Peskine449bd832023-01-11 14:50:10 +0100224 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200225 p += id_len;
226
227 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000229 buf, (size_t) (p - buf), hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200230
231 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200233 mbedtls_md_get_size_from_type(md_type)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100234 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200235
236cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200238}
239
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200240/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200241 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100243static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
244 const mbedtls_ecp_group *grp,
245 const int pf,
246 const mbedtls_ecp_point *G,
247 const mbedtls_ecp_point *X,
248 const char *id,
249 const unsigned char **p,
250 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200251{
Janos Follath24eed8d2019-11-22 13:21:35 +0000252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200253 mbedtls_ecp_point V, VV;
254 mbedtls_mpi r, h;
255 size_t r_len;
256
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 mbedtls_ecp_point_init(&V);
258 mbedtls_ecp_point_init(&VV);
259 mbedtls_mpi_init(&r);
260 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200261
262 /*
263 * struct {
264 * ECPoint V;
265 * opaque r<1..2^8-1>;
266 * } ECSchnorrZKP;
267 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100268 if (end < *p) {
269 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
270 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200271
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000272 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200275 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276 goto cleanup;
277 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200278
279 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200280
Gilles Peskine449bd832023-01-11 14:50:10 +0100281 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200282 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283 goto cleanup;
284 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200287 *p += r_len;
288
289 /*
290 * Verification
291 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100292 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
293 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
294 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200297 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298 goto cleanup;
299 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200300
301cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100302 mbedtls_ecp_point_free(&V);
303 mbedtls_ecp_point_free(&VV);
304 mbedtls_mpi_free(&r);
305 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200306
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200308}
309
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200310/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200311 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100313static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
314 const mbedtls_ecp_group *grp,
315 const int pf,
316 const mbedtls_ecp_point *G,
317 const mbedtls_mpi *x,
318 const mbedtls_ecp_point *X,
319 const char *id,
320 unsigned char **p,
321 const unsigned char *end,
322 int (*f_rng)(void *, unsigned char *, size_t),
323 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200324{
Janos Follath24eed8d2019-11-22 13:21:35 +0000325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200326 mbedtls_ecp_point V;
327 mbedtls_mpi v;
328 mbedtls_mpi h; /* later recycled to hold r */
329 size_t len;
330
Gilles Peskine449bd832023-01-11 14:50:10 +0100331 if (end < *p) {
332 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
333 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200334
Gilles Peskine449bd832023-01-11 14:50:10 +0100335 mbedtls_ecp_point_init(&V);
336 mbedtls_mpi_init(&v);
337 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200338
339 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100340 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
341 G, &v, &V, f_rng, p_rng));
342 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
343 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
344 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
345 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200346
347 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000349 pf, &len, *p, (size_t) (end - *p)));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200350 *p += len;
351
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 len = mbedtls_mpi_size(&h); /* actually r */
353 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200354 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355 goto cleanup;
356 }
357
Gilles Peskine449bd832023-01-11 14:50:10 +0100358 *(*p)++ = MBEDTLS_BYTE_0(len);
359 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200360 *p += len;
361
362cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 mbedtls_ecp_point_free(&V);
364 mbedtls_mpi_free(&v);
365 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200366
Gilles Peskine449bd832023-01-11 14:50:10 +0100367 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200368}
369
370/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200371 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200373 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100374static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
375 const mbedtls_ecp_group *grp,
376 const int pf,
377 const mbedtls_ecp_point *G,
378 mbedtls_ecp_point *X,
379 const char *id,
380 const unsigned char **p,
381 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200382{
Janos Follath24eed8d2019-11-22 13:21:35 +0000383 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200384
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 if (end < *p) {
386 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
387 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200388
389 /*
390 * struct {
391 * ECPoint X;
392 * ECSchnorrZKP zkp;
393 * } ECJPAKEKeyKP;
394 */
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000395 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200397 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398 goto cleanup;
399 }
400
Gilles Peskine449bd832023-01-11 14:50:10 +0100401 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200402
403cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200405}
406
407/*
408 * Generate an ECJPAKEKeyKP
409 * Output: the serialized structure, plus private/public key pair
410 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100411static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
412 const mbedtls_ecp_group *grp,
413 const int pf,
414 const mbedtls_ecp_point *G,
415 mbedtls_mpi *x,
416 mbedtls_ecp_point *X,
417 const char *id,
418 unsigned char **p,
419 const unsigned char *end,
420 int (*f_rng)(void *, unsigned char *, size_t),
421 void *p_rng)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200422{
Janos Follath24eed8d2019-11-22 13:21:35 +0000423 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200424 size_t len;
425
Gilles Peskine449bd832023-01-11 14:50:10 +0100426 if (end < *p) {
427 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
428 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200429
430 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
432 f_rng, p_rng));
433 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000434 pf, &len, *p, (size_t) (end - *p)));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200435 *p += len;
436
437 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200440
441cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100442 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200443}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200444
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200445/*
446 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800447 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200448 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
450 const mbedtls_ecp_group *grp,
451 const int pf,
452 const mbedtls_ecp_point *G,
453 mbedtls_ecp_point *Xa,
454 mbedtls_ecp_point *Xb,
455 const char *id,
456 const unsigned char *buf,
457 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200458{
Janos Follath24eed8d2019-11-22 13:21:35 +0000459 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200460 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200461 const unsigned char *end = buf + len;
462
463 /*
464 * struct {
465 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466 * } ECJPAKEKeyKPPairList;
467 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100468 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
469 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200470
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200472 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200474
475cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100476 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200477}
478
479/*
480 * Generate a ECJPAKEKeyKPPairList
481 * Outputs: the serialized structure, plus two private/public key pairs
482 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100483static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
484 const mbedtls_ecp_group *grp,
485 const int pf,
486 const mbedtls_ecp_point *G,
487 mbedtls_mpi *xm1,
488 mbedtls_ecp_point *Xa,
489 mbedtls_mpi *xm2,
490 mbedtls_ecp_point *Xb,
491 const char *id,
492 unsigned char *buf,
493 size_t len,
494 size_t *olen,
495 int (*f_rng)(void *, unsigned char *, size_t),
496 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200497{
Janos Follath24eed8d2019-11-22 13:21:35 +0000498 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200499 unsigned char *p = buf;
500 const unsigned char *end = buf + len;
501
Gilles Peskine449bd832023-01-11 14:50:10 +0100502 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
503 &p, end, f_rng, p_rng));
504 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
505 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200506
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000507 *olen = (size_t) (p - buf);
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200508
509cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200511}
512
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200513/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200514 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200515 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100516int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
517 const unsigned char *buf,
518 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200519{
Gilles Peskine449bd832023-01-11 14:50:10 +0100520 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
521 &ctx->grp.G,
522 &ctx->Xp1, &ctx->Xp2, ID_PEER,
523 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200524}
525
526/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200527 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200528 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100529int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
530 unsigned char *buf, size_t len, size_t *olen,
531 int (*f_rng)(void *, unsigned char *, size_t),
532 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200533{
Gilles Peskine449bd832023-01-11 14:50:10 +0100534 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
535 &ctx->grp.G,
536 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
537 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200538}
539
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200540/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200541 * Compute the sum of three points R = A + B + C
542 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100543static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
544 const mbedtls_ecp_point *A,
545 const mbedtls_ecp_point *B,
546 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200547{
Janos Follath24eed8d2019-11-22 13:21:35 +0000548 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200549 mbedtls_mpi one;
550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
554 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
555 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200556
557cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100558 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200561}
562
563/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200564 * 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 +0200565 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100566int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
567 const unsigned char *buf,
568 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200569{
Janos Follath24eed8d2019-11-22 13:21:35 +0000570 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200571 const unsigned char *p = buf;
572 const unsigned char *end = buf + len;
573 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200574 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000575
Gilles Peskine449bd832023-01-11 14:50:10 +0100576 mbedtls_ecp_group_init(&grp);
577 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200578
579 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200580 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
581 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
582 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200583 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200584 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100585 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200587
588 /*
589 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200590 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200591 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200593 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100594 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
595 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
596 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200597 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598 goto cleanup;
599 }
600 }
601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603 ctx->point_format,
604 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200607 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608 goto cleanup;
609 }
610
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200611cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100612 mbedtls_ecp_group_free(&grp);
613 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200614
Gilles Peskine449bd832023-01-11 14:50:10 +0100615 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200616}
617
618/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200619 * Compute R = +/- X * S mod N, taking care not to leak S
620 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100621static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
622 const mbedtls_mpi *X,
623 const mbedtls_mpi *S,
624 const mbedtls_mpi *N,
625 int (*f_rng)(void *, unsigned char *, size_t),
626 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200627{
Janos Follath24eed8d2019-11-22 13:21:35 +0000628 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200629 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630
Gilles Peskine449bd832023-01-11 14:50:10 +0100631 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200632
633 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
635 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
636 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200637
638 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100639 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200640 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100641 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200642
643cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200645
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200647}
648
649/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200650 * 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 +0200651 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100652int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
653 unsigned char *buf, size_t len, size_t *olen,
654 int (*f_rng)(void *, unsigned char *, size_t),
655 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200656{
Janos Follath24eed8d2019-11-22 13:21:35 +0000657 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200658 mbedtls_ecp_point G; /* C: GA, S: GB */
659 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
660 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200661 unsigned char *p = buf;
662 const unsigned char *end = buf + len;
663 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000664
Gilles Peskine449bd832023-01-11 14:50:10 +0100665 mbedtls_ecp_point_init(&G);
666 mbedtls_ecp_point_init(&Xm);
667 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200668
669 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 * 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 +0200671 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200672 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
673 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
674 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200675 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
677 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
678 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
679 &ctx->grp.N, f_rng, p_rng));
680 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200681
682 /*
683 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 *
685 * struct {
686 * ECParameters curve_params; // only server writing its message
687 * ECJPAKEKeyKP ecjpake_key_kp;
688 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200689 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100690 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
691 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200692 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693 goto cleanup;
694 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100695 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000696 p, (size_t) (end - p)));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200697 p += ec_len;
698 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200699
Gilles Peskine449bd832023-01-11 14:50:10 +0100700 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200701 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702 goto cleanup;
703 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000705 ctx->point_format, &ec_len, p, (size_t) (end - p)));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200706 p += ec_len;
707
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
709 ctx->point_format,
710 &G, &xm, &Xm, ID_MINE,
711 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200712
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000713 *olen = (size_t) (p - buf);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200714
715cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 mbedtls_ecp_point_free(&G);
717 mbedtls_ecp_point_free(&Xm);
718 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200721}
722
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200723/*
724 * Derive PMS (7.4.2.7 / 7.4.2.8)
725 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100726static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
727 mbedtls_ecp_point *K,
728 int (*f_rng)(void *, unsigned char *, size_t),
729 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200730{
Janos Follath24eed8d2019-11-22 13:21:35 +0000731 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200732 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000733
Gilles Peskine449bd832023-01-11 14:50:10 +0100734 mbedtls_mpi_init(&m_xm2_s);
735 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200736
Gilles Peskine449bd832023-01-11 14:50:10 +0100737 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200738
739 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200740 * Client: K = ( Xs - X4 * x2 * s ) * x2
741 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200742 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200743 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100744 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
745 &ctx->grp.N, f_rng, p_rng));
746 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
747 &one, &ctx->Xp,
748 &m_xm2_s, &ctx->Xp2));
749 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
750 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200751
Neil Armstrong12663092022-06-15 16:00:00 +0200752cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100753 mbedtls_mpi_free(&m_xm2_s);
754 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200755
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200757}
758
Gilles Peskine449bd832023-01-11 14:50:10 +0100759int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
760 unsigned char *buf, size_t len, size_t *olen,
761 int (*f_rng)(void *, unsigned char *, size_t),
762 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200763{
764 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
765 mbedtls_ecp_point K;
766 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
767 size_t x_bytes;
768
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200769 *olen = mbedtls_md_get_size_from_type(ctx->md_type);
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 if (len < *olen) {
771 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
772 }
Neil Armstrong12663092022-06-15 16:00:00 +0200773
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200775
776 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200778 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100779 }
Neil Armstrong12663092022-06-15 16:00:00 +0200780
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200781 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100782 x_bytes = (ctx->grp.pbits + 7) / 8;
783 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
784 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
785 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200786
787cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100788 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200789
Gilles Peskine449bd832023-01-11 14:50:10 +0100790 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200791}
792
Gilles Peskine449bd832023-01-11 14:50:10 +0100793int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
794 unsigned char *buf, size_t len, size_t *olen,
795 int (*f_rng)(void *, unsigned char *, size_t),
796 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200797{
798 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
799 mbedtls_ecp_point K;
800
Gilles Peskine449bd832023-01-11 14:50:10 +0100801 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200802
803 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100804 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200805 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100806 }
Neil Armstrong12663092022-06-15 16:00:00 +0200807
Gilles Peskine449bd832023-01-11 14:50:10 +0100808 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
809 olen, buf, len);
810 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200811 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100812 }
Neil Armstrong12663092022-06-15 16:00:00 +0200813
814cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100815 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200816
Gilles Peskine449bd832023-01-11 14:50:10 +0100817 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200818}
819
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200820#undef ID_MINE
821#undef ID_PEER
822
Hanno Becker616d1ca2018-01-24 10:25:05 +0000823#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200824
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200825#if defined(MBEDTLS_SELF_TEST)
826
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200827#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200828
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200829#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +0100830 !defined(MBEDTLS_MD_CAN_SHA256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100831int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200832{
833 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100834 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200835}
836#else
837
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200838static const unsigned char ecjpake_test_password[] = {
839 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
840 0x65, 0x73, 0x74
841};
842
Steven Cooreman64f27732021-01-11 17:20:10 +0100843#if !defined(MBEDTLS_ECJPAKE_ALT)
844
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200845static const unsigned char ecjpake_test_x1[] = {
846 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
847 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
848 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
849};
850
851static const unsigned char ecjpake_test_x2[] = {
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_x3[] = {
858 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
859 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
860 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
861};
862
863static const unsigned char ecjpake_test_x4[] = {
864 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
865 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
866 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
867};
868
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200869static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200870 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
871 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
872 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
873 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
874 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
875 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
876 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
877 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
878 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
879 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
880 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
881 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
882 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200883 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
884 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
885 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
886 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
887 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
888 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
889 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
890 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
891 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
892 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
893 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
894 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
895 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
896 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
897 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200898};
899
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200900static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200901 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
902 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
903 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
904 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
905 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
906 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
907 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
908 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
909 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
910 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
911 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
912 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
913 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
914 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
915 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
916 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
917 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
918 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
919 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
920 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
921 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
922 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
923 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
924 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
925 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
926 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
927 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
928 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
929};
930
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200931static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200932 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
933 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
934 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
935 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
936 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
937 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
938 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
939 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
940 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
941 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
942 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
943 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
944 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
945 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
946};
947
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200948static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200949 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
950 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
951 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
952 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
953 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
954 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
955 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
956 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
957 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
958 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
959 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
960 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
961 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
962 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
963};
964
Neil Armstrong12663092022-06-15 16:00:00 +0200965static const unsigned char ecjpake_test_shared_key[] = {
966 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
967 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
968 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
969 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
970 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
971 0x17, 0xc3, 0xde, 0x27, 0xb4,
972};
973
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200974static const unsigned char ecjpake_test_pms[] = {
975 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
976 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
977 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
978};
979
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200980/*
981 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
982 *
983 * This is the linear congruential generator from numerical recipes,
984 * except we only use the low byte as the output. See
985 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
986 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100987static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200988{
989 static uint32_t state = 42;
990
991 (void) ctx;
992
Gilles Peskine449bd832023-01-11 14:50:10 +0100993 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200994 state = state * 1664525u + 1013904223u;
995 out[i] = (unsigned char) state;
996 }
997
Gilles Peskine449bd832023-01-11 14:50:10 +0100998 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200999}
1000
Antonin Décimo36e89b52019-01-23 15:24:37 +01001001/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +01001002static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1003 const unsigned char *xm1, size_t len1,
1004 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001005{
Janos Follath24eed8d2019-11-22 13:21:35 +00001006 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001007
Gilles Peskine449bd832023-01-11 14:50:10 +01001008 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1009 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1010 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1011 &ctx->grp.G, self_test_rng, NULL));
1012 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1013 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001014
1015cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001016 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001017}
1018
Steven Cooreman64f27732021-01-11 17:20:10 +01001019#endif /* ! MBEDTLS_ECJPAKE_ALT */
1020
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001021/* For tests we don't need a secure RNG;
1022 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001023static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001024{
1025 static uint32_t x = 42;
1026 (void) p;
1027
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001029 size_t use_len = len > 4 ? 4 : len;
1030 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001031 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001032 out += use_len;
1033 len -= use_len;
1034 }
1035
Gilles Peskine449bd832023-01-11 14:50:10 +01001036 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001037}
1038
Gilles Peskine449bd832023-01-11 14:50:10 +01001039#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001040 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001041 if (x) \
1042 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001043 else \
1044 { \
1045 ret = 1; \
1046 goto cleanup; \
1047 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001048 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001049
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001050/*
1051 * Checkup routine
1052 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001053int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001054{
Janos Follath24eed8d2019-11-22 13:21:35 +00001055 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001056 mbedtls_ecjpake_context cli;
1057 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001058 unsigned char buf[512], pms[32];
1059 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001060
Gilles Peskine449bd832023-01-11 14:50:10 +01001061 mbedtls_ecjpake_init(&cli);
1062 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001063
Gilles Peskine449bd832023-01-11 14:50:10 +01001064 if (verbose != 0) {
1065 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1066 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001067
Gilles Peskine449bd832023-01-11 14:50:10 +01001068 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1069 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1070 ecjpake_test_password,
1071 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001072
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1074 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1075 ecjpake_test_password,
1076 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001077
Gilles Peskine449bd832023-01-11 14:50:10 +01001078 if (verbose != 0) {
1079 mbedtls_printf("passed\n");
1080 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001081
Gilles Peskine449bd832023-01-11 14:50:10 +01001082 if (verbose != 0) {
1083 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1084 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001085
Gilles Peskine449bd832023-01-11 14:50:10 +01001086 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001088
Gilles Peskine449bd832023-01-11 14:50:10 +01001089 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001090
Gilles Peskine449bd832023-01-11 14:50:10 +01001091 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001093
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001095
Gilles Peskine449bd832023-01-11 14:50:10 +01001096 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001098
Gilles Peskine449bd832023-01-11 14:50:10 +01001099 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001100
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001103
Gilles Peskine449bd832023-01-11 14:50:10 +01001104 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001106
Gilles Peskine449bd832023-01-11 14:50:10 +01001107 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001108
Gilles Peskine449bd832023-01-11 14:50:10 +01001109 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001111
Gilles Peskine449bd832023-01-11 14:50:10 +01001112 TEST_ASSERT(len == pmslen);
1113 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001114
Gilles Peskine449bd832023-01-11 14:50:10 +01001115 if (verbose != 0) {
1116 mbedtls_printf("passed\n");
1117 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001118
Steven Cooreman64f27732021-01-11 17:20:10 +01001119#if !defined(MBEDTLS_ECJPAKE_ALT)
1120 /* 'reference handshake' tests can only be run against implementations
1121 * for which we have 100% control over how the random ephemeral keys
Gilles Peskinee820c0a2023-08-03 17:45:20 +02001122 * are generated. This is only the case for the internal Mbed TLS
Steven Cooreman64f27732021-01-11 17:20:10 +01001123 * implementation, so these tests are skipped in case the internal
1124 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001125 if (verbose != 0) {
1126 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1127 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001128
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001129 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001130 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001133
Gilles Peskine449bd832023-01-11 14:50:10 +01001134 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001137
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001138 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001139 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140 ecjpake_test_cli_one,
1141 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001142
Gilles Peskine449bd832023-01-11 14:50:10 +01001143 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144 ecjpake_test_srv_one,
1145 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001146
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001147 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001148 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149 ecjpake_test_srv_two,
1150 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001151
Gilles Peskine449bd832023-01-11 14:50:10 +01001152 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153 ecjpake_test_cli_two,
1154 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001155
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001156 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001157 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001159
Gilles Peskine449bd832023-01-11 14:50:10 +01001160 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001162
Neil Armstrong12663092022-06-15 16:00:00 +02001163 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1165 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001166
Gilles Peskine449bd832023-01-11 14:50:10 +01001167 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1168 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001169
Gilles Peskine449bd832023-01-11 14:50:10 +01001170 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001171
1172 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001173 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001175
Gilles Peskine449bd832023-01-11 14:50:10 +01001176 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001178
Neil Armstrong12663092022-06-15 16:00:00 +02001179 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001180 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1181 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001182
Gilles Peskine449bd832023-01-11 14:50:10 +01001183 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1184 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001185
Gilles Peskine449bd832023-01-11 14:50:10 +01001186 if (verbose != 0) {
1187 mbedtls_printf("passed\n");
1188 }
Steven Cooreman64f27732021-01-11 17:20:10 +01001189#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001190
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001191cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 mbedtls_ecjpake_free(&cli);
1193 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001194
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 if (ret != 0) {
1196 if (verbose != 0) {
1197 mbedtls_printf("failed\n");
1198 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001199
1200 ret = 1;
1201 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001202
Gilles Peskine449bd832023-01-11 14:50:10 +01001203 if (verbose != 0) {
1204 mbedtls_printf("\n");
1205 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001206
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001208}
1209
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001210#undef TEST_ASSERT
1211
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +01001212#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001213
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001214#endif /* MBEDTLS_SELF_TEST */
1215
1216#endif /* MBEDTLS_ECJPAKE_C */