1817466cbSJens Wiklander /*
2817466cbSJens Wiklander * Elliptic curve J-PAKE
3817466cbSJens Wiklander *
47901324dSJerome Forissier * Copyright The Mbed TLS Contributors
5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6817466cbSJens Wiklander */
7817466cbSJens Wiklander
8817466cbSJens Wiklander /*
9817466cbSJens Wiklander * References in the code are to the Thread v1.0 Specification,
10817466cbSJens Wiklander * available to members of the Thread Group http://threadgroup.org/
11817466cbSJens Wiklander */
12817466cbSJens Wiklander
137901324dSJerome Forissier #include "common.h"
14817466cbSJens Wiklander
15817466cbSJens Wiklander #if defined(MBEDTLS_ECJPAKE_C)
16817466cbSJens Wiklander
17817466cbSJens Wiklander #include "mbedtls/ecjpake.h"
183d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
1911fa71b9SJerome Forissier #include "mbedtls/error.h"
20817466cbSJens Wiklander
21817466cbSJens Wiklander #include <string.h>
22817466cbSJens Wiklander
233d3b0591SJens Wiklander #if !defined(MBEDTLS_ECJPAKE_ALT)
243d3b0591SJens Wiklander
25817466cbSJens Wiklander /*
26817466cbSJens Wiklander * Convert a mbedtls_ecjpake_role to identifier string
27817466cbSJens Wiklander */
28817466cbSJens Wiklander static const char * const ecjpake_id[] = {
29817466cbSJens Wiklander "client",
30817466cbSJens Wiklander "server"
31817466cbSJens Wiklander };
32817466cbSJens Wiklander
33817466cbSJens Wiklander #define ID_MINE (ecjpake_id[ctx->role])
34817466cbSJens Wiklander #define ID_PEER (ecjpake_id[1 - ctx->role])
35817466cbSJens Wiklander
3632b31808SJens Wiklander /**
3732b31808SJens Wiklander * Helper to Compute a hash from md_type
3832b31808SJens Wiklander */
mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,const unsigned char * input,size_t ilen,unsigned char * output)3932b31808SJens Wiklander static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
4032b31808SJens Wiklander const unsigned char *input, size_t ilen,
4132b31808SJens Wiklander unsigned char *output)
4232b31808SJens Wiklander {
4332b31808SJens Wiklander return mbedtls_md(mbedtls_md_info_from_type(md_type),
4432b31808SJens Wiklander input, ilen, output);
4532b31808SJens Wiklander }
4632b31808SJens Wiklander
47817466cbSJens Wiklander /*
48817466cbSJens Wiklander * Initialize context
49817466cbSJens Wiklander */
mbedtls_ecjpake_init(mbedtls_ecjpake_context * ctx)50817466cbSJens Wiklander void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
51817466cbSJens Wiklander {
5232b31808SJens Wiklander ctx->md_type = MBEDTLS_MD_NONE;
53817466cbSJens Wiklander mbedtls_ecp_group_init(&ctx->grp);
54817466cbSJens Wiklander ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
55817466cbSJens Wiklander
56817466cbSJens Wiklander mbedtls_ecp_point_init(&ctx->Xm1);
57817466cbSJens Wiklander mbedtls_ecp_point_init(&ctx->Xm2);
58817466cbSJens Wiklander mbedtls_ecp_point_init(&ctx->Xp1);
59817466cbSJens Wiklander mbedtls_ecp_point_init(&ctx->Xp2);
60817466cbSJens Wiklander mbedtls_ecp_point_init(&ctx->Xp);
61817466cbSJens Wiklander
62817466cbSJens Wiklander mbedtls_mpi_init(&ctx->xm1);
63817466cbSJens Wiklander mbedtls_mpi_init(&ctx->xm2);
64817466cbSJens Wiklander mbedtls_mpi_init(&ctx->s);
65817466cbSJens Wiklander }
66817466cbSJens Wiklander
67817466cbSJens Wiklander /*
68817466cbSJens Wiklander * Free context
69817466cbSJens Wiklander */
mbedtls_ecjpake_free(mbedtls_ecjpake_context * ctx)70817466cbSJens Wiklander void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
71817466cbSJens Wiklander {
7232b31808SJens Wiklander if (ctx == NULL) {
73817466cbSJens Wiklander return;
7432b31808SJens Wiklander }
75817466cbSJens Wiklander
7632b31808SJens Wiklander ctx->md_type = MBEDTLS_MD_NONE;
77817466cbSJens Wiklander mbedtls_ecp_group_free(&ctx->grp);
78817466cbSJens Wiklander
79817466cbSJens Wiklander mbedtls_ecp_point_free(&ctx->Xm1);
80817466cbSJens Wiklander mbedtls_ecp_point_free(&ctx->Xm2);
81817466cbSJens Wiklander mbedtls_ecp_point_free(&ctx->Xp1);
82817466cbSJens Wiklander mbedtls_ecp_point_free(&ctx->Xp2);
83817466cbSJens Wiklander mbedtls_ecp_point_free(&ctx->Xp);
84817466cbSJens Wiklander
85817466cbSJens Wiklander mbedtls_mpi_free(&ctx->xm1);
86817466cbSJens Wiklander mbedtls_mpi_free(&ctx->xm2);
87817466cbSJens Wiklander mbedtls_mpi_free(&ctx->s);
88817466cbSJens Wiklander }
89817466cbSJens Wiklander
90817466cbSJens Wiklander /*
91817466cbSJens Wiklander * Setup context
92817466cbSJens Wiklander */
mbedtls_ecjpake_setup(mbedtls_ecjpake_context * ctx,mbedtls_ecjpake_role role,mbedtls_md_type_t hash,mbedtls_ecp_group_id curve,const unsigned char * secret,size_t len)93817466cbSJens Wiklander int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
94817466cbSJens Wiklander mbedtls_ecjpake_role role,
95817466cbSJens Wiklander mbedtls_md_type_t hash,
96817466cbSJens Wiklander mbedtls_ecp_group_id curve,
97817466cbSJens Wiklander const unsigned char *secret,
98817466cbSJens Wiklander size_t len)
99817466cbSJens Wiklander {
10011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101817466cbSJens Wiklander
10232b31808SJens Wiklander if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
10332b31808SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
10432b31808SJens Wiklander }
1053d3b0591SJens Wiklander
106817466cbSJens Wiklander ctx->role = role;
107817466cbSJens Wiklander
10832b31808SJens Wiklander if ((mbedtls_md_info_from_type(hash)) == NULL) {
10932b31808SJens Wiklander return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
11032b31808SJens Wiklander }
11132b31808SJens Wiklander
11232b31808SJens Wiklander ctx->md_type = hash;
113817466cbSJens Wiklander
114817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
115817466cbSJens Wiklander
116817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
117817466cbSJens Wiklander
118817466cbSJens Wiklander cleanup:
11932b31808SJens Wiklander if (ret != 0) {
120817466cbSJens Wiklander mbedtls_ecjpake_free(ctx);
12132b31808SJens Wiklander }
122817466cbSJens Wiklander
12332b31808SJens Wiklander return ret;
12432b31808SJens Wiklander }
12532b31808SJens Wiklander
mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context * ctx,int point_format)12632b31808SJens Wiklander int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
12732b31808SJens Wiklander int point_format)
12832b31808SJens Wiklander {
12932b31808SJens Wiklander switch (point_format) {
13032b31808SJens Wiklander case MBEDTLS_ECP_PF_UNCOMPRESSED:
13132b31808SJens Wiklander case MBEDTLS_ECP_PF_COMPRESSED:
13232b31808SJens Wiklander ctx->point_format = point_format;
13332b31808SJens Wiklander return 0;
13432b31808SJens Wiklander default:
13532b31808SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
13632b31808SJens Wiklander }
137817466cbSJens Wiklander }
138817466cbSJens Wiklander
139817466cbSJens Wiklander /*
140817466cbSJens Wiklander * Check if context is ready for use
141817466cbSJens Wiklander */
mbedtls_ecjpake_check(const mbedtls_ecjpake_context * ctx)142817466cbSJens Wiklander int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
143817466cbSJens Wiklander {
14432b31808SJens Wiklander if (ctx->md_type == MBEDTLS_MD_NONE ||
145817466cbSJens Wiklander ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
14632b31808SJens Wiklander ctx->s.p == NULL) {
14732b31808SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
148817466cbSJens Wiklander }
149817466cbSJens Wiklander
15032b31808SJens Wiklander return 0;
151817466cbSJens Wiklander }
152817466cbSJens Wiklander
153817466cbSJens Wiklander /*
154817466cbSJens Wiklander * Write a point plus its length to a buffer
155817466cbSJens Wiklander */
ecjpake_write_len_point(unsigned char ** p,const unsigned char * end,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * P)156817466cbSJens Wiklander static int ecjpake_write_len_point(unsigned char **p,
157817466cbSJens Wiklander const unsigned char *end,
158817466cbSJens Wiklander const mbedtls_ecp_group *grp,
159817466cbSJens Wiklander const int pf,
160817466cbSJens Wiklander const mbedtls_ecp_point *P)
161817466cbSJens Wiklander {
16211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
163817466cbSJens Wiklander size_t len;
164817466cbSJens Wiklander
165817466cbSJens Wiklander /* Need at least 4 for length plus 1 for point */
16632b31808SJens Wiklander if (end < *p || end - *p < 5) {
16732b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
16832b31808SJens Wiklander }
169817466cbSJens Wiklander
170817466cbSJens Wiklander ret = mbedtls_ecp_point_write_binary(grp, P, pf,
171*b0563631STom Van Eyck &len, *p + 4, (size_t) (end - (*p + 4)));
17232b31808SJens Wiklander if (ret != 0) {
17332b31808SJens Wiklander return ret;
17432b31808SJens Wiklander }
175817466cbSJens Wiklander
176039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(len, *p, 0);
177817466cbSJens Wiklander
178817466cbSJens Wiklander *p += 4 + len;
179817466cbSJens Wiklander
18032b31808SJens Wiklander return 0;
181817466cbSJens Wiklander }
182817466cbSJens Wiklander
183817466cbSJens Wiklander /*
184817466cbSJens Wiklander * Size of the temporary buffer for ecjpake_hash:
185817466cbSJens Wiklander * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
186817466cbSJens Wiklander */
187817466cbSJens Wiklander #define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
188817466cbSJens Wiklander
189817466cbSJens Wiklander /*
190817466cbSJens Wiklander * Compute hash for ZKP (7.4.2.2.2.1)
191817466cbSJens Wiklander */
ecjpake_hash(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_ecp_point * V,const mbedtls_ecp_point * X,const char * id,mbedtls_mpi * h)19232b31808SJens Wiklander static int ecjpake_hash(const mbedtls_md_type_t md_type,
193817466cbSJens Wiklander const mbedtls_ecp_group *grp,
194817466cbSJens Wiklander const int pf,
195817466cbSJens Wiklander const mbedtls_ecp_point *G,
196817466cbSJens Wiklander const mbedtls_ecp_point *V,
197817466cbSJens Wiklander const mbedtls_ecp_point *X,
198817466cbSJens Wiklander const char *id,
199817466cbSJens Wiklander mbedtls_mpi *h)
200817466cbSJens Wiklander {
20111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
202817466cbSJens Wiklander unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203817466cbSJens Wiklander unsigned char *p = buf;
204817466cbSJens Wiklander const unsigned char *end = buf + sizeof(buf);
205817466cbSJens Wiklander const size_t id_len = strlen(id);
206*b0563631STom Van Eyck unsigned char hash[MBEDTLS_MD_MAX_SIZE];
207817466cbSJens Wiklander
208817466cbSJens Wiklander /* Write things to temporary buffer */
209817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
210817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
211817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
212817466cbSJens Wiklander
21332b31808SJens Wiklander if (end - p < 4) {
21432b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
21532b31808SJens Wiklander }
216817466cbSJens Wiklander
217039e02dfSJerome Forissier MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
218039e02dfSJerome Forissier p += 4;
219817466cbSJens Wiklander
22032b31808SJens Wiklander if (end < p || (size_t) (end - p) < id_len) {
22132b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
22232b31808SJens Wiklander }
223817466cbSJens Wiklander
224817466cbSJens Wiklander memcpy(p, id, id_len);
225817466cbSJens Wiklander p += id_len;
226817466cbSJens Wiklander
227817466cbSJens Wiklander /* Compute hash */
22832b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
229*b0563631STom Van Eyck buf, (size_t) (p - buf), hash));
230817466cbSJens Wiklander
231817466cbSJens Wiklander /* Turn it into an integer mod n */
232817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
233*b0563631STom Van Eyck mbedtls_md_get_size_from_type(md_type)));
234817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
235817466cbSJens Wiklander
236817466cbSJens Wiklander cleanup:
23732b31808SJens Wiklander return ret;
238817466cbSJens Wiklander }
239817466cbSJens Wiklander
240817466cbSJens Wiklander /*
241817466cbSJens Wiklander * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242817466cbSJens Wiklander */
ecjpake_zkp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_ecp_point * X,const char * id,const unsigned char ** p,const unsigned char * end)24332b31808SJens Wiklander static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
244817466cbSJens Wiklander const mbedtls_ecp_group *grp,
245817466cbSJens Wiklander const int pf,
246817466cbSJens Wiklander const mbedtls_ecp_point *G,
247817466cbSJens Wiklander const mbedtls_ecp_point *X,
248817466cbSJens Wiklander const char *id,
249817466cbSJens Wiklander const unsigned char **p,
250817466cbSJens Wiklander const unsigned char *end)
251817466cbSJens Wiklander {
25211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253817466cbSJens Wiklander mbedtls_ecp_point V, VV;
254817466cbSJens Wiklander mbedtls_mpi r, h;
255817466cbSJens Wiklander size_t r_len;
256817466cbSJens Wiklander
257817466cbSJens Wiklander mbedtls_ecp_point_init(&V);
258817466cbSJens Wiklander mbedtls_ecp_point_init(&VV);
259817466cbSJens Wiklander mbedtls_mpi_init(&r);
260817466cbSJens Wiklander mbedtls_mpi_init(&h);
261817466cbSJens Wiklander
262817466cbSJens Wiklander /*
263817466cbSJens Wiklander * struct {
264817466cbSJens Wiklander * ECPoint V;
265817466cbSJens Wiklander * opaque r<1..2^8-1>;
266817466cbSJens Wiklander * } ECSchnorrZKP;
267817466cbSJens Wiklander */
26832b31808SJens Wiklander if (end < *p) {
26932b31808SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
27032b31808SJens Wiklander }
271817466cbSJens Wiklander
272*b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
273817466cbSJens Wiklander
27432b31808SJens Wiklander if (end < *p || (size_t) (end - *p) < 1) {
275817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276817466cbSJens Wiklander goto cleanup;
277817466cbSJens Wiklander }
278817466cbSJens Wiklander
279817466cbSJens Wiklander r_len = *(*p)++;
280817466cbSJens Wiklander
28132b31808SJens Wiklander if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
282817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283817466cbSJens Wiklander goto cleanup;
284817466cbSJens Wiklander }
285817466cbSJens Wiklander
286817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
287817466cbSJens Wiklander *p += r_len;
288817466cbSJens Wiklander
289817466cbSJens Wiklander /*
290817466cbSJens Wiklander * Verification
291817466cbSJens Wiklander */
29232b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
293817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
294817466cbSJens Wiklander &VV, &h, X, &r, G));
295817466cbSJens Wiklander
29632b31808SJens Wiklander if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
297817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298817466cbSJens Wiklander goto cleanup;
299817466cbSJens Wiklander }
300817466cbSJens Wiklander
301817466cbSJens Wiklander cleanup:
302817466cbSJens Wiklander mbedtls_ecp_point_free(&V);
303817466cbSJens Wiklander mbedtls_ecp_point_free(&VV);
304817466cbSJens Wiklander mbedtls_mpi_free(&r);
305817466cbSJens Wiklander mbedtls_mpi_free(&h);
306817466cbSJens Wiklander
30732b31808SJens Wiklander return ret;
308817466cbSJens Wiklander }
309817466cbSJens Wiklander
310817466cbSJens Wiklander /*
311817466cbSJens Wiklander * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312817466cbSJens Wiklander */
ecjpake_zkp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,const mbedtls_mpi * x,const mbedtls_ecp_point * X,const char * id,unsigned char ** p,const unsigned char * end,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)31332b31808SJens Wiklander static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
314817466cbSJens Wiklander const mbedtls_ecp_group *grp,
315817466cbSJens Wiklander const int pf,
316817466cbSJens Wiklander const mbedtls_ecp_point *G,
317817466cbSJens Wiklander const mbedtls_mpi *x,
318817466cbSJens Wiklander const mbedtls_ecp_point *X,
319817466cbSJens Wiklander const char *id,
320817466cbSJens Wiklander unsigned char **p,
321817466cbSJens Wiklander const unsigned char *end,
322817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
323817466cbSJens Wiklander void *p_rng)
324817466cbSJens Wiklander {
32511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326817466cbSJens Wiklander mbedtls_ecp_point V;
327817466cbSJens Wiklander mbedtls_mpi v;
328817466cbSJens Wiklander mbedtls_mpi h; /* later recycled to hold r */
329817466cbSJens Wiklander size_t len;
330817466cbSJens Wiklander
33132b31808SJens Wiklander if (end < *p) {
33232b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
33332b31808SJens Wiklander }
334817466cbSJens Wiklander
335817466cbSJens Wiklander mbedtls_ecp_point_init(&V);
336817466cbSJens Wiklander mbedtls_mpi_init(&v);
337817466cbSJens Wiklander mbedtls_mpi_init(&h);
338817466cbSJens Wiklander
339817466cbSJens Wiklander /* Compute signature */
340817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
341817466cbSJens Wiklander G, &v, &V, f_rng, p_rng));
34232b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
343817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */
344817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */
345817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */
346817466cbSJens Wiklander
347817466cbSJens Wiklander /* Write it out */
348817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
349*b0563631STom Van Eyck pf, &len, *p, (size_t) (end - *p)));
350817466cbSJens Wiklander *p += len;
351817466cbSJens Wiklander
352817466cbSJens Wiklander len = mbedtls_mpi_size(&h); /* actually r */
35332b31808SJens Wiklander if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
354817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355817466cbSJens Wiklander goto cleanup;
356817466cbSJens Wiklander }
357817466cbSJens Wiklander
358039e02dfSJerome Forissier *(*p)++ = MBEDTLS_BYTE_0(len);
359817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */
360817466cbSJens Wiklander *p += len;
361817466cbSJens Wiklander
362817466cbSJens Wiklander cleanup:
363817466cbSJens Wiklander mbedtls_ecp_point_free(&V);
364817466cbSJens Wiklander mbedtls_mpi_free(&v);
365817466cbSJens Wiklander mbedtls_mpi_free(&h);
366817466cbSJens Wiklander
36732b31808SJens Wiklander return ret;
368817466cbSJens Wiklander }
369817466cbSJens Wiklander
370817466cbSJens Wiklander /*
371817466cbSJens Wiklander * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372817466cbSJens Wiklander * Output: verified public key X
373817466cbSJens Wiklander */
ecjpake_kkp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_ecp_point * X,const char * id,const unsigned char ** p,const unsigned char * end)37432b31808SJens Wiklander static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
375817466cbSJens Wiklander const mbedtls_ecp_group *grp,
376817466cbSJens Wiklander const int pf,
377817466cbSJens Wiklander const mbedtls_ecp_point *G,
378817466cbSJens Wiklander mbedtls_ecp_point *X,
379817466cbSJens Wiklander const char *id,
380817466cbSJens Wiklander const unsigned char **p,
381817466cbSJens Wiklander const unsigned char *end)
382817466cbSJens Wiklander {
38311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
384817466cbSJens Wiklander
38532b31808SJens Wiklander if (end < *p) {
38632b31808SJens Wiklander return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
38732b31808SJens Wiklander }
388817466cbSJens Wiklander
389817466cbSJens Wiklander /*
390817466cbSJens Wiklander * struct {
391817466cbSJens Wiklander * ECPoint X;
392817466cbSJens Wiklander * ECSchnorrZKP zkp;
393817466cbSJens Wiklander * } ECJPAKEKeyKP;
394817466cbSJens Wiklander */
395*b0563631STom Van Eyck MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
39632b31808SJens Wiklander if (mbedtls_ecp_is_zero(X)) {
397817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398817466cbSJens Wiklander goto cleanup;
399817466cbSJens Wiklander }
400817466cbSJens Wiklander
40132b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
402817466cbSJens Wiklander
403817466cbSJens Wiklander cleanup:
40432b31808SJens Wiklander return ret;
405817466cbSJens Wiklander }
406817466cbSJens Wiklander
407817466cbSJens Wiklander /*
408817466cbSJens Wiklander * Generate an ECJPAKEKeyKP
409817466cbSJens Wiklander * Output: the serialized structure, plus private/public key pair
410817466cbSJens Wiklander */
ecjpake_kkp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_mpi * x,mbedtls_ecp_point * X,const char * id,unsigned char ** p,const unsigned char * end,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)41132b31808SJens Wiklander static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
412817466cbSJens Wiklander const mbedtls_ecp_group *grp,
413817466cbSJens Wiklander const int pf,
414817466cbSJens Wiklander const mbedtls_ecp_point *G,
415817466cbSJens Wiklander mbedtls_mpi *x,
416817466cbSJens Wiklander mbedtls_ecp_point *X,
417817466cbSJens Wiklander const char *id,
418817466cbSJens Wiklander unsigned char **p,
419817466cbSJens Wiklander const unsigned char *end,
420817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
421817466cbSJens Wiklander void *p_rng)
422817466cbSJens Wiklander {
42311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
424817466cbSJens Wiklander size_t len;
425817466cbSJens Wiklander
42632b31808SJens Wiklander if (end < *p) {
42732b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
42832b31808SJens Wiklander }
429817466cbSJens Wiklander
430817466cbSJens Wiklander /* Generate key (7.4.2.3.1) and write it out */
431817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
432817466cbSJens Wiklander f_rng, p_rng));
433817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
434*b0563631STom Van Eyck pf, &len, *p, (size_t) (end - *p)));
435817466cbSJens Wiklander *p += len;
436817466cbSJens Wiklander
437817466cbSJens Wiklander /* Generate and write proof */
43832b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439817466cbSJens Wiklander p, end, f_rng, p_rng));
440817466cbSJens Wiklander
441817466cbSJens Wiklander cleanup:
44232b31808SJens Wiklander return ret;
443817466cbSJens Wiklander }
444817466cbSJens Wiklander
445817466cbSJens Wiklander /*
446817466cbSJens Wiklander * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
447039e02dfSJerome Forissier * Outputs: verified peer public keys Xa, Xb
448817466cbSJens Wiklander */
ecjpake_kkpp_read(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_ecp_point * Xa,mbedtls_ecp_point * Xb,const char * id,const unsigned char * buf,size_t len)44932b31808SJens Wiklander static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
450817466cbSJens Wiklander const mbedtls_ecp_group *grp,
451817466cbSJens Wiklander const int pf,
452817466cbSJens Wiklander const mbedtls_ecp_point *G,
453817466cbSJens Wiklander mbedtls_ecp_point *Xa,
454817466cbSJens Wiklander mbedtls_ecp_point *Xb,
455817466cbSJens Wiklander const char *id,
456817466cbSJens Wiklander const unsigned char *buf,
457817466cbSJens Wiklander size_t len)
458817466cbSJens Wiklander {
45911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
460817466cbSJens Wiklander const unsigned char *p = buf;
461817466cbSJens Wiklander const unsigned char *end = buf + len;
462817466cbSJens Wiklander
463817466cbSJens Wiklander /*
464817466cbSJens Wiklander * struct {
465817466cbSJens Wiklander * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466817466cbSJens Wiklander * } ECJPAKEKeyKPPairList;
467817466cbSJens Wiklander */
46832b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
46932b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
470817466cbSJens Wiklander
47132b31808SJens Wiklander if (p != end) {
472817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
47332b31808SJens Wiklander }
474817466cbSJens Wiklander
475817466cbSJens Wiklander cleanup:
47632b31808SJens Wiklander return ret;
477817466cbSJens Wiklander }
478817466cbSJens Wiklander
479817466cbSJens Wiklander /*
480817466cbSJens Wiklander * Generate a ECJPAKEKeyKPPairList
481817466cbSJens Wiklander * Outputs: the serialized structure, plus two private/public key pairs
482817466cbSJens Wiklander */
ecjpake_kkpp_write(const mbedtls_md_type_t md_type,const mbedtls_ecp_group * grp,const int pf,const mbedtls_ecp_point * G,mbedtls_mpi * xm1,mbedtls_ecp_point * Xa,mbedtls_mpi * xm2,mbedtls_ecp_point * Xb,const char * id,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)48332b31808SJens Wiklander static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
484817466cbSJens Wiklander const mbedtls_ecp_group *grp,
485817466cbSJens Wiklander const int pf,
486817466cbSJens Wiklander const mbedtls_ecp_point *G,
487817466cbSJens Wiklander mbedtls_mpi *xm1,
488817466cbSJens Wiklander mbedtls_ecp_point *Xa,
489817466cbSJens Wiklander mbedtls_mpi *xm2,
490817466cbSJens Wiklander mbedtls_ecp_point *Xb,
491817466cbSJens Wiklander const char *id,
492817466cbSJens Wiklander unsigned char *buf,
493817466cbSJens Wiklander size_t len,
494817466cbSJens Wiklander size_t *olen,
495817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
496817466cbSJens Wiklander void *p_rng)
497817466cbSJens Wiklander {
49811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
499817466cbSJens Wiklander unsigned char *p = buf;
500817466cbSJens Wiklander const unsigned char *end = buf + len;
501817466cbSJens Wiklander
50232b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
503817466cbSJens Wiklander &p, end, f_rng, p_rng));
50432b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
505817466cbSJens Wiklander &p, end, f_rng, p_rng));
506817466cbSJens Wiklander
507*b0563631STom Van Eyck *olen = (size_t) (p - buf);
508817466cbSJens Wiklander
509817466cbSJens Wiklander cleanup:
51032b31808SJens Wiklander return ret;
511817466cbSJens Wiklander }
512817466cbSJens Wiklander
513817466cbSJens Wiklander /*
514817466cbSJens Wiklander * Read and process the first round message
515817466cbSJens Wiklander */
mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)516817466cbSJens Wiklander int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
517817466cbSJens Wiklander const unsigned char *buf,
518817466cbSJens Wiklander size_t len)
519817466cbSJens Wiklander {
52032b31808SJens Wiklander return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
521817466cbSJens Wiklander &ctx->grp.G,
522817466cbSJens Wiklander &ctx->Xp1, &ctx->Xp2, ID_PEER,
52332b31808SJens Wiklander buf, len);
524817466cbSJens Wiklander }
525817466cbSJens Wiklander
526817466cbSJens Wiklander /*
527817466cbSJens Wiklander * Generate and write the first round message
528817466cbSJens Wiklander */
mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)529817466cbSJens Wiklander int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
530817466cbSJens Wiklander unsigned char *buf, size_t len, size_t *olen,
531817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
532817466cbSJens Wiklander void *p_rng)
533817466cbSJens Wiklander {
53432b31808SJens Wiklander return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
535817466cbSJens Wiklander &ctx->grp.G,
536817466cbSJens Wiklander &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
53732b31808SJens Wiklander ID_MINE, buf, len, olen, f_rng, p_rng);
538817466cbSJens Wiklander }
539817466cbSJens Wiklander
540817466cbSJens Wiklander /*
541817466cbSJens Wiklander * Compute the sum of three points R = A + B + C
542817466cbSJens Wiklander */
ecjpake_ecp_add3(mbedtls_ecp_group * grp,mbedtls_ecp_point * R,const mbedtls_ecp_point * A,const mbedtls_ecp_point * B,const mbedtls_ecp_point * C)543817466cbSJens Wiklander static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
544817466cbSJens Wiklander const mbedtls_ecp_point *A,
545817466cbSJens Wiklander const mbedtls_ecp_point *B,
546817466cbSJens Wiklander const mbedtls_ecp_point *C)
547817466cbSJens Wiklander {
54811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
549817466cbSJens Wiklander mbedtls_mpi one;
550817466cbSJens Wiklander
551817466cbSJens Wiklander mbedtls_mpi_init(&one);
552817466cbSJens Wiklander
553817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
554817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
555817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
556817466cbSJens Wiklander
557817466cbSJens Wiklander cleanup:
558817466cbSJens Wiklander mbedtls_mpi_free(&one);
559817466cbSJens Wiklander
56032b31808SJens Wiklander return ret;
561817466cbSJens Wiklander }
562817466cbSJens Wiklander
563817466cbSJens Wiklander /*
564817466cbSJens Wiklander * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
565817466cbSJens Wiklander */
mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context * ctx,const unsigned char * buf,size_t len)566817466cbSJens Wiklander int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
567817466cbSJens Wiklander const unsigned char *buf,
568817466cbSJens Wiklander size_t len)
569817466cbSJens Wiklander {
57011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
571817466cbSJens Wiklander const unsigned char *p = buf;
572817466cbSJens Wiklander const unsigned char *end = buf + len;
573817466cbSJens Wiklander mbedtls_ecp_group grp;
574817466cbSJens Wiklander mbedtls_ecp_point G; /* C: GB, S: GA */
575817466cbSJens Wiklander
576817466cbSJens Wiklander mbedtls_ecp_group_init(&grp);
577817466cbSJens Wiklander mbedtls_ecp_point_init(&G);
578817466cbSJens Wiklander
579817466cbSJens Wiklander /*
580817466cbSJens Wiklander * Server: GA = X3 + X4 + X1 (7.4.2.6.1)
581817466cbSJens Wiklander * Client: GB = X1 + X2 + X3 (7.4.2.5.1)
582817466cbSJens Wiklander * Unified: G = Xm1 + Xm2 + Xp1
583817466cbSJens Wiklander * We need that before parsing in order to check Xp as we read it
584817466cbSJens Wiklander */
585817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586817466cbSJens Wiklander &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
587817466cbSJens Wiklander
588817466cbSJens Wiklander /*
589817466cbSJens Wiklander * struct {
590817466cbSJens Wiklander * ECParameters curve_params; // only client reading server msg
591817466cbSJens Wiklander * ECJPAKEKeyKP ecjpake_key_kp;
592817466cbSJens Wiklander * } Client/ServerECJPAKEParams;
593817466cbSJens Wiklander */
59432b31808SJens Wiklander if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
595817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
59632b31808SJens Wiklander if (grp.id != ctx->grp.id) {
597817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598817466cbSJens Wiklander goto cleanup;
599817466cbSJens Wiklander }
600817466cbSJens Wiklander }
601817466cbSJens Wiklander
60232b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603817466cbSJens Wiklander ctx->point_format,
604817466cbSJens Wiklander &G, &ctx->Xp, ID_PEER, &p, end));
605817466cbSJens Wiklander
60632b31808SJens Wiklander if (p != end) {
607817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608817466cbSJens Wiklander goto cleanup;
609817466cbSJens Wiklander }
610817466cbSJens Wiklander
611817466cbSJens Wiklander cleanup:
612817466cbSJens Wiklander mbedtls_ecp_group_free(&grp);
613817466cbSJens Wiklander mbedtls_ecp_point_free(&G);
614817466cbSJens Wiklander
61532b31808SJens Wiklander return ret;
616817466cbSJens Wiklander }
617817466cbSJens Wiklander
618817466cbSJens Wiklander /*
619817466cbSJens Wiklander * Compute R = +/- X * S mod N, taking care not to leak S
620817466cbSJens Wiklander */
ecjpake_mul_secret(mbedtls_mpi * R,int sign,const mbedtls_mpi * X,const mbedtls_mpi * S,const mbedtls_mpi * N,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)621817466cbSJens Wiklander static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
622817466cbSJens Wiklander const mbedtls_mpi *X,
623817466cbSJens Wiklander const mbedtls_mpi *S,
624817466cbSJens Wiklander const mbedtls_mpi *N,
625817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
626817466cbSJens Wiklander void *p_rng)
627817466cbSJens Wiklander {
62811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
629817466cbSJens Wiklander mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630817466cbSJens Wiklander
631817466cbSJens Wiklander mbedtls_mpi_init(&b);
632817466cbSJens Wiklander
633817466cbSJens Wiklander /* b = s + rnd-128-bit * N */
634817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
635817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
636817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
637817466cbSJens Wiklander
638817466cbSJens Wiklander /* R = sign * X * b mod N */
639817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
640817466cbSJens Wiklander R->s *= sign;
641817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
642817466cbSJens Wiklander
643817466cbSJens Wiklander cleanup:
644817466cbSJens Wiklander mbedtls_mpi_free(&b);
645817466cbSJens Wiklander
64632b31808SJens Wiklander return ret;
647817466cbSJens Wiklander }
648817466cbSJens Wiklander
649817466cbSJens Wiklander /*
650817466cbSJens Wiklander * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
651817466cbSJens Wiklander */
mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)652817466cbSJens Wiklander int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
653817466cbSJens Wiklander unsigned char *buf, size_t len, size_t *olen,
654817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
655817466cbSJens Wiklander void *p_rng)
656817466cbSJens Wiklander {
65711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
658817466cbSJens Wiklander mbedtls_ecp_point G; /* C: GA, S: GB */
659817466cbSJens Wiklander mbedtls_ecp_point Xm; /* C: Xc, S: Xs */
660817466cbSJens Wiklander mbedtls_mpi xm; /* C: xc, S: xs */
661817466cbSJens Wiklander unsigned char *p = buf;
662817466cbSJens Wiklander const unsigned char *end = buf + len;
663817466cbSJens Wiklander size_t ec_len;
664817466cbSJens Wiklander
665817466cbSJens Wiklander mbedtls_ecp_point_init(&G);
666817466cbSJens Wiklander mbedtls_ecp_point_init(&Xm);
667817466cbSJens Wiklander mbedtls_mpi_init(&xm);
668817466cbSJens Wiklander
669817466cbSJens Wiklander /*
670817466cbSJens Wiklander * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
671817466cbSJens Wiklander *
672817466cbSJens Wiklander * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA
673817466cbSJens Wiklander * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB
674817466cbSJens Wiklander * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
675817466cbSJens Wiklander */
676817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
677817466cbSJens Wiklander &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
678817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
679817466cbSJens Wiklander &ctx->grp.N, f_rng, p_rng));
680817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
681817466cbSJens Wiklander
682817466cbSJens Wiklander /*
683817466cbSJens Wiklander * Now write things out
684817466cbSJens Wiklander *
685817466cbSJens Wiklander * struct {
686817466cbSJens Wiklander * ECParameters curve_params; // only server writing its message
687817466cbSJens Wiklander * ECJPAKEKeyKP ecjpake_key_kp;
688817466cbSJens Wiklander * } Client/ServerECJPAKEParams;
689817466cbSJens Wiklander */
69032b31808SJens Wiklander if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
69132b31808SJens Wiklander if (end < p) {
692817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693817466cbSJens Wiklander goto cleanup;
694817466cbSJens Wiklander }
695817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
696*b0563631STom Van Eyck p, (size_t) (end - p)));
697817466cbSJens Wiklander p += ec_len;
698817466cbSJens Wiklander }
699817466cbSJens Wiklander
70032b31808SJens Wiklander if (end < p) {
701817466cbSJens Wiklander ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702817466cbSJens Wiklander goto cleanup;
703817466cbSJens Wiklander }
704817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
705*b0563631STom Van Eyck ctx->point_format, &ec_len, p, (size_t) (end - p)));
706817466cbSJens Wiklander p += ec_len;
707817466cbSJens Wiklander
70832b31808SJens Wiklander MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
709817466cbSJens Wiklander ctx->point_format,
710817466cbSJens Wiklander &G, &xm, &Xm, ID_MINE,
711817466cbSJens Wiklander &p, end, f_rng, p_rng));
712817466cbSJens Wiklander
713*b0563631STom Van Eyck *olen = (size_t) (p - buf);
714817466cbSJens Wiklander
715817466cbSJens Wiklander cleanup:
716817466cbSJens Wiklander mbedtls_ecp_point_free(&G);
717817466cbSJens Wiklander mbedtls_ecp_point_free(&Xm);
718817466cbSJens Wiklander mbedtls_mpi_free(&xm);
719817466cbSJens Wiklander
72032b31808SJens Wiklander return ret;
721817466cbSJens Wiklander }
722817466cbSJens Wiklander
723817466cbSJens Wiklander /*
724817466cbSJens Wiklander * Derive PMS (7.4.2.7 / 7.4.2.8)
725817466cbSJens Wiklander */
mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context * ctx,mbedtls_ecp_point * K,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)72632b31808SJens Wiklander static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
72732b31808SJens Wiklander mbedtls_ecp_point *K,
728817466cbSJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
729817466cbSJens Wiklander void *p_rng)
730817466cbSJens Wiklander {
73111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
732817466cbSJens Wiklander mbedtls_mpi m_xm2_s, one;
733817466cbSJens Wiklander
734817466cbSJens Wiklander mbedtls_mpi_init(&m_xm2_s);
735817466cbSJens Wiklander mbedtls_mpi_init(&one);
736817466cbSJens Wiklander
737817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
738817466cbSJens Wiklander
739817466cbSJens Wiklander /*
740817466cbSJens Wiklander * Client: K = ( Xs - X4 * x2 * s ) * x2
741817466cbSJens Wiklander * Server: K = ( Xc - X2 * x4 * s ) * x4
742817466cbSJens Wiklander * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
743817466cbSJens Wiklander */
744817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
745817466cbSJens Wiklander &ctx->grp.N, f_rng, p_rng));
74632b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
747817466cbSJens Wiklander &one, &ctx->Xp,
748817466cbSJens Wiklander &m_xm2_s, &ctx->Xp2));
74932b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
750817466cbSJens Wiklander f_rng, p_rng));
751817466cbSJens Wiklander
75232b31808SJens Wiklander cleanup:
75332b31808SJens Wiklander mbedtls_mpi_free(&m_xm2_s);
75432b31808SJens Wiklander mbedtls_mpi_free(&one);
75532b31808SJens Wiklander
75632b31808SJens Wiklander return ret;
75732b31808SJens Wiklander }
75832b31808SJens Wiklander
mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)75932b31808SJens Wiklander int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
76032b31808SJens Wiklander unsigned char *buf, size_t len, size_t *olen,
76132b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
76232b31808SJens Wiklander void *p_rng)
76332b31808SJens Wiklander {
76432b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
76532b31808SJens Wiklander mbedtls_ecp_point K;
76632b31808SJens Wiklander unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
76732b31808SJens Wiklander size_t x_bytes;
76832b31808SJens Wiklander
769*b0563631STom Van Eyck *olen = mbedtls_md_get_size_from_type(ctx->md_type);
77032b31808SJens Wiklander if (len < *olen) {
77132b31808SJens Wiklander return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
77232b31808SJens Wiklander }
77332b31808SJens Wiklander
77432b31808SJens Wiklander mbedtls_ecp_point_init(&K);
77532b31808SJens Wiklander
77632b31808SJens Wiklander ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
77732b31808SJens Wiklander if (ret) {
77832b31808SJens Wiklander goto cleanup;
77932b31808SJens Wiklander }
78032b31808SJens Wiklander
781817466cbSJens Wiklander /* PMS = SHA-256( K.X ) */
782817466cbSJens Wiklander x_bytes = (ctx->grp.pbits + 7) / 8;
783817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
78432b31808SJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
78532b31808SJens Wiklander kx, x_bytes, buf));
786817466cbSJens Wiklander
787817466cbSJens Wiklander cleanup:
788817466cbSJens Wiklander mbedtls_ecp_point_free(&K);
789817466cbSJens Wiklander
79032b31808SJens Wiklander return ret;
79132b31808SJens Wiklander }
79232b31808SJens Wiklander
mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context * ctx,unsigned char * buf,size_t len,size_t * olen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)79332b31808SJens Wiklander int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
79432b31808SJens Wiklander unsigned char *buf, size_t len, size_t *olen,
79532b31808SJens Wiklander int (*f_rng)(void *, unsigned char *, size_t),
79632b31808SJens Wiklander void *p_rng)
79732b31808SJens Wiklander {
79832b31808SJens Wiklander int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
79932b31808SJens Wiklander mbedtls_ecp_point K;
80032b31808SJens Wiklander
80132b31808SJens Wiklander mbedtls_ecp_point_init(&K);
80232b31808SJens Wiklander
80332b31808SJens Wiklander ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
80432b31808SJens Wiklander if (ret) {
80532b31808SJens Wiklander goto cleanup;
80632b31808SJens Wiklander }
80732b31808SJens Wiklander
80832b31808SJens Wiklander ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
80932b31808SJens Wiklander olen, buf, len);
81032b31808SJens Wiklander if (ret != 0) {
81132b31808SJens Wiklander goto cleanup;
81232b31808SJens Wiklander }
81332b31808SJens Wiklander
81432b31808SJens Wiklander cleanup:
81532b31808SJens Wiklander mbedtls_ecp_point_free(&K);
81632b31808SJens Wiklander
81732b31808SJens Wiklander return ret;
818817466cbSJens Wiklander }
819817466cbSJens Wiklander
820817466cbSJens Wiklander #undef ID_MINE
821817466cbSJens Wiklander #undef ID_PEER
822817466cbSJens Wiklander
8233d3b0591SJens Wiklander #endif /* ! MBEDTLS_ECJPAKE_ALT */
824817466cbSJens Wiklander
825817466cbSJens Wiklander #if defined(MBEDTLS_SELF_TEST)
826817466cbSJens Wiklander
827817466cbSJens Wiklander #include "mbedtls/platform.h"
828817466cbSJens Wiklander
829817466cbSJens Wiklander #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
830*b0563631STom Van Eyck !defined(MBEDTLS_MD_CAN_SHA256)
mbedtls_ecjpake_self_test(int verbose)831817466cbSJens Wiklander int mbedtls_ecjpake_self_test(int verbose)
832817466cbSJens Wiklander {
833817466cbSJens Wiklander (void) verbose;
83432b31808SJens Wiklander return 0;
835817466cbSJens Wiklander }
836817466cbSJens Wiklander #else
837817466cbSJens Wiklander
838817466cbSJens Wiklander static const unsigned char ecjpake_test_password[] = {
839817466cbSJens Wiklander 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
840817466cbSJens Wiklander 0x65, 0x73, 0x74
841817466cbSJens Wiklander };
842817466cbSJens Wiklander
8437901324dSJerome Forissier #if !defined(MBEDTLS_ECJPAKE_ALT)
8447901324dSJerome Forissier
845817466cbSJens Wiklander static const unsigned char ecjpake_test_x1[] = {
846817466cbSJens Wiklander 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
847817466cbSJens Wiklander 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
848817466cbSJens Wiklander 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
849817466cbSJens Wiklander };
850817466cbSJens Wiklander
851817466cbSJens Wiklander static const unsigned char ecjpake_test_x2[] = {
852817466cbSJens Wiklander 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853817466cbSJens Wiklander 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854817466cbSJens Wiklander 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855817466cbSJens Wiklander };
856817466cbSJens Wiklander
857817466cbSJens Wiklander static const unsigned char ecjpake_test_x3[] = {
858817466cbSJens Wiklander 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
859817466cbSJens Wiklander 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
860817466cbSJens Wiklander 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
861817466cbSJens Wiklander };
862817466cbSJens Wiklander
863817466cbSJens Wiklander static const unsigned char ecjpake_test_x4[] = {
864817466cbSJens Wiklander 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
865817466cbSJens Wiklander 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
866817466cbSJens Wiklander 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
867817466cbSJens Wiklander };
868817466cbSJens Wiklander
869817466cbSJens Wiklander static const unsigned char ecjpake_test_cli_one[] = {
870817466cbSJens Wiklander 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
871817466cbSJens Wiklander 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
872817466cbSJens Wiklander 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
873817466cbSJens Wiklander 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
874817466cbSJens Wiklander 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
875817466cbSJens Wiklander 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
876817466cbSJens Wiklander 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
877817466cbSJens Wiklander 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
878817466cbSJens Wiklander 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
879817466cbSJens Wiklander 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
880817466cbSJens Wiklander 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
881817466cbSJens Wiklander 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
882817466cbSJens Wiklander 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
883817466cbSJens Wiklander 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
884817466cbSJens Wiklander 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
885817466cbSJens Wiklander 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
886817466cbSJens Wiklander 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
887817466cbSJens Wiklander 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
888817466cbSJens Wiklander 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
889817466cbSJens Wiklander 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
890817466cbSJens Wiklander 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
891817466cbSJens Wiklander 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
892817466cbSJens Wiklander 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
893817466cbSJens Wiklander 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
894817466cbSJens Wiklander 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
895817466cbSJens Wiklander 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
896817466cbSJens Wiklander 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
897817466cbSJens Wiklander 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
898817466cbSJens Wiklander };
899817466cbSJens Wiklander
900817466cbSJens Wiklander static const unsigned char ecjpake_test_srv_one[] = {
901817466cbSJens Wiklander 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
902817466cbSJens Wiklander 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
903817466cbSJens Wiklander 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
904817466cbSJens Wiklander 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
905817466cbSJens Wiklander 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
906817466cbSJens Wiklander 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
907817466cbSJens Wiklander 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
908817466cbSJens Wiklander 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
909817466cbSJens Wiklander 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
910817466cbSJens Wiklander 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
911817466cbSJens Wiklander 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
912817466cbSJens Wiklander 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
913817466cbSJens Wiklander 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
914817466cbSJens Wiklander 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
915817466cbSJens Wiklander 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
916817466cbSJens Wiklander 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
917817466cbSJens Wiklander 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
918817466cbSJens Wiklander 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
919817466cbSJens Wiklander 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
920817466cbSJens Wiklander 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
921817466cbSJens Wiklander 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
922817466cbSJens Wiklander 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
923817466cbSJens Wiklander 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
924817466cbSJens Wiklander 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
925817466cbSJens Wiklander 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
926817466cbSJens Wiklander 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
927817466cbSJens Wiklander 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
928817466cbSJens Wiklander 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
929817466cbSJens Wiklander };
930817466cbSJens Wiklander
931817466cbSJens Wiklander static const unsigned char ecjpake_test_srv_two[] = {
932817466cbSJens Wiklander 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
933817466cbSJens Wiklander 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
934817466cbSJens Wiklander 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
935817466cbSJens Wiklander 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
936817466cbSJens Wiklander 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
937817466cbSJens Wiklander 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
938817466cbSJens Wiklander 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
939817466cbSJens Wiklander 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
940817466cbSJens Wiklander 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
941817466cbSJens Wiklander 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
942817466cbSJens Wiklander 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
943817466cbSJens Wiklander 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
944817466cbSJens Wiklander 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
945817466cbSJens Wiklander 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
946817466cbSJens Wiklander };
947817466cbSJens Wiklander
948817466cbSJens Wiklander static const unsigned char ecjpake_test_cli_two[] = {
949817466cbSJens Wiklander 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
950817466cbSJens Wiklander 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
951817466cbSJens Wiklander 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
952817466cbSJens Wiklander 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
953817466cbSJens Wiklander 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
954817466cbSJens Wiklander 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
955817466cbSJens Wiklander 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
956817466cbSJens Wiklander 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
957817466cbSJens Wiklander 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
958817466cbSJens Wiklander 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
959817466cbSJens Wiklander 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
960817466cbSJens Wiklander 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
961817466cbSJens Wiklander 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
962817466cbSJens Wiklander 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
963817466cbSJens Wiklander };
964817466cbSJens Wiklander
96532b31808SJens Wiklander static const unsigned char ecjpake_test_shared_key[] = {
96632b31808SJens Wiklander 0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
96732b31808SJens Wiklander 0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
96832b31808SJens Wiklander 0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
96932b31808SJens Wiklander 0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
97032b31808SJens Wiklander 0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
97132b31808SJens Wiklander 0x17, 0xc3, 0xde, 0x27, 0xb4,
97232b31808SJens Wiklander };
97332b31808SJens Wiklander
974817466cbSJens Wiklander static const unsigned char ecjpake_test_pms[] = {
975817466cbSJens Wiklander 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
976817466cbSJens Wiklander 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
977817466cbSJens Wiklander 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
978817466cbSJens Wiklander };
979817466cbSJens Wiklander
98032b31808SJens Wiklander /*
98132b31808SJens Wiklander * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
98232b31808SJens Wiklander *
98332b31808SJens Wiklander * This is the linear congruential generator from numerical recipes,
98432b31808SJens Wiklander * except we only use the low byte as the output. See
98532b31808SJens Wiklander * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
98632b31808SJens Wiklander */
self_test_rng(void * ctx,unsigned char * out,size_t len)98732b31808SJens Wiklander static int self_test_rng(void *ctx, unsigned char *out, size_t len)
98832b31808SJens Wiklander {
98932b31808SJens Wiklander static uint32_t state = 42;
99032b31808SJens Wiklander
99132b31808SJens Wiklander (void) ctx;
99232b31808SJens Wiklander
99332b31808SJens Wiklander for (size_t i = 0; i < len; i++) {
99432b31808SJens Wiklander state = state * 1664525u + 1013904223u;
99532b31808SJens Wiklander out[i] = (unsigned char) state;
99632b31808SJens Wiklander }
99732b31808SJens Wiklander
99832b31808SJens Wiklander return 0;
99932b31808SJens Wiklander }
100032b31808SJens Wiklander
10015b25c76aSJerome Forissier /* Load my private keys and generate the corresponding public keys */
ecjpake_test_load(mbedtls_ecjpake_context * ctx,const unsigned char * xm1,size_t len1,const unsigned char * xm2,size_t len2)1002817466cbSJens Wiklander static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1003817466cbSJens Wiklander const unsigned char *xm1, size_t len1,
1004817466cbSJens Wiklander const unsigned char *xm2, size_t len2)
1005817466cbSJens Wiklander {
100611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1007817466cbSJens Wiklander
1008817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1009817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1010817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
101132b31808SJens Wiklander &ctx->grp.G, self_test_rng, NULL));
1012817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
101332b31808SJens Wiklander &ctx->grp.G, self_test_rng, NULL));
1014817466cbSJens Wiklander
1015817466cbSJens Wiklander cleanup:
101632b31808SJens Wiklander return ret;
1017817466cbSJens Wiklander }
1018817466cbSJens Wiklander
10197901324dSJerome Forissier #endif /* ! MBEDTLS_ECJPAKE_ALT */
10207901324dSJerome Forissier
1021817466cbSJens Wiklander /* For tests we don't need a secure RNG;
1022817466cbSJens Wiklander * use the LGC from Numerical Recipes for simplicity */
ecjpake_lgc(void * p,unsigned char * out,size_t len)1023817466cbSJens Wiklander static int ecjpake_lgc(void *p, unsigned char *out, size_t len)
1024817466cbSJens Wiklander {
1025817466cbSJens Wiklander static uint32_t x = 42;
1026817466cbSJens Wiklander (void) p;
1027817466cbSJens Wiklander
102832b31808SJens Wiklander while (len > 0) {
1029817466cbSJens Wiklander size_t use_len = len > 4 ? 4 : len;
1030817466cbSJens Wiklander x = 1664525 * x + 1013904223;
1031817466cbSJens Wiklander memcpy(out, &x, use_len);
1032817466cbSJens Wiklander out += use_len;
1033817466cbSJens Wiklander len -= use_len;
1034817466cbSJens Wiklander }
1035817466cbSJens Wiklander
103632b31808SJens Wiklander return 0;
1037817466cbSJens Wiklander }
1038817466cbSJens Wiklander
1039817466cbSJens Wiklander #define TEST_ASSERT(x) \
1040817466cbSJens Wiklander do { \
1041817466cbSJens Wiklander if (x) \
1042817466cbSJens Wiklander ret = 0; \
1043817466cbSJens Wiklander else \
1044817466cbSJens Wiklander { \
1045817466cbSJens Wiklander ret = 1; \
1046817466cbSJens Wiklander goto cleanup; \
1047817466cbSJens Wiklander } \
1048817466cbSJens Wiklander } while (0)
1049817466cbSJens Wiklander
1050817466cbSJens Wiklander /*
1051817466cbSJens Wiklander * Checkup routine
1052817466cbSJens Wiklander */
mbedtls_ecjpake_self_test(int verbose)1053817466cbSJens Wiklander int mbedtls_ecjpake_self_test(int verbose)
1054817466cbSJens Wiklander {
105511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1056817466cbSJens Wiklander mbedtls_ecjpake_context cli;
1057817466cbSJens Wiklander mbedtls_ecjpake_context srv;
1058817466cbSJens Wiklander unsigned char buf[512], pms[32];
1059817466cbSJens Wiklander size_t len, pmslen;
1060817466cbSJens Wiklander
1061817466cbSJens Wiklander mbedtls_ecjpake_init(&cli);
1062817466cbSJens Wiklander mbedtls_ecjpake_init(&srv);
1063817466cbSJens Wiklander
106432b31808SJens Wiklander if (verbose != 0) {
1065817466cbSJens Wiklander mbedtls_printf(" ECJPAKE test #0 (setup): ");
106632b31808SJens Wiklander }
1067817466cbSJens Wiklander
1068817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1069817466cbSJens Wiklander MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1070817466cbSJens Wiklander ecjpake_test_password,
1071817466cbSJens Wiklander sizeof(ecjpake_test_password)) == 0);
1072817466cbSJens Wiklander
1073817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1074817466cbSJens Wiklander MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1075817466cbSJens Wiklander ecjpake_test_password,
1076817466cbSJens Wiklander sizeof(ecjpake_test_password)) == 0);
1077817466cbSJens Wiklander
107832b31808SJens Wiklander if (verbose != 0) {
1079817466cbSJens Wiklander mbedtls_printf("passed\n");
108032b31808SJens Wiklander }
1081817466cbSJens Wiklander
108232b31808SJens Wiklander if (verbose != 0) {
1083817466cbSJens Wiklander mbedtls_printf(" ECJPAKE test #1 (random handshake): ");
108432b31808SJens Wiklander }
1085817466cbSJens Wiklander
1086817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1088817466cbSJens Wiklander
1089817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1090817466cbSJens Wiklander
1091817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1093817466cbSJens Wiklander
1094817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1095817466cbSJens Wiklander
1096817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1098817466cbSJens Wiklander
1099817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1100817466cbSJens Wiklander
1101817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102817466cbSJens Wiklander pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1103817466cbSJens Wiklander
1104817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1106817466cbSJens Wiklander
1107817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1108817466cbSJens Wiklander
1109817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1111817466cbSJens Wiklander
1112817466cbSJens Wiklander TEST_ASSERT(len == pmslen);
1113817466cbSJens Wiklander TEST_ASSERT(memcmp(buf, pms, len) == 0);
1114817466cbSJens Wiklander
111532b31808SJens Wiklander if (verbose != 0) {
1116817466cbSJens Wiklander mbedtls_printf("passed\n");
111732b31808SJens Wiklander }
1118817466cbSJens Wiklander
11197901324dSJerome Forissier #if !defined(MBEDTLS_ECJPAKE_ALT)
11207901324dSJerome Forissier /* 'reference handshake' tests can only be run against implementations
11217901324dSJerome Forissier * for which we have 100% control over how the random ephemeral keys
1122*b0563631STom Van Eyck * are generated. This is only the case for the internal Mbed TLS
11237901324dSJerome Forissier * implementation, so these tests are skipped in case the internal
11247901324dSJerome Forissier * implementation is swapped out for an alternative one. */
112532b31808SJens Wiklander if (verbose != 0) {
1126817466cbSJens Wiklander mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");
112732b31808SJens Wiklander }
1128817466cbSJens Wiklander
1129817466cbSJens Wiklander /* Simulate generation of round one */
1130817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131817466cbSJens Wiklander ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132817466cbSJens Wiklander ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1133817466cbSJens Wiklander
1134817466cbSJens Wiklander MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135817466cbSJens Wiklander ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136817466cbSJens Wiklander ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1137817466cbSJens Wiklander
1138817466cbSJens Wiklander /* Read round one */
1139817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140817466cbSJens Wiklander ecjpake_test_cli_one,
1141817466cbSJens Wiklander sizeof(ecjpake_test_cli_one)) == 0);
1142817466cbSJens Wiklander
1143817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144817466cbSJens Wiklander ecjpake_test_srv_one,
1145817466cbSJens Wiklander sizeof(ecjpake_test_srv_one)) == 0);
1146817466cbSJens Wiklander
1147817466cbSJens Wiklander /* Skip generation of round two, read round two */
1148817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149817466cbSJens Wiklander ecjpake_test_srv_two,
1150817466cbSJens Wiklander sizeof(ecjpake_test_srv_two)) == 0);
1151817466cbSJens Wiklander
1152817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153817466cbSJens Wiklander ecjpake_test_cli_two,
1154817466cbSJens Wiklander sizeof(ecjpake_test_cli_two)) == 0);
1155817466cbSJens Wiklander
1156817466cbSJens Wiklander /* Server derives PMS */
1157817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1159817466cbSJens Wiklander
1160817466cbSJens Wiklander TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161817466cbSJens Wiklander TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1162817466cbSJens Wiklander
116332b31808SJens Wiklander /* Server derives K as unsigned binary data */
116432b31808SJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
116532b31808SJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
116632b31808SJens Wiklander
116732b31808SJens Wiklander TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
116832b31808SJens Wiklander TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
116932b31808SJens Wiklander
1170817466cbSJens Wiklander memset(buf, 0, len); /* Avoid interferences with next step */
1171817466cbSJens Wiklander
1172817466cbSJens Wiklander /* Client derives PMS */
1173817466cbSJens Wiklander TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174817466cbSJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1175817466cbSJens Wiklander
1176817466cbSJens Wiklander TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177817466cbSJens Wiklander TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1178817466cbSJens Wiklander
117932b31808SJens Wiklander /* Client derives K as unsigned binary data */
118032b31808SJens Wiklander TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
118132b31808SJens Wiklander buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
118232b31808SJens Wiklander
118332b31808SJens Wiklander TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
118432b31808SJens Wiklander TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
118532b31808SJens Wiklander
118632b31808SJens Wiklander if (verbose != 0) {
1187817466cbSJens Wiklander mbedtls_printf("passed\n");
118832b31808SJens Wiklander }
11897901324dSJerome Forissier #endif /* ! MBEDTLS_ECJPAKE_ALT */
1190817466cbSJens Wiklander
1191817466cbSJens Wiklander cleanup:
1192817466cbSJens Wiklander mbedtls_ecjpake_free(&cli);
1193817466cbSJens Wiklander mbedtls_ecjpake_free(&srv);
1194817466cbSJens Wiklander
119532b31808SJens Wiklander if (ret != 0) {
119632b31808SJens Wiklander if (verbose != 0) {
1197817466cbSJens Wiklander mbedtls_printf("failed\n");
119832b31808SJens Wiklander }
1199817466cbSJens Wiklander
1200817466cbSJens Wiklander ret = 1;
1201817466cbSJens Wiklander }
1202817466cbSJens Wiklander
120332b31808SJens Wiklander if (verbose != 0) {
1204817466cbSJens Wiklander mbedtls_printf("\n");
120532b31808SJens Wiklander }
1206817466cbSJens Wiklander
120732b31808SJens Wiklander return ret;
1208817466cbSJens Wiklander }
1209817466cbSJens Wiklander
1210817466cbSJens Wiklander #undef TEST_ASSERT
1211817466cbSJens Wiklander
1212*b0563631STom Van Eyck #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
1213817466cbSJens Wiklander
1214817466cbSJens Wiklander #endif /* MBEDTLS_SELF_TEST */
1215817466cbSJens Wiklander
1216817466cbSJens Wiklander #endif /* MBEDTLS_ECJPAKE_C */
1217