blob: 6355b5ea58414410ce5c01ff57c51739b6bfa45e [file] [log] [blame]
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001/*
2 * Elliptic curve J-PAKE
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020018 */
19
20/*
Manuel Pégourié-Gonnard6b798b92015-08-14 11:18:30 +020021 * References in the code are to the Thread v1.0 Specification,
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +020022 * available to members of the Thread Group http://threadgroup.org/
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020023 */
24
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020026
27#if defined(MBEDTLS_ECJPAKE_C)
28
29#include "mbedtls/ecjpake.h"
Hanno Becker71c8e1b2018-12-14 17:09:39 +000030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +020032
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020033#include <string.h>
34
Hanno Becker616d1ca2018-01-24 10:25:05 +000035#if !defined(MBEDTLS_ECJPAKE_ALT)
36
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +020037/*
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020038 * Convert a mbedtls_ecjpake_role to identifier string
39 */
40static const char * const ecjpake_id[] = {
41 "client",
42 "server"
43};
44
Gilles Peskine449bd832023-01-11 14:50:10 +010045#define ID_MINE (ecjpake_id[ctx->role])
46#define ID_PEER (ecjpake_id[1 - ctx->role])
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020047
Neil Armstrongecaba1c2022-08-11 10:47:08 +020048/**
Gilles Peskine449bd832023-01-11 14:50:10 +010049 * Helper to Compute a hash from md_type
50 */
51static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
52 const unsigned char *input, size_t ilen,
53 unsigned char *output)
Neil Armstrongecaba1c2022-08-11 10:47:08 +020054{
Gilles Peskine449bd832023-01-11 14:50:10 +010055 return mbedtls_md(mbedtls_md_info_from_type(md_type),
56 input, ilen, output);
Neil Armstrongecaba1c2022-08-11 10:47:08 +020057}
58
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +020059/*
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020060 * Initialize context
61 */
Gilles Peskine449bd832023-01-11 14:50:10 +010062void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020063{
Neil Armstrong0d763412022-08-11 10:32:22 +020064 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010065 mbedtls_ecp_group_init(&ctx->grp);
Manuel Pégourié-Gonnardb7da1942015-10-19 13:35:22 +020066 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020067
Gilles Peskine449bd832023-01-11 14:50:10 +010068 mbedtls_ecp_point_init(&ctx->Xm1);
69 mbedtls_ecp_point_init(&ctx->Xm2);
70 mbedtls_ecp_point_init(&ctx->Xp1);
71 mbedtls_ecp_point_init(&ctx->Xp2);
72 mbedtls_ecp_point_init(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020073
Gilles Peskine449bd832023-01-11 14:50:10 +010074 mbedtls_mpi_init(&ctx->xm1);
75 mbedtls_mpi_init(&ctx->xm2);
76 mbedtls_mpi_init(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020077}
78
79/*
80 * Free context
81 */
Gilles Peskine449bd832023-01-11 14:50:10 +010082void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020083{
Gilles Peskine449bd832023-01-11 14:50:10 +010084 if (ctx == NULL) {
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020085 return;
Gilles Peskine449bd832023-01-11 14:50:10 +010086 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020087
Neil Armstrong0d763412022-08-11 10:32:22 +020088 ctx->md_type = MBEDTLS_MD_NONE;
Gilles Peskine449bd832023-01-11 14:50:10 +010089 mbedtls_ecp_group_free(&ctx->grp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020090
Gilles Peskine449bd832023-01-11 14:50:10 +010091 mbedtls_ecp_point_free(&ctx->Xm1);
92 mbedtls_ecp_point_free(&ctx->Xm2);
93 mbedtls_ecp_point_free(&ctx->Xp1);
94 mbedtls_ecp_point_free(&ctx->Xp2);
95 mbedtls_ecp_point_free(&ctx->Xp);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +020096
Gilles Peskine449bd832023-01-11 14:50:10 +010097 mbedtls_mpi_free(&ctx->xm1);
98 mbedtls_mpi_free(&ctx->xm2);
99 mbedtls_mpi_free(&ctx->s);
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200100}
101
102/*
103 * Setup context
104 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100105int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
106 mbedtls_ecjpake_role role,
107 mbedtls_md_type_t hash,
108 mbedtls_ecp_group_id curve,
109 const unsigned char *secret,
110 size_t len)
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200111{
Janos Follath24eed8d2019-11-22 13:21:35 +0000112 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Hanno Becker185e5162018-12-19 09:48:50 +0000113
Gilles Peskine449bd832023-01-11 14:50:10 +0100114 if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
115 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
116 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200117
Manuel Pégourié-Gonnard64493912015-08-13 20:19:51 +0200118 ctx->role = role;
119
Gilles Peskine449bd832023-01-11 14:50:10 +0100120 if ((mbedtls_md_info_from_type(hash)) == NULL) {
121 return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
122 }
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200123
Neil Armstrong0d763412022-08-11 10:32:22 +0200124 ctx->md_type = hash;
125
Gilles Peskine449bd832023-01-11 14:50:10 +0100126 MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200127
Gilles Peskine449bd832023-01-11 14:50:10 +0100128 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200129
130cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (ret != 0) {
132 mbedtls_ecjpake_free(ctx);
133 }
Manuel Pégourié-Gonnard23dcbe32015-08-13 09:37:00 +0200134
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 return ret;
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200136}
137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
139 int point_format)
Gilles Peskinecd07e222021-05-27 23:17:34 +0200140{
Gilles Peskine449bd832023-01-11 14:50:10 +0100141 switch (point_format) {
Gilles Peskinecd07e222021-05-27 23:17:34 +0200142 case MBEDTLS_ECP_PF_UNCOMPRESSED:
143 case MBEDTLS_ECP_PF_COMPRESSED:
144 ctx->point_format = point_format;
Gilles Peskine449bd832023-01-11 14:50:10 +0100145 return 0;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200146 default:
Gilles Peskine449bd832023-01-11 14:50:10 +0100147 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskinecd07e222021-05-27 23:17:34 +0200148 }
149}
150
Manuel Pégourié-Gonnard7af8bc12015-08-12 16:58:50 +0200151/*
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200152 * Check if context is ready for use
153 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100154int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200155{
Gilles Peskine449bd832023-01-11 14:50:10 +0100156 if (ctx->md_type == MBEDTLS_MD_NONE ||
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200157 ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
Gilles Peskine449bd832023-01-11 14:50:10 +0100158 ctx->s.p == NULL) {
159 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200160 }
161
Gilles Peskine449bd832023-01-11 14:50:10 +0100162 return 0;
Manuel Pégourié-Gonnardb813acc2015-09-15 15:34:09 +0200163}
164
165/*
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200166 * Write a point plus its length to a buffer
167 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100168static int ecjpake_write_len_point(unsigned char **p,
169 const unsigned char *end,
170 const mbedtls_ecp_group *grp,
171 const int pf,
172 const mbedtls_ecp_point *P)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200173{
Janos Follath24eed8d2019-11-22 13:21:35 +0000174 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200175 size_t len;
176
177 /* Need at least 4 for length plus 1 for point */
Gilles Peskine449bd832023-01-11 14:50:10 +0100178 if (end < *p || end - *p < 5) {
179 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
180 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 ret = mbedtls_ecp_point_write_binary(grp, P, pf,
183 &len, *p + 4, end - (*p + 4));
184 if (ret != 0) {
185 return ret;
186 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200187
Gilles Peskine449bd832023-01-11 14:50:10 +0100188 MBEDTLS_PUT_UINT32_BE(len, *p, 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200189
190 *p += 4 + len;
191
Gilles Peskine449bd832023-01-11 14:50:10 +0100192 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200193}
194
195/*
196 * Size of the temporary buffer for ecjpake_hash:
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200197 * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200198 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100199#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200200
201/*
202 * Compute hash for ZKP (7.4.2.2.2.1)
203 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100204static int ecjpake_hash(const mbedtls_md_type_t md_type,
205 const mbedtls_ecp_group *grp,
206 const int pf,
207 const mbedtls_ecp_point *G,
208 const mbedtls_ecp_point *V,
209 const mbedtls_ecp_point *X,
210 const char *id,
211 mbedtls_mpi *h)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200212{
Janos Follath24eed8d2019-11-22 13:21:35 +0000213 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200214 unsigned char buf[ECJPAKE_HASH_BUF_LEN];
215 unsigned char *p = buf;
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 const unsigned char *end = buf + sizeof(buf);
217 const size_t id_len = strlen(id);
Manuel Pégourié-Gonnard88579842023-03-28 11:20:23 +0200218 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200219
220 /* Write things to temporary buffer */
Gilles Peskine449bd832023-01-11 14:50:10 +0100221 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
222 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
223 MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200224
Gilles Peskine449bd832023-01-11 14:50:10 +0100225 if (end - p < 4) {
226 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
227 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200228
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
Joe Subbiania5cb0d22021-08-23 11:35:25 +0100230 p += 4;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200231
Gilles Peskine449bd832023-01-11 14:50:10 +0100232 if (end < p || (size_t) (end - p) < id_len) {
233 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
234 }
Manuel Pégourié-Gonnard4b20c0e2015-10-20 16:16:38 +0200235
Gilles Peskine449bd832023-01-11 14:50:10 +0100236 memcpy(p, id, id_len);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200237 p += id_len;
238
239 /* Compute hash */
Gilles Peskine449bd832023-01-11 14:50:10 +0100240 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
241 buf, p - buf, hash));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200242
243 /* Turn it into an integer mod n */
Gilles Peskine449bd832023-01-11 14:50:10 +0100244 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200245 mbedtls_md_get_size_from_type(md_type)));
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200247
248cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 return ret;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200250}
251
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +0200252/*
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200253 * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
254 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100255static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
256 const mbedtls_ecp_group *grp,
257 const int pf,
258 const mbedtls_ecp_point *G,
259 const mbedtls_ecp_point *X,
260 const char *id,
261 const unsigned char **p,
262 const unsigned char *end)
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200263{
Janos Follath24eed8d2019-11-22 13:21:35 +0000264 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200265 mbedtls_ecp_point V, VV;
266 mbedtls_mpi r, h;
267 size_t r_len;
268
Gilles Peskine449bd832023-01-11 14:50:10 +0100269 mbedtls_ecp_point_init(&V);
270 mbedtls_ecp_point_init(&VV);
271 mbedtls_mpi_init(&r);
272 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200273
274 /*
275 * struct {
276 * ECPoint V;
277 * opaque r<1..2^8-1>;
278 * } ECSchnorrZKP;
279 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if (end < *p) {
281 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
282 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200285
Gilles Peskine449bd832023-01-11 14:50:10 +0100286 if (end < *p || (size_t) (end - *p) < 1) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200287 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
288 goto cleanup;
289 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200290
291 r_len = *(*p)++;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200292
Gilles Peskine449bd832023-01-11 14:50:10 +0100293 if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200294 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
295 goto cleanup;
296 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200297
Gilles Peskine449bd832023-01-11 14:50:10 +0100298 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200299 *p += r_len;
300
301 /*
302 * Verification
303 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100304 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
305 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
306 &VV, &h, X, &r, G));
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200307
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
Manuel Pégourié-Gonnard4f2cd952015-08-12 11:17:55 +0200309 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
310 goto cleanup;
311 }
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200312
313cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 mbedtls_ecp_point_free(&V);
315 mbedtls_ecp_point_free(&VV);
316 mbedtls_mpi_free(&r);
317 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200318
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 return ret;
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200320}
321
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200322/*
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200323 * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
324 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100325static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
326 const mbedtls_ecp_group *grp,
327 const int pf,
328 const mbedtls_ecp_point *G,
329 const mbedtls_mpi *x,
330 const mbedtls_ecp_point *X,
331 const char *id,
332 unsigned char **p,
333 const unsigned char *end,
334 int (*f_rng)(void *, unsigned char *, size_t),
335 void *p_rng)
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200336{
Janos Follath24eed8d2019-11-22 13:21:35 +0000337 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200338 mbedtls_ecp_point V;
339 mbedtls_mpi v;
340 mbedtls_mpi h; /* later recycled to hold r */
341 size_t len;
342
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 if (end < *p) {
344 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
345 }
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200346
Gilles Peskine449bd832023-01-11 14:50:10 +0100347 mbedtls_ecp_point_init(&V);
348 mbedtls_mpi_init(&v);
349 mbedtls_mpi_init(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200350
351 /* Compute signature */
Gilles Peskine449bd832023-01-11 14:50:10 +0100352 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
353 G, &v, &V, f_rng, p_rng));
354 MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
355 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
356 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
357 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200358
359 /* Write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
361 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200362 *p += len;
363
Gilles Peskine449bd832023-01-11 14:50:10 +0100364 len = mbedtls_mpi_size(&h); /* actually r */
365 if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200366 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
367 goto cleanup;
368 }
369
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 *(*p)++ = MBEDTLS_BYTE_0(len);
371 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200372 *p += len;
373
374cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 mbedtls_ecp_point_free(&V);
376 mbedtls_mpi_free(&v);
377 mbedtls_mpi_free(&h);
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200378
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 return ret;
Manuel Pégourié-Gonnard3aed1852015-08-12 14:53:56 +0200380}
381
382/*
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200383 * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
384 * Output: verified public key X
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200385 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100386static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
387 const mbedtls_ecp_group *grp,
388 const int pf,
389 const mbedtls_ecp_point *G,
390 mbedtls_ecp_point *X,
391 const char *id,
392 const unsigned char **p,
393 const unsigned char *end)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200394{
Janos Follath24eed8d2019-11-22 13:21:35 +0000395 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200396
Gilles Peskine449bd832023-01-11 14:50:10 +0100397 if (end < *p) {
398 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
399 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200400
401 /*
402 * struct {
403 * ECPoint X;
404 * ECSchnorrZKP zkp;
405 * } ECJPAKEKeyKP;
406 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100407 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
408 if (mbedtls_ecp_is_zero(X)) {
Manuel Pégourié-Gonnard30590952015-08-17 10:37:40 +0200409 ret = MBEDTLS_ERR_ECP_INVALID_KEY;
410 goto cleanup;
411 }
412
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200414
415cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200417}
418
419/*
420 * Generate an ECJPAKEKeyKP
421 * Output: the serialized structure, plus private/public key pair
422 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100423static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
424 const mbedtls_ecp_group *grp,
425 const int pf,
426 const mbedtls_ecp_point *G,
427 mbedtls_mpi *x,
428 mbedtls_ecp_point *X,
429 const char *id,
430 unsigned char **p,
431 const unsigned char *end,
432 int (*f_rng)(void *, unsigned char *, size_t),
433 void *p_rng)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200434{
Janos Follath24eed8d2019-11-22 13:21:35 +0000435 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200436 size_t len;
437
Gilles Peskine449bd832023-01-11 14:50:10 +0100438 if (end < *p) {
439 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
440 }
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200441
442 /* Generate key (7.4.2.3.1) and write it out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100443 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
444 f_rng, p_rng));
445 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
446 pf, &len, *p, end - *p));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200447 *p += len;
448
449 /* Generate and write proof */
Gilles Peskine449bd832023-01-11 14:50:10 +0100450 MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
451 p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200452
453cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100454 return ret;
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200455}
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +0200456
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200457/*
458 * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
Shaun Case8b0ecbc2021-12-20 21:14:10 -0800459 * Outputs: verified peer public keys Xa, Xb
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200460 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100461static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
462 const mbedtls_ecp_group *grp,
463 const int pf,
464 const mbedtls_ecp_point *G,
465 mbedtls_ecp_point *Xa,
466 mbedtls_ecp_point *Xb,
467 const char *id,
468 const unsigned char *buf,
469 size_t len)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200470{
Janos Follath24eed8d2019-11-22 13:21:35 +0000471 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard9028c5a2015-08-12 14:51:36 +0200472 const unsigned char *p = buf;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200473 const unsigned char *end = buf + len;
474
475 /*
476 * struct {
477 * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
478 * } ECJPAKEKeyKPPairList;
479 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100480 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
481 MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (p != end) {
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200484 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100485 }
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200486
487cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200489}
490
491/*
492 * Generate a ECJPAKEKeyKPPairList
493 * Outputs: the serialized structure, plus two private/public key pairs
494 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100495static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
496 const mbedtls_ecp_group *grp,
497 const int pf,
498 const mbedtls_ecp_point *G,
499 mbedtls_mpi *xm1,
500 mbedtls_ecp_point *Xa,
501 mbedtls_mpi *xm2,
502 mbedtls_ecp_point *Xb,
503 const char *id,
504 unsigned char *buf,
505 size_t len,
506 size_t *olen,
507 int (*f_rng)(void *, unsigned char *, size_t),
508 void *p_rng)
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200509{
Janos Follath24eed8d2019-11-22 13:21:35 +0000510 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200511 unsigned char *p = buf;
512 const unsigned char *end = buf + len;
513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
515 &p, end, f_rng, p_rng));
516 MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
517 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200518
519 *olen = p - buf;
520
521cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 return ret;
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200523}
524
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200525/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200526 * Read and process the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200527 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100528int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
529 const unsigned char *buf,
530 size_t len)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200531{
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
533 &ctx->grp.G,
534 &ctx->Xp1, &ctx->Xp2, ID_PEER,
535 buf, len);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200536}
537
538/*
Manuel Pégourié-Gonnardd8204a72015-08-14 13:36:55 +0200539 * Generate and write the first round message
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200540 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100541int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
542 unsigned char *buf, size_t len, size_t *olen,
543 int (*f_rng)(void *, unsigned char *, size_t),
544 void *p_rng)
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200545{
Gilles Peskine449bd832023-01-11 14:50:10 +0100546 return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
547 &ctx->grp.G,
548 &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
549 ID_MINE, buf, len, olen, f_rng, p_rng);
Manuel Pégourié-Gonnard4e8bc782015-08-12 20:50:31 +0200550}
551
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200552/*
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200553 * Compute the sum of three points R = A + B + C
554 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100555static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
556 const mbedtls_ecp_point *A,
557 const mbedtls_ecp_point *B,
558 const mbedtls_ecp_point *C)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200559{
Janos Follath24eed8d2019-11-22 13:21:35 +0000560 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200561 mbedtls_mpi one;
562
Gilles Peskine449bd832023-01-11 14:50:10 +0100563 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200564
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
566 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
567 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200568
569cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100570 mbedtls_mpi_free(&one);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200571
Gilles Peskine449bd832023-01-11 14:50:10 +0100572 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200573}
574
575/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200576 * 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 +0200577 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100578int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
579 const unsigned char *buf,
580 size_t len)
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200581{
Janos Follath24eed8d2019-11-22 13:21:35 +0000582 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200583 const unsigned char *p = buf;
584 const unsigned char *end = buf + len;
585 mbedtls_ecp_group grp;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200586 mbedtls_ecp_point G; /* C: GB, S: GA */
Hanno Becker185e5162018-12-19 09:48:50 +0000587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588 mbedtls_ecp_group_init(&grp);
589 mbedtls_ecp_point_init(&G);
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200590
591 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200592 * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
593 * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
594 * Unified: G = Xm1 + Xm2 + Xp1
Manuel Pégourié-Gonnardce456762015-08-14 11:54:35 +0200595 * We need that before parsing in order to check Xp as we read it
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200596 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100597 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
598 &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200599
600 /*
601 * struct {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200602 * ECParameters curve_params; // only client reading server msg
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200603 * ECJPAKEKeyKP ecjpake_key_kp;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200604 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200605 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100606 if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
607 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
608 if (grp.id != ctx->grp.id) {
Manuel Pégourié-Gonnardd9802af2015-08-17 12:47:38 +0200609 ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
610 goto cleanup;
611 }
612 }
613
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
615 ctx->point_format,
616 &G, &ctx->Xp, ID_PEER, &p, end));
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200617
Gilles Peskine449bd832023-01-11 14:50:10 +0100618 if (p != end) {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200619 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
620 goto cleanup;
621 }
622
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200623cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100624 mbedtls_ecp_group_free(&grp);
625 mbedtls_ecp_point_free(&G);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200626
Gilles Peskine449bd832023-01-11 14:50:10 +0100627 return ret;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200628}
629
630/*
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200631 * Compute R = +/- X * S mod N, taking care not to leak S
632 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100633static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
634 const mbedtls_mpi *X,
635 const mbedtls_mpi *S,
636 const mbedtls_mpi *N,
637 int (*f_rng)(void *, unsigned char *, size_t),
638 void *p_rng)
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200639{
Janos Follath24eed8d2019-11-22 13:21:35 +0000640 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200641 mbedtls_mpi b; /* Blinding value, then s + N * blinding */
642
Gilles Peskine449bd832023-01-11 14:50:10 +0100643 mbedtls_mpi_init(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200644
645 /* b = s + rnd-128-bit * N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100646 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
647 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
648 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200649
650 /* R = sign * X * b mod N */
Gilles Peskine449bd832023-01-11 14:50:10 +0100651 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200652 R->s *= sign;
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200654
655cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100656 mbedtls_mpi_free(&b);
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200657
Gilles Peskine449bd832023-01-11 14:50:10 +0100658 return ret;
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200659}
660
661/*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200662 * 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 +0200663 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100664int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
665 unsigned char *buf, size_t len, size_t *olen,
666 int (*f_rng)(void *, unsigned char *, size_t),
667 void *p_rng)
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200668{
Janos Follath24eed8d2019-11-22 13:21:35 +0000669 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200670 mbedtls_ecp_point G; /* C: GA, S: GB */
671 mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
672 mbedtls_mpi xm; /* C: xc, S: xs */
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200673 unsigned char *p = buf;
674 const unsigned char *end = buf + len;
675 size_t ec_len;
Hanno Becker185e5162018-12-19 09:48:50 +0000676
Gilles Peskine449bd832023-01-11 14:50:10 +0100677 mbedtls_ecp_point_init(&G);
678 mbedtls_ecp_point_init(&Xm);
679 mbedtls_mpi_init(&xm);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200680
681 /*
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200682 * 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 +0200683 *
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200684 * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
685 * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
686 * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200687 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100688 MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
689 &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
690 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
691 &ctx->grp.N, f_rng, p_rng));
692 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200693
694 /*
695 * Now write things out
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200696 *
697 * struct {
698 * ECParameters curve_params; // only server writing its message
699 * ECJPAKEKeyKP ecjpake_key_kp;
700 * } Client/ServerECJPAKEParams;
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200701 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
703 if (end < p) {
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200704 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
705 goto cleanup;
706 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100707 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
708 p, end - p));
Manuel Pégourié-Gonnarde1927102015-08-14 14:20:48 +0200709 p += ec_len;
710 }
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200711
Gilles Peskine449bd832023-01-11 14:50:10 +0100712 if (end < p) {
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200713 ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
714 goto cleanup;
715 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100716 MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
717 ctx->point_format, &ec_len, p, end - p));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200718 p += ec_len;
719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720 MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
721 ctx->point_format,
722 &G, &xm, &Xm, ID_MINE,
723 &p, end, f_rng, p_rng));
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +0200724
725 *olen = p - buf;
726
727cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 mbedtls_ecp_point_free(&G);
729 mbedtls_ecp_point_free(&Xm);
730 mbedtls_mpi_free(&xm);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200731
Gilles Peskine449bd832023-01-11 14:50:10 +0100732 return ret;
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +0200733}
734
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200735/*
736 * Derive PMS (7.4.2.7 / 7.4.2.8)
737 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100738static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
739 mbedtls_ecp_point *K,
740 int (*f_rng)(void *, unsigned char *, size_t),
741 void *p_rng)
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200742{
Janos Follath24eed8d2019-11-22 13:21:35 +0000743 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200744 mbedtls_mpi m_xm2_s, one;
Hanno Becker185e5162018-12-19 09:48:50 +0000745
Gilles Peskine449bd832023-01-11 14:50:10 +0100746 mbedtls_mpi_init(&m_xm2_s);
747 mbedtls_mpi_init(&one);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200748
Gilles Peskine449bd832023-01-11 14:50:10 +0100749 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200750
751 /*
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200752 * Client: K = ( Xs - X4 * x2 * s ) * x2
753 * Server: K = ( Xc - X2 * x4 * s ) * x4
Manuel Pégourié-Gonnardd0d8a932015-08-14 15:14:50 +0200754 * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200755 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
757 &ctx->grp.N, f_rng, p_rng));
758 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
759 &one, &ctx->Xp,
760 &m_xm2_s, &ctx->Xp2));
761 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
762 f_rng, p_rng));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200763
Neil Armstrong12663092022-06-15 16:00:00 +0200764cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100765 mbedtls_mpi_free(&m_xm2_s);
766 mbedtls_mpi_free(&one);
Neil Armstrong12663092022-06-15 16:00:00 +0200767
Gilles Peskine449bd832023-01-11 14:50:10 +0100768 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200769}
770
Gilles Peskine449bd832023-01-11 14:50:10 +0100771int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
772 unsigned char *buf, size_t len, size_t *olen,
773 int (*f_rng)(void *, unsigned char *, size_t),
774 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200775{
776 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
777 mbedtls_ecp_point K;
778 unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
779 size_t x_bytes;
780
Manuel Pégourié-Gonnard9b41eb82023-03-28 11:14:24 +0200781 *olen = mbedtls_md_get_size_from_type(ctx->md_type);
Gilles Peskine449bd832023-01-11 14:50:10 +0100782 if (len < *olen) {
783 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
784 }
Neil Armstrong12663092022-06-15 16:00:00 +0200785
Gilles Peskine449bd832023-01-11 14:50:10 +0100786 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200787
788 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200790 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100791 }
Neil Armstrong12663092022-06-15 16:00:00 +0200792
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200793 /* PMS = SHA-256( K.X ) */
Gilles Peskine449bd832023-01-11 14:50:10 +0100794 x_bytes = (ctx->grp.pbits + 7) / 8;
795 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
796 MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
797 kx, x_bytes, buf));
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200798
799cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100800 mbedtls_ecp_point_free(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200801
Gilles Peskine449bd832023-01-11 14:50:10 +0100802 return ret;
Neil Armstrong12663092022-06-15 16:00:00 +0200803}
804
Gilles Peskine449bd832023-01-11 14:50:10 +0100805int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
806 unsigned char *buf, size_t len, size_t *olen,
807 int (*f_rng)(void *, unsigned char *, size_t),
808 void *p_rng)
Neil Armstrong12663092022-06-15 16:00:00 +0200809{
810 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
811 mbedtls_ecp_point K;
812
Gilles Peskine449bd832023-01-11 14:50:10 +0100813 mbedtls_ecp_point_init(&K);
Neil Armstrong12663092022-06-15 16:00:00 +0200814
815 ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
Gilles Peskine449bd832023-01-11 14:50:10 +0100816 if (ret) {
Neil Armstrong12663092022-06-15 16:00:00 +0200817 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100818 }
Neil Armstrong12663092022-06-15 16:00:00 +0200819
Gilles Peskine449bd832023-01-11 14:50:10 +0100820 ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
821 olen, buf, len);
822 if (ret != 0) {
Neil Armstrong12663092022-06-15 16:00:00 +0200823 goto cleanup;
Gilles Peskine449bd832023-01-11 14:50:10 +0100824 }
Neil Armstrong12663092022-06-15 16:00:00 +0200825
826cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100827 mbedtls_ecp_point_free(&K);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200828
Gilles Peskine449bd832023-01-11 14:50:10 +0100829 return ret;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200830}
831
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200832#undef ID_MINE
833#undef ID_PEER
834
Hanno Becker616d1ca2018-01-24 10:25:05 +0000835#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnarde0ad57b2015-08-14 11:10:39 +0200836
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200837#if defined(MBEDTLS_SELF_TEST)
838
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200839#include "mbedtls/platform.h"
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +0200840
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200841#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +0100842 !defined(MBEDTLS_MD_CAN_SHA256)
Gilles Peskine449bd832023-01-11 14:50:10 +0100843int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200844{
845 (void) verbose;
Gilles Peskine449bd832023-01-11 14:50:10 +0100846 return 0;
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200847}
848#else
849
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200850static const unsigned char ecjpake_test_password[] = {
851 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
852 0x65, 0x73, 0x74
853};
854
Steven Cooreman64f27732021-01-11 17:20:10 +0100855#if !defined(MBEDTLS_ECJPAKE_ALT)
856
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +0200857static const unsigned char ecjpake_test_x1[] = {
858 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
859 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
860 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
861};
862
863static const unsigned char ecjpake_test_x2[] = {
864 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
865 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
866 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
867};
868
869static const unsigned char ecjpake_test_x3[] = {
870 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
871 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
872 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
873};
874
875static const unsigned char ecjpake_test_x4[] = {
876 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
877 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
878 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
879};
880
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200881static const unsigned char ecjpake_test_cli_one[] = {
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +0200882 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
883 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
884 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
885 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
886 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
887 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
888 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
889 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
890 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
891 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
892 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
893 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
894 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
Manuel Pégourié-Gonnard082767f2015-08-12 14:43:57 +0200895 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
896 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
897 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
898 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
899 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
900 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
901 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
902 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
903 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
904 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
905 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
906 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
907 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
908 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
909 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +0200910};
911
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200912static const unsigned char ecjpake_test_srv_one[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200913 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
914 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
915 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
916 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
917 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
918 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
919 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
920 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
921 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
922 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
923 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
924 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
925 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
926 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
927 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
928 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
929 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
930 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
931 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
932 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
933 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
934 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
935 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
936 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
937 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
938 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
939 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
940 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
941};
942
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200943static const unsigned char ecjpake_test_srv_two[] = {
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +0200944 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
945 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
946 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
947 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
948 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
949 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
950 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
951 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
952 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
953 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
954 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
955 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
956 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
957 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
958};
959
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +0200960static const unsigned char ecjpake_test_cli_two[] = {
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +0200961 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
962 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
963 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
964 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
965 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
966 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
967 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
968 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
969 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
970 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
971 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
972 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
973 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
974 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
975};
976
Neil Armstrong12663092022-06-15 16:00:00 +0200977static const unsigned char ecjpake_test_shared_key[] = {
978 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
979 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
980 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
981 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
982 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
983 0x17, 0xc3, 0xde, 0x27, 0xb4,
984};
985
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +0200986static const unsigned char ecjpake_test_pms[] = {
987 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
988 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
989 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
990};
991
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +0200992/*
993 * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
994 *
995 * This is the linear congruential generator from numerical recipes,
996 * except we only use the low byte as the output. See
997 * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
998 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100999static int self_test_rng(void *ctx, unsigned char *out, size_t len)
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001000{
1001 static uint32_t state = 42;
1002
1003 (void) ctx;
1004
Gilles Peskine449bd832023-01-11 14:50:10 +01001005 for (size_t i = 0; i < len; i++) {
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001006 state = state * 1664525u + 1013904223u;
1007 out[i] = (unsigned char) state;
1008 }
1009
Gilles Peskine449bd832023-01-11 14:50:10 +01001010 return 0;
Manuel Pégourié-Gonnardaa3ed6f2021-06-15 11:29:26 +02001011}
1012
Antonin Décimo36e89b52019-01-23 15:24:37 +01001013/* Load my private keys and generate the corresponding public keys */
Gilles Peskine449bd832023-01-11 14:50:10 +01001014static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1015 const unsigned char *xm1, size_t len1,
1016 const unsigned char *xm2, size_t len2)
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001017{
Janos Follath24eed8d2019-11-22 13:21:35 +00001018 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001019
Gilles Peskine449bd832023-01-11 14:50:10 +01001020 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1021 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1022 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1023 &ctx->grp.G, self_test_rng, NULL));
1024 MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1025 &ctx->grp.G, self_test_rng, NULL));
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001026
1027cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001028 return ret;
Manuel Pégourié-Gonnarde2d3a4e2015-08-14 12:03:04 +02001029}
1030
Steven Cooreman64f27732021-01-11 17:20:10 +01001031#endif /* ! MBEDTLS_ECJPAKE_ALT */
1032
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001033/* For tests we don't need a secure RNG;
1034 * use the LGC from Numerical Recipes for simplicity */
Gilles Peskine449bd832023-01-11 14:50:10 +01001035static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001036{
1037 static uint32_t x = 42;
1038 (void) p;
1039
Gilles Peskine449bd832023-01-11 14:50:10 +01001040 while (len > 0) {
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001041 size_t use_len = len > 4 ? 4 : len;
1042 x = 1664525 * x + 1013904223;
Gilles Peskine449bd832023-01-11 14:50:10 +01001043 memcpy(out, &x, use_len);
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001044 out += use_len;
1045 len -= use_len;
1046 }
1047
Gilles Peskine449bd832023-01-11 14:50:10 +01001048 return 0;
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001049}
1050
Gilles Peskine449bd832023-01-11 14:50:10 +01001051#define TEST_ASSERT(x) \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001052 do { \
Gilles Peskine449bd832023-01-11 14:50:10 +01001053 if (x) \
1054 ret = 0; \
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001055 else \
1056 { \
1057 ret = 1; \
1058 goto cleanup; \
1059 } \
Gilles Peskine449bd832023-01-11 14:50:10 +01001060 } while (0)
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001061
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001062/*
1063 * Checkup routine
1064 */
Gilles Peskine449bd832023-01-11 14:50:10 +01001065int mbedtls_ecjpake_self_test(int verbose)
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001066{
Janos Follath24eed8d2019-11-22 13:21:35 +00001067 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001068 mbedtls_ecjpake_context cli;
1069 mbedtls_ecjpake_context srv;
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001070 unsigned char buf[512], pms[32];
1071 size_t len, pmslen;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001072
Gilles Peskine449bd832023-01-11 14:50:10 +01001073 mbedtls_ecjpake_init(&cli);
1074 mbedtls_ecjpake_init(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001075
Gilles Peskine449bd832023-01-11 14:50:10 +01001076 if (verbose != 0) {
1077 mbedtls_printf(" ECJPAKE test #0 (setup): ");
1078 }
Manuel Pégourié-Gonnardcb7cd032015-08-13 10:09:10 +02001079
Gilles Peskine449bd832023-01-11 14:50:10 +01001080 TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1081 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1082 ecjpake_test_password,
1083 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001084
Gilles Peskine449bd832023-01-11 14:50:10 +01001085 TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1086 MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1087 ecjpake_test_password,
1088 sizeof(ecjpake_test_password)) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001089
Gilles Peskine449bd832023-01-11 14:50:10 +01001090 if (verbose != 0) {
1091 mbedtls_printf("passed\n");
1092 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001093
Gilles Peskine449bd832023-01-11 14:50:10 +01001094 if (verbose != 0) {
1095 mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
1096 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001097
Gilles Peskine449bd832023-01-11 14:50:10 +01001098 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1099 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001100
Gilles Peskine449bd832023-01-11 14:50:10 +01001101 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001102
Gilles Peskine449bd832023-01-11 14:50:10 +01001103 TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1104 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001105
Gilles Peskine449bd832023-01-11 14:50:10 +01001106 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001107
Gilles Peskine449bd832023-01-11 14:50:10 +01001108 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1109 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001110
Gilles Peskine449bd832023-01-11 14:50:10 +01001111 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
Manuel Pégourié-Gonnardbed9e412015-08-13 18:53:59 +02001112
Gilles Peskine449bd832023-01-11 14:50:10 +01001113 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1114 pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001115
Gilles Peskine449bd832023-01-11 14:50:10 +01001116 TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1117 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001118
Gilles Peskine449bd832023-01-11 14:50:10 +01001119 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
Manuel Pégourié-Gonnard614bd5e2015-08-13 20:19:16 +02001120
Gilles Peskine449bd832023-01-11 14:50:10 +01001121 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1122 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001123
Gilles Peskine449bd832023-01-11 14:50:10 +01001124 TEST_ASSERT(len == pmslen);
1125 TEST_ASSERT(memcmp(buf, pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001126
Gilles Peskine449bd832023-01-11 14:50:10 +01001127 if (verbose != 0) {
1128 mbedtls_printf("passed\n");
1129 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001130
Steven Cooreman64f27732021-01-11 17:20:10 +01001131#if !defined(MBEDTLS_ECJPAKE_ALT)
1132 /* 'reference handshake' tests can only be run against implementations
1133 * for which we have 100% control over how the random ephemeral keys
Gilles Peskinee820c0a2023-08-03 17:45:20 +02001134 * are generated. This is only the case for the internal Mbed TLS
Steven Cooreman64f27732021-01-11 17:20:10 +01001135 * implementation, so these tests are skipped in case the internal
1136 * implementation is swapped out for an alternative one. */
Gilles Peskine449bd832023-01-11 14:50:10 +01001137 if (verbose != 0) {
1138 mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
1139 }
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001140
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001141 /* Simulate generation of round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001142 MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1143 ecjpake_test_x1, sizeof(ecjpake_test_x1),
1144 ecjpake_test_x2, sizeof(ecjpake_test_x2)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001145
Gilles Peskine449bd832023-01-11 14:50:10 +01001146 MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1147 ecjpake_test_x3, sizeof(ecjpake_test_x3),
1148 ecjpake_test_x4, sizeof(ecjpake_test_x4)));
Manuel Pégourié-Gonnard8d31e802015-08-13 14:44:57 +02001149
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001150 /* Read round one */
Gilles Peskine449bd832023-01-11 14:50:10 +01001151 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1152 ecjpake_test_cli_one,
1153 sizeof(ecjpake_test_cli_one)) == 0);
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001154
Gilles Peskine449bd832023-01-11 14:50:10 +01001155 TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1156 ecjpake_test_srv_one,
1157 sizeof(ecjpake_test_srv_one)) == 0);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001158
Manuel Pégourié-Gonnardc9070812015-08-14 14:48:50 +02001159 /* Skip generation of round two, read round two */
Gilles Peskine449bd832023-01-11 14:50:10 +01001160 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1161 ecjpake_test_srv_two,
1162 sizeof(ecjpake_test_srv_two)) == 0);
Manuel Pégourié-Gonnard6029a852015-08-11 15:44:41 +02001163
Gilles Peskine449bd832023-01-11 14:50:10 +01001164 TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1165 ecjpake_test_cli_two,
1166 sizeof(ecjpake_test_cli_two)) == 0);
Manuel Pégourié-Gonnardec0eece2015-08-13 19:13:20 +02001167
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001168 /* Server derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001169 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1170 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001171
Gilles Peskine449bd832023-01-11 14:50:10 +01001172 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1173 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001174
Neil Armstrong12663092022-06-15 16:00:00 +02001175 /* Server derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001176 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1177 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001178
Gilles Peskine449bd832023-01-11 14:50:10 +01001179 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1180 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001181
Gilles Peskine449bd832023-01-11 14:50:10 +01001182 memset(buf, 0, len); /* Avoid interferences with next step */
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001183
1184 /* Client derives PMS */
Gilles Peskine449bd832023-01-11 14:50:10 +01001185 TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1186 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001187
Gilles Peskine449bd832023-01-11 14:50:10 +01001188 TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1189 TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
Manuel Pégourié-Gonnard5f188292015-08-14 10:52:39 +02001190
Neil Armstrong12663092022-06-15 16:00:00 +02001191 /* Client derives K as unsigned binary data */
Gilles Peskine449bd832023-01-11 14:50:10 +01001192 TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1193 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001194
Gilles Peskine449bd832023-01-11 14:50:10 +01001195 TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1196 TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
Neil Armstrong12663092022-06-15 16:00:00 +02001197
Gilles Peskine449bd832023-01-11 14:50:10 +01001198 if (verbose != 0) {
1199 mbedtls_printf("passed\n");
1200 }
Steven Cooreman64f27732021-01-11 17:20:10 +01001201#endif /* ! MBEDTLS_ECJPAKE_ALT */
Manuel Pégourié-Gonnard8489f172015-08-07 17:47:39 +02001202
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001203cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +01001204 mbedtls_ecjpake_free(&cli);
1205 mbedtls_ecjpake_free(&srv);
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001206
Gilles Peskine449bd832023-01-11 14:50:10 +01001207 if (ret != 0) {
1208 if (verbose != 0) {
1209 mbedtls_printf("failed\n");
1210 }
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001211
1212 ret = 1;
1213 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001214
Gilles Peskine449bd832023-01-11 14:50:10 +01001215 if (verbose != 0) {
1216 mbedtls_printf("\n");
1217 }
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001218
Gilles Peskine449bd832023-01-11 14:50:10 +01001219 return ret;
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001220}
1221
Manuel Pégourié-Gonnardb1b250b2015-08-12 11:01:58 +02001222#undef TEST_ASSERT
1223
Manuel Pégourié-Gonnardb2eb1f72023-03-15 00:12:24 +01001224#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
Manuel Pégourié-Gonnard3dbf2fb2015-08-06 17:24:39 +02001225
Manuel Pégourié-Gonnard4d8685b2015-08-05 15:44:42 +02001226#endif /* MBEDTLS_SELF_TEST */
1227
1228#endif /* MBEDTLS_ECJPAKE_C */