1a8e1175bSopenharmony_ci/*
2a8e1175bSopenharmony_ci *  Elliptic curve J-PAKE
3a8e1175bSopenharmony_ci *
4a8e1175bSopenharmony_ci *  Copyright The Mbed TLS Contributors
5a8e1175bSopenharmony_ci *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6a8e1175bSopenharmony_ci */
7a8e1175bSopenharmony_ci
8a8e1175bSopenharmony_ci/*
9a8e1175bSopenharmony_ci * References in the code are to the Thread v1.0 Specification,
10a8e1175bSopenharmony_ci * available to members of the Thread Group http://threadgroup.org/
11a8e1175bSopenharmony_ci */
12a8e1175bSopenharmony_ci
13a8e1175bSopenharmony_ci#include "common.h"
14a8e1175bSopenharmony_ci
15a8e1175bSopenharmony_ci#if defined(MBEDTLS_ECJPAKE_C)
16a8e1175bSopenharmony_ci
17a8e1175bSopenharmony_ci#include "mbedtls/ecjpake.h"
18a8e1175bSopenharmony_ci#include "mbedtls/platform_util.h"
19a8e1175bSopenharmony_ci#include "mbedtls/error.h"
20a8e1175bSopenharmony_ci
21a8e1175bSopenharmony_ci#include <string.h>
22a8e1175bSopenharmony_ci
23a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECJPAKE_ALT)
24a8e1175bSopenharmony_ci
25a8e1175bSopenharmony_ci/*
26a8e1175bSopenharmony_ci * Convert a mbedtls_ecjpake_role to identifier string
27a8e1175bSopenharmony_ci */
28a8e1175bSopenharmony_cistatic const char * const ecjpake_id[] = {
29a8e1175bSopenharmony_ci    "client",
30a8e1175bSopenharmony_ci    "server"
31a8e1175bSopenharmony_ci};
32a8e1175bSopenharmony_ci
33a8e1175bSopenharmony_ci#define ID_MINE     (ecjpake_id[ctx->role])
34a8e1175bSopenharmony_ci#define ID_PEER     (ecjpake_id[1 - ctx->role])
35a8e1175bSopenharmony_ci
36a8e1175bSopenharmony_ci/**
37a8e1175bSopenharmony_ci * Helper to Compute a hash from md_type
38a8e1175bSopenharmony_ci */
39a8e1175bSopenharmony_cistatic int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
40a8e1175bSopenharmony_ci                                        const unsigned char *input, size_t ilen,
41a8e1175bSopenharmony_ci                                        unsigned char *output)
42a8e1175bSopenharmony_ci{
43a8e1175bSopenharmony_ci    return mbedtls_md(mbedtls_md_info_from_type(md_type),
44a8e1175bSopenharmony_ci                      input, ilen, output);
45a8e1175bSopenharmony_ci}
46a8e1175bSopenharmony_ci
47a8e1175bSopenharmony_ci/*
48a8e1175bSopenharmony_ci * Initialize context
49a8e1175bSopenharmony_ci */
50a8e1175bSopenharmony_civoid mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)
51a8e1175bSopenharmony_ci{
52a8e1175bSopenharmony_ci    ctx->md_type = MBEDTLS_MD_NONE;
53a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&ctx->grp);
54a8e1175bSopenharmony_ci    ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
55a8e1175bSopenharmony_ci
56a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Xm1);
57a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Xm2);
58a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Xp1);
59a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Xp2);
60a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&ctx->Xp);
61a8e1175bSopenharmony_ci
62a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->xm1);
63a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->xm2);
64a8e1175bSopenharmony_ci    mbedtls_mpi_init(&ctx->s);
65a8e1175bSopenharmony_ci}
66a8e1175bSopenharmony_ci
67a8e1175bSopenharmony_ci/*
68a8e1175bSopenharmony_ci * Free context
69a8e1175bSopenharmony_ci */
70a8e1175bSopenharmony_civoid mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)
71a8e1175bSopenharmony_ci{
72a8e1175bSopenharmony_ci    if (ctx == NULL) {
73a8e1175bSopenharmony_ci        return;
74a8e1175bSopenharmony_ci    }
75a8e1175bSopenharmony_ci
76a8e1175bSopenharmony_ci    ctx->md_type = MBEDTLS_MD_NONE;
77a8e1175bSopenharmony_ci    mbedtls_ecp_group_free(&ctx->grp);
78a8e1175bSopenharmony_ci
79a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Xm1);
80a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Xm2);
81a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Xp1);
82a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Xp2);
83a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&ctx->Xp);
84a8e1175bSopenharmony_ci
85a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->xm1);
86a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->xm2);
87a8e1175bSopenharmony_ci    mbedtls_mpi_free(&ctx->s);
88a8e1175bSopenharmony_ci}
89a8e1175bSopenharmony_ci
90a8e1175bSopenharmony_ci/*
91a8e1175bSopenharmony_ci * Setup context
92a8e1175bSopenharmony_ci */
93a8e1175bSopenharmony_ciint mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
94a8e1175bSopenharmony_ci                          mbedtls_ecjpake_role role,
95a8e1175bSopenharmony_ci                          mbedtls_md_type_t hash,
96a8e1175bSopenharmony_ci                          mbedtls_ecp_group_id curve,
97a8e1175bSopenharmony_ci                          const unsigned char *secret,
98a8e1175bSopenharmony_ci                          size_t len)
99a8e1175bSopenharmony_ci{
100a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101a8e1175bSopenharmony_ci
102a8e1175bSopenharmony_ci    if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {
103a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
104a8e1175bSopenharmony_ci    }
105a8e1175bSopenharmony_ci
106a8e1175bSopenharmony_ci    ctx->role = role;
107a8e1175bSopenharmony_ci
108a8e1175bSopenharmony_ci    if ((mbedtls_md_info_from_type(hash)) == NULL) {
109a8e1175bSopenharmony_ci        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
110a8e1175bSopenharmony_ci    }
111a8e1175bSopenharmony_ci
112a8e1175bSopenharmony_ci    ctx->md_type = hash;
113a8e1175bSopenharmony_ci
114a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));
115a8e1175bSopenharmony_ci
116a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));
117a8e1175bSopenharmony_ci
118a8e1175bSopenharmony_cicleanup:
119a8e1175bSopenharmony_ci    if (ret != 0) {
120a8e1175bSopenharmony_ci        mbedtls_ecjpake_free(ctx);
121a8e1175bSopenharmony_ci    }
122a8e1175bSopenharmony_ci
123a8e1175bSopenharmony_ci    return ret;
124a8e1175bSopenharmony_ci}
125a8e1175bSopenharmony_ci
126a8e1175bSopenharmony_ciint mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,
127a8e1175bSopenharmony_ci                                     int point_format)
128a8e1175bSopenharmony_ci{
129a8e1175bSopenharmony_ci    switch (point_format) {
130a8e1175bSopenharmony_ci        case MBEDTLS_ECP_PF_UNCOMPRESSED:
131a8e1175bSopenharmony_ci        case MBEDTLS_ECP_PF_COMPRESSED:
132a8e1175bSopenharmony_ci            ctx->point_format = point_format;
133a8e1175bSopenharmony_ci            return 0;
134a8e1175bSopenharmony_ci        default:
135a8e1175bSopenharmony_ci            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
136a8e1175bSopenharmony_ci    }
137a8e1175bSopenharmony_ci}
138a8e1175bSopenharmony_ci
139a8e1175bSopenharmony_ci/*
140a8e1175bSopenharmony_ci * Check if context is ready for use
141a8e1175bSopenharmony_ci */
142a8e1175bSopenharmony_ciint mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)
143a8e1175bSopenharmony_ci{
144a8e1175bSopenharmony_ci    if (ctx->md_type == MBEDTLS_MD_NONE ||
145a8e1175bSopenharmony_ci        ctx->grp.id == MBEDTLS_ECP_DP_NONE ||
146a8e1175bSopenharmony_ci        ctx->s.p == NULL) {
147a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
148a8e1175bSopenharmony_ci    }
149a8e1175bSopenharmony_ci
150a8e1175bSopenharmony_ci    return 0;
151a8e1175bSopenharmony_ci}
152a8e1175bSopenharmony_ci
153a8e1175bSopenharmony_ci/*
154a8e1175bSopenharmony_ci * Write a point plus its length to a buffer
155a8e1175bSopenharmony_ci */
156a8e1175bSopenharmony_cistatic int ecjpake_write_len_point(unsigned char **p,
157a8e1175bSopenharmony_ci                                   const unsigned char *end,
158a8e1175bSopenharmony_ci                                   const mbedtls_ecp_group *grp,
159a8e1175bSopenharmony_ci                                   const int pf,
160a8e1175bSopenharmony_ci                                   const mbedtls_ecp_point *P)
161a8e1175bSopenharmony_ci{
162a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
163a8e1175bSopenharmony_ci    size_t len;
164a8e1175bSopenharmony_ci
165a8e1175bSopenharmony_ci    /* Need at least 4 for length plus 1 for point */
166a8e1175bSopenharmony_ci    if (end < *p || end - *p < 5) {
167a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
168a8e1175bSopenharmony_ci    }
169a8e1175bSopenharmony_ci
170a8e1175bSopenharmony_ci    ret = mbedtls_ecp_point_write_binary(grp, P, pf,
171a8e1175bSopenharmony_ci                                         &len, *p + 4, (size_t) (end - (*p + 4)));
172a8e1175bSopenharmony_ci    if (ret != 0) {
173a8e1175bSopenharmony_ci        return ret;
174a8e1175bSopenharmony_ci    }
175a8e1175bSopenharmony_ci
176a8e1175bSopenharmony_ci    MBEDTLS_PUT_UINT32_BE(len, *p, 0);
177a8e1175bSopenharmony_ci
178a8e1175bSopenharmony_ci    *p += 4 + len;
179a8e1175bSopenharmony_ci
180a8e1175bSopenharmony_ci    return 0;
181a8e1175bSopenharmony_ci}
182a8e1175bSopenharmony_ci
183a8e1175bSopenharmony_ci/*
184a8e1175bSopenharmony_ci * Size of the temporary buffer for ecjpake_hash:
185a8e1175bSopenharmony_ci * 3 EC points plus their length, plus ID and its length (4 + 6 bytes)
186a8e1175bSopenharmony_ci */
187a8e1175bSopenharmony_ci#define ECJPAKE_HASH_BUF_LEN    (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)
188a8e1175bSopenharmony_ci
189a8e1175bSopenharmony_ci/*
190a8e1175bSopenharmony_ci * Compute hash for ZKP (7.4.2.2.2.1)
191a8e1175bSopenharmony_ci */
192a8e1175bSopenharmony_cistatic int ecjpake_hash(const mbedtls_md_type_t md_type,
193a8e1175bSopenharmony_ci                        const mbedtls_ecp_group *grp,
194a8e1175bSopenharmony_ci                        const int pf,
195a8e1175bSopenharmony_ci                        const mbedtls_ecp_point *G,
196a8e1175bSopenharmony_ci                        const mbedtls_ecp_point *V,
197a8e1175bSopenharmony_ci                        const mbedtls_ecp_point *X,
198a8e1175bSopenharmony_ci                        const char *id,
199a8e1175bSopenharmony_ci                        mbedtls_mpi *h)
200a8e1175bSopenharmony_ci{
201a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
202a8e1175bSopenharmony_ci    unsigned char buf[ECJPAKE_HASH_BUF_LEN];
203a8e1175bSopenharmony_ci    unsigned char *p = buf;
204a8e1175bSopenharmony_ci    const unsigned char *end = buf + sizeof(buf);
205a8e1175bSopenharmony_ci    const size_t id_len = strlen(id);
206a8e1175bSopenharmony_ci    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
207a8e1175bSopenharmony_ci
208a8e1175bSopenharmony_ci    /* Write things to temporary buffer */
209a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
210a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));
211a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));
212a8e1175bSopenharmony_ci
213a8e1175bSopenharmony_ci    if (end - p < 4) {
214a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
215a8e1175bSopenharmony_ci    }
216a8e1175bSopenharmony_ci
217a8e1175bSopenharmony_ci    MBEDTLS_PUT_UINT32_BE(id_len, p, 0);
218a8e1175bSopenharmony_ci    p += 4;
219a8e1175bSopenharmony_ci
220a8e1175bSopenharmony_ci    if (end < p || (size_t) (end - p) < id_len) {
221a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
222a8e1175bSopenharmony_ci    }
223a8e1175bSopenharmony_ci
224a8e1175bSopenharmony_ci    memcpy(p, id, id_len);
225a8e1175bSopenharmony_ci    p += id_len;
226a8e1175bSopenharmony_ci
227a8e1175bSopenharmony_ci    /* Compute hash */
228a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
229a8e1175bSopenharmony_ci                                                 buf, (size_t) (p - buf), hash));
230a8e1175bSopenharmony_ci
231a8e1175bSopenharmony_ci    /* Turn it into an integer mod n */
232a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
233a8e1175bSopenharmony_ci                                            mbedtls_md_get_size_from_type(md_type)));
234a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
235a8e1175bSopenharmony_ci
236a8e1175bSopenharmony_cicleanup:
237a8e1175bSopenharmony_ci    return ret;
238a8e1175bSopenharmony_ci}
239a8e1175bSopenharmony_ci
240a8e1175bSopenharmony_ci/*
241a8e1175bSopenharmony_ci * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
242a8e1175bSopenharmony_ci */
243a8e1175bSopenharmony_cistatic int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
244a8e1175bSopenharmony_ci                            const mbedtls_ecp_group *grp,
245a8e1175bSopenharmony_ci                            const int pf,
246a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *G,
247a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *X,
248a8e1175bSopenharmony_ci                            const char *id,
249a8e1175bSopenharmony_ci                            const unsigned char **p,
250a8e1175bSopenharmony_ci                            const unsigned char *end)
251a8e1175bSopenharmony_ci{
252a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253a8e1175bSopenharmony_ci    mbedtls_ecp_point V, VV;
254a8e1175bSopenharmony_ci    mbedtls_mpi r, h;
255a8e1175bSopenharmony_ci    size_t r_len;
256a8e1175bSopenharmony_ci
257a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&V);
258a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&VV);
259a8e1175bSopenharmony_ci    mbedtls_mpi_init(&r);
260a8e1175bSopenharmony_ci    mbedtls_mpi_init(&h);
261a8e1175bSopenharmony_ci
262a8e1175bSopenharmony_ci    /*
263a8e1175bSopenharmony_ci     * struct {
264a8e1175bSopenharmony_ci     *     ECPoint V;
265a8e1175bSopenharmony_ci     *     opaque r<1..2^8-1>;
266a8e1175bSopenharmony_ci     * } ECSchnorrZKP;
267a8e1175bSopenharmony_ci     */
268a8e1175bSopenharmony_ci    if (end < *p) {
269a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
270a8e1175bSopenharmony_ci    }
271a8e1175bSopenharmony_ci
272a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
273a8e1175bSopenharmony_ci
274a8e1175bSopenharmony_ci    if (end < *p || (size_t) (end - *p) < 1) {
275a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
276a8e1175bSopenharmony_ci        goto cleanup;
277a8e1175bSopenharmony_ci    }
278a8e1175bSopenharmony_ci
279a8e1175bSopenharmony_ci    r_len = *(*p)++;
280a8e1175bSopenharmony_ci
281a8e1175bSopenharmony_ci    if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {
282a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
283a8e1175bSopenharmony_ci        goto cleanup;
284a8e1175bSopenharmony_ci    }
285a8e1175bSopenharmony_ci
286a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));
287a8e1175bSopenharmony_ci    *p += r_len;
288a8e1175bSopenharmony_ci
289a8e1175bSopenharmony_ci    /*
290a8e1175bSopenharmony_ci     * Verification
291a8e1175bSopenharmony_ci     */
292a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
293a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,
294a8e1175bSopenharmony_ci                                       &VV, &h, X, &r, G));
295a8e1175bSopenharmony_ci
296a8e1175bSopenharmony_ci    if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {
297a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
298a8e1175bSopenharmony_ci        goto cleanup;
299a8e1175bSopenharmony_ci    }
300a8e1175bSopenharmony_ci
301a8e1175bSopenharmony_cicleanup:
302a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&V);
303a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&VV);
304a8e1175bSopenharmony_ci    mbedtls_mpi_free(&r);
305a8e1175bSopenharmony_ci    mbedtls_mpi_free(&h);
306a8e1175bSopenharmony_ci
307a8e1175bSopenharmony_ci    return ret;
308a8e1175bSopenharmony_ci}
309a8e1175bSopenharmony_ci
310a8e1175bSopenharmony_ci/*
311a8e1175bSopenharmony_ci * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
312a8e1175bSopenharmony_ci */
313a8e1175bSopenharmony_cistatic int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
314a8e1175bSopenharmony_ci                             const mbedtls_ecp_group *grp,
315a8e1175bSopenharmony_ci                             const int pf,
316a8e1175bSopenharmony_ci                             const mbedtls_ecp_point *G,
317a8e1175bSopenharmony_ci                             const mbedtls_mpi *x,
318a8e1175bSopenharmony_ci                             const mbedtls_ecp_point *X,
319a8e1175bSopenharmony_ci                             const char *id,
320a8e1175bSopenharmony_ci                             unsigned char **p,
321a8e1175bSopenharmony_ci                             const unsigned char *end,
322a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t),
323a8e1175bSopenharmony_ci                             void *p_rng)
324a8e1175bSopenharmony_ci{
325a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326a8e1175bSopenharmony_ci    mbedtls_ecp_point V;
327a8e1175bSopenharmony_ci    mbedtls_mpi v;
328a8e1175bSopenharmony_ci    mbedtls_mpi h; /* later recycled to hold r */
329a8e1175bSopenharmony_ci    size_t len;
330a8e1175bSopenharmony_ci
331a8e1175bSopenharmony_ci    if (end < *p) {
332a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
333a8e1175bSopenharmony_ci    }
334a8e1175bSopenharmony_ci
335a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&V);
336a8e1175bSopenharmony_ci    mbedtls_mpi_init(&v);
337a8e1175bSopenharmony_ci    mbedtls_mpi_init(&h);
338a8e1175bSopenharmony_ci
339a8e1175bSopenharmony_ci    /* Compute signature */
340a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,
341a8e1175bSopenharmony_ci                                                 G, &v, &V, f_rng, p_rng));
342a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));
343a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x));     /* x*h */
344a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h));     /* v - x*h */
345a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N));     /* r */
346a8e1175bSopenharmony_ci
347a8e1175bSopenharmony_ci    /* Write it out */
348a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
349a8e1175bSopenharmony_ci                                                pf, &len, *p, (size_t) (end - *p)));
350a8e1175bSopenharmony_ci    *p += len;
351a8e1175bSopenharmony_ci
352a8e1175bSopenharmony_ci    len = mbedtls_mpi_size(&h);   /* actually r */
353a8e1175bSopenharmony_ci    if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {
354a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
355a8e1175bSopenharmony_ci        goto cleanup;
356a8e1175bSopenharmony_ci    }
357a8e1175bSopenharmony_ci
358a8e1175bSopenharmony_ci    *(*p)++ = MBEDTLS_BYTE_0(len);
359a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len));     /* r */
360a8e1175bSopenharmony_ci    *p += len;
361a8e1175bSopenharmony_ci
362a8e1175bSopenharmony_cicleanup:
363a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&V);
364a8e1175bSopenharmony_ci    mbedtls_mpi_free(&v);
365a8e1175bSopenharmony_ci    mbedtls_mpi_free(&h);
366a8e1175bSopenharmony_ci
367a8e1175bSopenharmony_ci    return ret;
368a8e1175bSopenharmony_ci}
369a8e1175bSopenharmony_ci
370a8e1175bSopenharmony_ci/*
371a8e1175bSopenharmony_ci * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof
372a8e1175bSopenharmony_ci * Output: verified public key X
373a8e1175bSopenharmony_ci */
374a8e1175bSopenharmony_cistatic int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
375a8e1175bSopenharmony_ci                            const mbedtls_ecp_group *grp,
376a8e1175bSopenharmony_ci                            const int pf,
377a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *G,
378a8e1175bSopenharmony_ci                            mbedtls_ecp_point *X,
379a8e1175bSopenharmony_ci                            const char *id,
380a8e1175bSopenharmony_ci                            const unsigned char **p,
381a8e1175bSopenharmony_ci                            const unsigned char *end)
382a8e1175bSopenharmony_ci{
383a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
384a8e1175bSopenharmony_ci
385a8e1175bSopenharmony_ci    if (end < *p) {
386a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
387a8e1175bSopenharmony_ci    }
388a8e1175bSopenharmony_ci
389a8e1175bSopenharmony_ci    /*
390a8e1175bSopenharmony_ci     * struct {
391a8e1175bSopenharmony_ci     *     ECPoint X;
392a8e1175bSopenharmony_ci     *     ECSchnorrZKP zkp;
393a8e1175bSopenharmony_ci     * } ECJPAKEKeyKP;
394a8e1175bSopenharmony_ci     */
395a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
396a8e1175bSopenharmony_ci    if (mbedtls_ecp_is_zero(X)) {
397a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_INVALID_KEY;
398a8e1175bSopenharmony_ci        goto cleanup;
399a8e1175bSopenharmony_ci    }
400a8e1175bSopenharmony_ci
401a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));
402a8e1175bSopenharmony_ci
403a8e1175bSopenharmony_cicleanup:
404a8e1175bSopenharmony_ci    return ret;
405a8e1175bSopenharmony_ci}
406a8e1175bSopenharmony_ci
407a8e1175bSopenharmony_ci/*
408a8e1175bSopenharmony_ci * Generate an ECJPAKEKeyKP
409a8e1175bSopenharmony_ci * Output: the serialized structure, plus private/public key pair
410a8e1175bSopenharmony_ci */
411a8e1175bSopenharmony_cistatic int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
412a8e1175bSopenharmony_ci                             const mbedtls_ecp_group *grp,
413a8e1175bSopenharmony_ci                             const int pf,
414a8e1175bSopenharmony_ci                             const mbedtls_ecp_point *G,
415a8e1175bSopenharmony_ci                             mbedtls_mpi *x,
416a8e1175bSopenharmony_ci                             mbedtls_ecp_point *X,
417a8e1175bSopenharmony_ci                             const char *id,
418a8e1175bSopenharmony_ci                             unsigned char **p,
419a8e1175bSopenharmony_ci                             const unsigned char *end,
420a8e1175bSopenharmony_ci                             int (*f_rng)(void *, unsigned char *, size_t),
421a8e1175bSopenharmony_ci                             void *p_rng)
422a8e1175bSopenharmony_ci{
423a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
424a8e1175bSopenharmony_ci    size_t len;
425a8e1175bSopenharmony_ci
426a8e1175bSopenharmony_ci    if (end < *p) {
427a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
428a8e1175bSopenharmony_ci    }
429a8e1175bSopenharmony_ci
430a8e1175bSopenharmony_ci    /* Generate key (7.4.2.3.1) and write it out */
431a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
432a8e1175bSopenharmony_ci                                                 f_rng, p_rng));
433a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
434a8e1175bSopenharmony_ci                                                pf, &len, *p, (size_t) (end - *p)));
435a8e1175bSopenharmony_ci    *p += len;
436a8e1175bSopenharmony_ci
437a8e1175bSopenharmony_ci    /* Generate and write proof */
438a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,
439a8e1175bSopenharmony_ci                                      p, end, f_rng, p_rng));
440a8e1175bSopenharmony_ci
441a8e1175bSopenharmony_cicleanup:
442a8e1175bSopenharmony_ci    return ret;
443a8e1175bSopenharmony_ci}
444a8e1175bSopenharmony_ci
445a8e1175bSopenharmony_ci/*
446a8e1175bSopenharmony_ci * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
447a8e1175bSopenharmony_ci * Outputs: verified peer public keys Xa, Xb
448a8e1175bSopenharmony_ci */
449a8e1175bSopenharmony_cistatic int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,
450a8e1175bSopenharmony_ci                             const mbedtls_ecp_group *grp,
451a8e1175bSopenharmony_ci                             const int pf,
452a8e1175bSopenharmony_ci                             const mbedtls_ecp_point *G,
453a8e1175bSopenharmony_ci                             mbedtls_ecp_point *Xa,
454a8e1175bSopenharmony_ci                             mbedtls_ecp_point *Xb,
455a8e1175bSopenharmony_ci                             const char *id,
456a8e1175bSopenharmony_ci                             const unsigned char *buf,
457a8e1175bSopenharmony_ci                             size_t len)
458a8e1175bSopenharmony_ci{
459a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
460a8e1175bSopenharmony_ci    const unsigned char *p = buf;
461a8e1175bSopenharmony_ci    const unsigned char *end = buf + len;
462a8e1175bSopenharmony_ci
463a8e1175bSopenharmony_ci    /*
464a8e1175bSopenharmony_ci     * struct {
465a8e1175bSopenharmony_ci     *     ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];
466a8e1175bSopenharmony_ci     * } ECJPAKEKeyKPPairList;
467a8e1175bSopenharmony_ci     */
468a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));
469a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));
470a8e1175bSopenharmony_ci
471a8e1175bSopenharmony_ci    if (p != end) {
472a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
473a8e1175bSopenharmony_ci    }
474a8e1175bSopenharmony_ci
475a8e1175bSopenharmony_cicleanup:
476a8e1175bSopenharmony_ci    return ret;
477a8e1175bSopenharmony_ci}
478a8e1175bSopenharmony_ci
479a8e1175bSopenharmony_ci/*
480a8e1175bSopenharmony_ci * Generate a ECJPAKEKeyKPPairList
481a8e1175bSopenharmony_ci * Outputs: the serialized structure, plus two private/public key pairs
482a8e1175bSopenharmony_ci */
483a8e1175bSopenharmony_cistatic int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
484a8e1175bSopenharmony_ci                              const mbedtls_ecp_group *grp,
485a8e1175bSopenharmony_ci                              const int pf,
486a8e1175bSopenharmony_ci                              const mbedtls_ecp_point *G,
487a8e1175bSopenharmony_ci                              mbedtls_mpi *xm1,
488a8e1175bSopenharmony_ci                              mbedtls_ecp_point *Xa,
489a8e1175bSopenharmony_ci                              mbedtls_mpi *xm2,
490a8e1175bSopenharmony_ci                              mbedtls_ecp_point *Xb,
491a8e1175bSopenharmony_ci                              const char *id,
492a8e1175bSopenharmony_ci                              unsigned char *buf,
493a8e1175bSopenharmony_ci                              size_t len,
494a8e1175bSopenharmony_ci                              size_t *olen,
495a8e1175bSopenharmony_ci                              int (*f_rng)(void *, unsigned char *, size_t),
496a8e1175bSopenharmony_ci                              void *p_rng)
497a8e1175bSopenharmony_ci{
498a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
499a8e1175bSopenharmony_ci    unsigned char *p = buf;
500a8e1175bSopenharmony_ci    const unsigned char *end = buf + len;
501a8e1175bSopenharmony_ci
502a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,
503a8e1175bSopenharmony_ci                                      &p, end, f_rng, p_rng));
504a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
505a8e1175bSopenharmony_ci                                      &p, end, f_rng, p_rng));
506a8e1175bSopenharmony_ci
507a8e1175bSopenharmony_ci    *olen = (size_t) (p - buf);
508a8e1175bSopenharmony_ci
509a8e1175bSopenharmony_cicleanup:
510a8e1175bSopenharmony_ci    return ret;
511a8e1175bSopenharmony_ci}
512a8e1175bSopenharmony_ci
513a8e1175bSopenharmony_ci/*
514a8e1175bSopenharmony_ci * Read and process the first round message
515a8e1175bSopenharmony_ci */
516a8e1175bSopenharmony_ciint mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,
517a8e1175bSopenharmony_ci                                   const unsigned char *buf,
518a8e1175bSopenharmony_ci                                   size_t len)
519a8e1175bSopenharmony_ci{
520a8e1175bSopenharmony_ci    return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,
521a8e1175bSopenharmony_ci                             &ctx->grp.G,
522a8e1175bSopenharmony_ci                             &ctx->Xp1, &ctx->Xp2, ID_PEER,
523a8e1175bSopenharmony_ci                             buf, len);
524a8e1175bSopenharmony_ci}
525a8e1175bSopenharmony_ci
526a8e1175bSopenharmony_ci/*
527a8e1175bSopenharmony_ci * Generate and write the first round message
528a8e1175bSopenharmony_ci */
529a8e1175bSopenharmony_ciint mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,
530a8e1175bSopenharmony_ci                                    unsigned char *buf, size_t len, size_t *olen,
531a8e1175bSopenharmony_ci                                    int (*f_rng)(void *, unsigned char *, size_t),
532a8e1175bSopenharmony_ci                                    void *p_rng)
533a8e1175bSopenharmony_ci{
534a8e1175bSopenharmony_ci    return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,
535a8e1175bSopenharmony_ci                              &ctx->grp.G,
536a8e1175bSopenharmony_ci                              &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,
537a8e1175bSopenharmony_ci                              ID_MINE, buf, len, olen, f_rng, p_rng);
538a8e1175bSopenharmony_ci}
539a8e1175bSopenharmony_ci
540a8e1175bSopenharmony_ci/*
541a8e1175bSopenharmony_ci * Compute the sum of three points R = A + B + C
542a8e1175bSopenharmony_ci */
543a8e1175bSopenharmony_cistatic int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
544a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *A,
545a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *B,
546a8e1175bSopenharmony_ci                            const mbedtls_ecp_point *C)
547a8e1175bSopenharmony_ci{
548a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
549a8e1175bSopenharmony_ci    mbedtls_mpi one;
550a8e1175bSopenharmony_ci
551a8e1175bSopenharmony_ci    mbedtls_mpi_init(&one);
552a8e1175bSopenharmony_ci
553a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
554a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));
555a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));
556a8e1175bSopenharmony_ci
557a8e1175bSopenharmony_cicleanup:
558a8e1175bSopenharmony_ci    mbedtls_mpi_free(&one);
559a8e1175bSopenharmony_ci
560a8e1175bSopenharmony_ci    return ret;
561a8e1175bSopenharmony_ci}
562a8e1175bSopenharmony_ci
563a8e1175bSopenharmony_ci/*
564a8e1175bSopenharmony_ci * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)
565a8e1175bSopenharmony_ci */
566a8e1175bSopenharmony_ciint mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,
567a8e1175bSopenharmony_ci                                   const unsigned char *buf,
568a8e1175bSopenharmony_ci                                   size_t len)
569a8e1175bSopenharmony_ci{
570a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
571a8e1175bSopenharmony_ci    const unsigned char *p = buf;
572a8e1175bSopenharmony_ci    const unsigned char *end = buf + len;
573a8e1175bSopenharmony_ci    mbedtls_ecp_group grp;
574a8e1175bSopenharmony_ci    mbedtls_ecp_point G;    /* C: GB, S: GA */
575a8e1175bSopenharmony_ci
576a8e1175bSopenharmony_ci    mbedtls_ecp_group_init(&grp);
577a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&G);
578a8e1175bSopenharmony_ci
579a8e1175bSopenharmony_ci    /*
580a8e1175bSopenharmony_ci     * Server: GA = X3  + X4  + X1      (7.4.2.6.1)
581a8e1175bSopenharmony_ci     * Client: GB = X1  + X2  + X3      (7.4.2.5.1)
582a8e1175bSopenharmony_ci     * Unified: G = Xm1 + Xm2 + Xp1
583a8e1175bSopenharmony_ci     * We need that before parsing in order to check Xp as we read it
584a8e1175bSopenharmony_ci     */
585a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
586a8e1175bSopenharmony_ci                                     &ctx->Xm1, &ctx->Xm2, &ctx->Xp1));
587a8e1175bSopenharmony_ci
588a8e1175bSopenharmony_ci    /*
589a8e1175bSopenharmony_ci     * struct {
590a8e1175bSopenharmony_ci     *     ECParameters curve_params;   // only client reading server msg
591a8e1175bSopenharmony_ci     *     ECJPAKEKeyKP ecjpake_key_kp;
592a8e1175bSopenharmony_ci     * } Client/ServerECJPAKEParams;
593a8e1175bSopenharmony_ci     */
594a8e1175bSopenharmony_ci    if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {
595a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));
596a8e1175bSopenharmony_ci        if (grp.id != ctx->grp.id) {
597a8e1175bSopenharmony_ci            ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
598a8e1175bSopenharmony_ci            goto cleanup;
599a8e1175bSopenharmony_ci        }
600a8e1175bSopenharmony_ci    }
601a8e1175bSopenharmony_ci
602a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,
603a8e1175bSopenharmony_ci                                     ctx->point_format,
604a8e1175bSopenharmony_ci                                     &G, &ctx->Xp, ID_PEER, &p, end));
605a8e1175bSopenharmony_ci
606a8e1175bSopenharmony_ci    if (p != end) {
607a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
608a8e1175bSopenharmony_ci        goto cleanup;
609a8e1175bSopenharmony_ci    }
610a8e1175bSopenharmony_ci
611a8e1175bSopenharmony_cicleanup:
612a8e1175bSopenharmony_ci    mbedtls_ecp_group_free(&grp);
613a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&G);
614a8e1175bSopenharmony_ci
615a8e1175bSopenharmony_ci    return ret;
616a8e1175bSopenharmony_ci}
617a8e1175bSopenharmony_ci
618a8e1175bSopenharmony_ci/*
619a8e1175bSopenharmony_ci * Compute R = +/- X * S mod N, taking care not to leak S
620a8e1175bSopenharmony_ci */
621a8e1175bSopenharmony_cistatic int ecjpake_mul_secret(mbedtls_mpi *R, int sign,
622a8e1175bSopenharmony_ci                              const mbedtls_mpi *X,
623a8e1175bSopenharmony_ci                              const mbedtls_mpi *S,
624a8e1175bSopenharmony_ci                              const mbedtls_mpi *N,
625a8e1175bSopenharmony_ci                              int (*f_rng)(void *, unsigned char *, size_t),
626a8e1175bSopenharmony_ci                              void *p_rng)
627a8e1175bSopenharmony_ci{
628a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
629a8e1175bSopenharmony_ci    mbedtls_mpi b; /* Blinding value, then s + N * blinding */
630a8e1175bSopenharmony_ci
631a8e1175bSopenharmony_ci    mbedtls_mpi_init(&b);
632a8e1175bSopenharmony_ci
633a8e1175bSopenharmony_ci    /* b = s + rnd-128-bit * N */
634a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));
635a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));
636a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));
637a8e1175bSopenharmony_ci
638a8e1175bSopenharmony_ci    /* R = sign * X * b mod N */
639a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));
640a8e1175bSopenharmony_ci    R->s *= sign;
641a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));
642a8e1175bSopenharmony_ci
643a8e1175bSopenharmony_cicleanup:
644a8e1175bSopenharmony_ci    mbedtls_mpi_free(&b);
645a8e1175bSopenharmony_ci
646a8e1175bSopenharmony_ci    return ret;
647a8e1175bSopenharmony_ci}
648a8e1175bSopenharmony_ci
649a8e1175bSopenharmony_ci/*
650a8e1175bSopenharmony_ci * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)
651a8e1175bSopenharmony_ci */
652a8e1175bSopenharmony_ciint mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
653a8e1175bSopenharmony_ci                                    unsigned char *buf, size_t len, size_t *olen,
654a8e1175bSopenharmony_ci                                    int (*f_rng)(void *, unsigned char *, size_t),
655a8e1175bSopenharmony_ci                                    void *p_rng)
656a8e1175bSopenharmony_ci{
657a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
658a8e1175bSopenharmony_ci    mbedtls_ecp_point G;    /* C: GA, S: GB */
659a8e1175bSopenharmony_ci    mbedtls_ecp_point Xm;   /* C: Xc, S: Xs */
660a8e1175bSopenharmony_ci    mbedtls_mpi xm;         /* C: xc, S: xs */
661a8e1175bSopenharmony_ci    unsigned char *p = buf;
662a8e1175bSopenharmony_ci    const unsigned char *end = buf + len;
663a8e1175bSopenharmony_ci    size_t ec_len;
664a8e1175bSopenharmony_ci
665a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&G);
666a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&Xm);
667a8e1175bSopenharmony_ci    mbedtls_mpi_init(&xm);
668a8e1175bSopenharmony_ci
669a8e1175bSopenharmony_ci    /*
670a8e1175bSopenharmony_ci     * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)
671a8e1175bSopenharmony_ci     *
672a8e1175bSopenharmony_ci     * Client:  GA = X1  + X3  + X4  | xs = x2  * s | Xc = xc * GA
673a8e1175bSopenharmony_ci     * Server:  GB = X3  + X1  + X2  | xs = x4  * s | Xs = xs * GB
674a8e1175bSopenharmony_ci     * Unified: G  = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G
675a8e1175bSopenharmony_ci     */
676a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,
677a8e1175bSopenharmony_ci                                     &ctx->Xp1, &ctx->Xp2, &ctx->Xm1));
678a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,
679a8e1175bSopenharmony_ci                                       &ctx->grp.N, f_rng, p_rng));
680a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));
681a8e1175bSopenharmony_ci
682a8e1175bSopenharmony_ci    /*
683a8e1175bSopenharmony_ci     * Now write things out
684a8e1175bSopenharmony_ci     *
685a8e1175bSopenharmony_ci     * struct {
686a8e1175bSopenharmony_ci     *     ECParameters curve_params;   // only server writing its message
687a8e1175bSopenharmony_ci     *     ECJPAKEKeyKP ecjpake_key_kp;
688a8e1175bSopenharmony_ci     * } Client/ServerECJPAKEParams;
689a8e1175bSopenharmony_ci     */
690a8e1175bSopenharmony_ci    if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {
691a8e1175bSopenharmony_ci        if (end < p) {
692a8e1175bSopenharmony_ci            ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
693a8e1175bSopenharmony_ci            goto cleanup;
694a8e1175bSopenharmony_ci        }
695a8e1175bSopenharmony_ci        MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
696a8e1175bSopenharmony_ci                                                    p, (size_t) (end - p)));
697a8e1175bSopenharmony_ci        p += ec_len;
698a8e1175bSopenharmony_ci    }
699a8e1175bSopenharmony_ci
700a8e1175bSopenharmony_ci    if (end < p) {
701a8e1175bSopenharmony_ci        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
702a8e1175bSopenharmony_ci        goto cleanup;
703a8e1175bSopenharmony_ci    }
704a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
705a8e1175bSopenharmony_ci                                                ctx->point_format, &ec_len, p, (size_t) (end - p)));
706a8e1175bSopenharmony_ci    p += ec_len;
707a8e1175bSopenharmony_ci
708a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
709a8e1175bSopenharmony_ci                                      ctx->point_format,
710a8e1175bSopenharmony_ci                                      &G, &xm, &Xm, ID_MINE,
711a8e1175bSopenharmony_ci                                      &p, end, f_rng, p_rng));
712a8e1175bSopenharmony_ci
713a8e1175bSopenharmony_ci    *olen = (size_t) (p - buf);
714a8e1175bSopenharmony_ci
715a8e1175bSopenharmony_cicleanup:
716a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&G);
717a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&Xm);
718a8e1175bSopenharmony_ci    mbedtls_mpi_free(&xm);
719a8e1175bSopenharmony_ci
720a8e1175bSopenharmony_ci    return ret;
721a8e1175bSopenharmony_ci}
722a8e1175bSopenharmony_ci
723a8e1175bSopenharmony_ci/*
724a8e1175bSopenharmony_ci * Derive PMS (7.4.2.7 / 7.4.2.8)
725a8e1175bSopenharmony_ci */
726a8e1175bSopenharmony_cistatic int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,
727a8e1175bSopenharmony_ci                                    mbedtls_ecp_point *K,
728a8e1175bSopenharmony_ci                                    int (*f_rng)(void *, unsigned char *, size_t),
729a8e1175bSopenharmony_ci                                    void *p_rng)
730a8e1175bSopenharmony_ci{
731a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
732a8e1175bSopenharmony_ci    mbedtls_mpi m_xm2_s, one;
733a8e1175bSopenharmony_ci
734a8e1175bSopenharmony_ci    mbedtls_mpi_init(&m_xm2_s);
735a8e1175bSopenharmony_ci    mbedtls_mpi_init(&one);
736a8e1175bSopenharmony_ci
737a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));
738a8e1175bSopenharmony_ci
739a8e1175bSopenharmony_ci    /*
740a8e1175bSopenharmony_ci     * Client:  K = ( Xs - X4  * x2  * s ) * x2
741a8e1175bSopenharmony_ci     * Server:  K = ( Xc - X2  * x4  * s ) * x4
742a8e1175bSopenharmony_ci     * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2
743a8e1175bSopenharmony_ci     */
744a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,
745a8e1175bSopenharmony_ci                                       &ctx->grp.N, f_rng, p_rng));
746a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,
747a8e1175bSopenharmony_ci                                       &one, &ctx->Xp,
748a8e1175bSopenharmony_ci                                       &m_xm2_s, &ctx->Xp2));
749a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,
750a8e1175bSopenharmony_ci                                    f_rng, p_rng));
751a8e1175bSopenharmony_ci
752a8e1175bSopenharmony_cicleanup:
753a8e1175bSopenharmony_ci    mbedtls_mpi_free(&m_xm2_s);
754a8e1175bSopenharmony_ci    mbedtls_mpi_free(&one);
755a8e1175bSopenharmony_ci
756a8e1175bSopenharmony_ci    return ret;
757a8e1175bSopenharmony_ci}
758a8e1175bSopenharmony_ci
759a8e1175bSopenharmony_ciint mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
760a8e1175bSopenharmony_ci                                  unsigned char *buf, size_t len, size_t *olen,
761a8e1175bSopenharmony_ci                                  int (*f_rng)(void *, unsigned char *, size_t),
762a8e1175bSopenharmony_ci                                  void *p_rng)
763a8e1175bSopenharmony_ci{
764a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
765a8e1175bSopenharmony_ci    mbedtls_ecp_point K;
766a8e1175bSopenharmony_ci    unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
767a8e1175bSopenharmony_ci    size_t x_bytes;
768a8e1175bSopenharmony_ci
769a8e1175bSopenharmony_ci    *olen = mbedtls_md_get_size_from_type(ctx->md_type);
770a8e1175bSopenharmony_ci    if (len < *olen) {
771a8e1175bSopenharmony_ci        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
772a8e1175bSopenharmony_ci    }
773a8e1175bSopenharmony_ci
774a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&K);
775a8e1175bSopenharmony_ci
776a8e1175bSopenharmony_ci    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
777a8e1175bSopenharmony_ci    if (ret) {
778a8e1175bSopenharmony_ci        goto cleanup;
779a8e1175bSopenharmony_ci    }
780a8e1175bSopenharmony_ci
781a8e1175bSopenharmony_ci    /* PMS = SHA-256( K.X ) */
782a8e1175bSopenharmony_ci    x_bytes = (ctx->grp.pbits + 7) / 8;
783a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));
784a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,
785a8e1175bSopenharmony_ci                                                 kx, x_bytes, buf));
786a8e1175bSopenharmony_ci
787a8e1175bSopenharmony_cicleanup:
788a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&K);
789a8e1175bSopenharmony_ci
790a8e1175bSopenharmony_ci    return ret;
791a8e1175bSopenharmony_ci}
792a8e1175bSopenharmony_ci
793a8e1175bSopenharmony_ciint mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,
794a8e1175bSopenharmony_ci                                     unsigned char *buf, size_t len, size_t *olen,
795a8e1175bSopenharmony_ci                                     int (*f_rng)(void *, unsigned char *, size_t),
796a8e1175bSopenharmony_ci                                     void *p_rng)
797a8e1175bSopenharmony_ci{
798a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
799a8e1175bSopenharmony_ci    mbedtls_ecp_point K;
800a8e1175bSopenharmony_ci
801a8e1175bSopenharmony_ci    mbedtls_ecp_point_init(&K);
802a8e1175bSopenharmony_ci
803a8e1175bSopenharmony_ci    ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);
804a8e1175bSopenharmony_ci    if (ret) {
805a8e1175bSopenharmony_ci        goto cleanup;
806a8e1175bSopenharmony_ci    }
807a8e1175bSopenharmony_ci
808a8e1175bSopenharmony_ci    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,
809a8e1175bSopenharmony_ci                                         olen, buf, len);
810a8e1175bSopenharmony_ci    if (ret != 0) {
811a8e1175bSopenharmony_ci        goto cleanup;
812a8e1175bSopenharmony_ci    }
813a8e1175bSopenharmony_ci
814a8e1175bSopenharmony_cicleanup:
815a8e1175bSopenharmony_ci    mbedtls_ecp_point_free(&K);
816a8e1175bSopenharmony_ci
817a8e1175bSopenharmony_ci    return ret;
818a8e1175bSopenharmony_ci}
819a8e1175bSopenharmony_ci
820a8e1175bSopenharmony_ci#undef ID_MINE
821a8e1175bSopenharmony_ci#undef ID_PEER
822a8e1175bSopenharmony_ci
823a8e1175bSopenharmony_ci#endif /* ! MBEDTLS_ECJPAKE_ALT */
824a8e1175bSopenharmony_ci
825a8e1175bSopenharmony_ci#if defined(MBEDTLS_SELF_TEST)
826a8e1175bSopenharmony_ci
827a8e1175bSopenharmony_ci#include "mbedtls/platform.h"
828a8e1175bSopenharmony_ci
829a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
830a8e1175bSopenharmony_ci    !defined(MBEDTLS_MD_CAN_SHA256)
831a8e1175bSopenharmony_ciint mbedtls_ecjpake_self_test(int verbose)
832a8e1175bSopenharmony_ci{
833a8e1175bSopenharmony_ci    (void) verbose;
834a8e1175bSopenharmony_ci    return 0;
835a8e1175bSopenharmony_ci}
836a8e1175bSopenharmony_ci#else
837a8e1175bSopenharmony_ci
838a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_password[] = {
839a8e1175bSopenharmony_ci    0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,
840a8e1175bSopenharmony_ci    0x65, 0x73, 0x74
841a8e1175bSopenharmony_ci};
842a8e1175bSopenharmony_ci
843a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECJPAKE_ALT)
844a8e1175bSopenharmony_ci
845a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_x1[] = {
846a8e1175bSopenharmony_ci    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
847a8e1175bSopenharmony_ci    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
848a8e1175bSopenharmony_ci    0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21
849a8e1175bSopenharmony_ci};
850a8e1175bSopenharmony_ci
851a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_x2[] = {
852a8e1175bSopenharmony_ci    0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
853a8e1175bSopenharmony_ci    0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
854a8e1175bSopenharmony_ci    0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
855a8e1175bSopenharmony_ci};
856a8e1175bSopenharmony_ci
857a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_x3[] = {
858a8e1175bSopenharmony_ci    0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
859a8e1175bSopenharmony_ci    0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
860a8e1175bSopenharmony_ci    0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81
861a8e1175bSopenharmony_ci};
862a8e1175bSopenharmony_ci
863a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_x4[] = {
864a8e1175bSopenharmony_ci    0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,
865a8e1175bSopenharmony_ci    0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
866a8e1175bSopenharmony_ci    0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1
867a8e1175bSopenharmony_ci};
868a8e1175bSopenharmony_ci
869a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_cli_one[] = {
870a8e1175bSopenharmony_ci    0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,
871a8e1175bSopenharmony_ci    0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,
872a8e1175bSopenharmony_ci    0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,
873a8e1175bSopenharmony_ci    0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,
874a8e1175bSopenharmony_ci    0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,
875a8e1175bSopenharmony_ci    0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,
876a8e1175bSopenharmony_ci    0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,
877a8e1175bSopenharmony_ci    0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,
878a8e1175bSopenharmony_ci    0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,
879a8e1175bSopenharmony_ci    0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,
880a8e1175bSopenharmony_ci    0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,
881a8e1175bSopenharmony_ci    0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,
882a8e1175bSopenharmony_ci    0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,
883a8e1175bSopenharmony_ci    0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,
884a8e1175bSopenharmony_ci    0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,
885a8e1175bSopenharmony_ci    0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,
886a8e1175bSopenharmony_ci    0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,
887a8e1175bSopenharmony_ci    0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,
888a8e1175bSopenharmony_ci    0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,
889a8e1175bSopenharmony_ci    0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,
890a8e1175bSopenharmony_ci    0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,
891a8e1175bSopenharmony_ci    0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,
892a8e1175bSopenharmony_ci    0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,
893a8e1175bSopenharmony_ci    0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,
894a8e1175bSopenharmony_ci    0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,
895a8e1175bSopenharmony_ci    0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,
896a8e1175bSopenharmony_ci    0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,
897a8e1175bSopenharmony_ci    0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0
898a8e1175bSopenharmony_ci};
899a8e1175bSopenharmony_ci
900a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_srv_one[] = {
901a8e1175bSopenharmony_ci    0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,
902a8e1175bSopenharmony_ci    0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,
903a8e1175bSopenharmony_ci    0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,
904a8e1175bSopenharmony_ci    0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,
905a8e1175bSopenharmony_ci    0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,
906a8e1175bSopenharmony_ci    0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,
907a8e1175bSopenharmony_ci    0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,
908a8e1175bSopenharmony_ci    0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,
909a8e1175bSopenharmony_ci    0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,
910a8e1175bSopenharmony_ci    0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,
911a8e1175bSopenharmony_ci    0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,
912a8e1175bSopenharmony_ci    0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,
913a8e1175bSopenharmony_ci    0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,
914a8e1175bSopenharmony_ci    0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,
915a8e1175bSopenharmony_ci    0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,
916a8e1175bSopenharmony_ci    0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,
917a8e1175bSopenharmony_ci    0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,
918a8e1175bSopenharmony_ci    0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,
919a8e1175bSopenharmony_ci    0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,
920a8e1175bSopenharmony_ci    0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,
921a8e1175bSopenharmony_ci    0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,
922a8e1175bSopenharmony_ci    0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,
923a8e1175bSopenharmony_ci    0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,
924a8e1175bSopenharmony_ci    0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,
925a8e1175bSopenharmony_ci    0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,
926a8e1175bSopenharmony_ci    0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,
927a8e1175bSopenharmony_ci    0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,
928a8e1175bSopenharmony_ci    0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12
929a8e1175bSopenharmony_ci};
930a8e1175bSopenharmony_ci
931a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_srv_two[] = {
932a8e1175bSopenharmony_ci    0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,
933a8e1175bSopenharmony_ci    0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,
934a8e1175bSopenharmony_ci    0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,
935a8e1175bSopenharmony_ci    0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,
936a8e1175bSopenharmony_ci    0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,
937a8e1175bSopenharmony_ci    0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,
938a8e1175bSopenharmony_ci    0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,
939a8e1175bSopenharmony_ci    0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,
940a8e1175bSopenharmony_ci    0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,
941a8e1175bSopenharmony_ci    0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,
942a8e1175bSopenharmony_ci    0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,
943a8e1175bSopenharmony_ci    0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,
944a8e1175bSopenharmony_ci    0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,
945a8e1175bSopenharmony_ci    0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c
946a8e1175bSopenharmony_ci};
947a8e1175bSopenharmony_ci
948a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_cli_two[] = {
949a8e1175bSopenharmony_ci    0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,
950a8e1175bSopenharmony_ci    0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,
951a8e1175bSopenharmony_ci    0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,
952a8e1175bSopenharmony_ci    0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,
953a8e1175bSopenharmony_ci    0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,
954a8e1175bSopenharmony_ci    0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,
955a8e1175bSopenharmony_ci    0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,
956a8e1175bSopenharmony_ci    0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,
957a8e1175bSopenharmony_ci    0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,
958a8e1175bSopenharmony_ci    0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,
959a8e1175bSopenharmony_ci    0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,
960a8e1175bSopenharmony_ci    0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,
961a8e1175bSopenharmony_ci    0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,
962a8e1175bSopenharmony_ci    0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c
963a8e1175bSopenharmony_ci};
964a8e1175bSopenharmony_ci
965a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_shared_key[] = {
966a8e1175bSopenharmony_ci    0x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,
967a8e1175bSopenharmony_ci    0xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,
968a8e1175bSopenharmony_ci    0xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,
969a8e1175bSopenharmony_ci    0x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,
970a8e1175bSopenharmony_ci    0x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,
971a8e1175bSopenharmony_ci    0x17, 0xc3, 0xde, 0x27, 0xb4,
972a8e1175bSopenharmony_ci};
973a8e1175bSopenharmony_ci
974a8e1175bSopenharmony_cistatic const unsigned char ecjpake_test_pms[] = {
975a8e1175bSopenharmony_ci    0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,
976a8e1175bSopenharmony_ci    0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,
977a8e1175bSopenharmony_ci    0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51
978a8e1175bSopenharmony_ci};
979a8e1175bSopenharmony_ci
980a8e1175bSopenharmony_ci/*
981a8e1175bSopenharmony_ci * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
982a8e1175bSopenharmony_ci *
983a8e1175bSopenharmony_ci * This is the linear congruential generator from numerical recipes,
984a8e1175bSopenharmony_ci * except we only use the low byte as the output. See
985a8e1175bSopenharmony_ci * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use
986a8e1175bSopenharmony_ci */
987a8e1175bSopenharmony_cistatic int self_test_rng(void *ctx, unsigned char *out, size_t len)
988a8e1175bSopenharmony_ci{
989a8e1175bSopenharmony_ci    static uint32_t state = 42;
990a8e1175bSopenharmony_ci
991a8e1175bSopenharmony_ci    (void) ctx;
992a8e1175bSopenharmony_ci
993a8e1175bSopenharmony_ci    for (size_t i = 0; i < len; i++) {
994a8e1175bSopenharmony_ci        state = state * 1664525u + 1013904223u;
995a8e1175bSopenharmony_ci        out[i] = (unsigned char) state;
996a8e1175bSopenharmony_ci    }
997a8e1175bSopenharmony_ci
998a8e1175bSopenharmony_ci    return 0;
999a8e1175bSopenharmony_ci}
1000a8e1175bSopenharmony_ci
1001a8e1175bSopenharmony_ci/* Load my private keys and generate the corresponding public keys */
1002a8e1175bSopenharmony_cistatic int ecjpake_test_load(mbedtls_ecjpake_context *ctx,
1003a8e1175bSopenharmony_ci                             const unsigned char *xm1, size_t len1,
1004a8e1175bSopenharmony_ci                             const unsigned char *xm2, size_t len2)
1005a8e1175bSopenharmony_ci{
1006a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1007a8e1175bSopenharmony_ci
1008a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));
1009a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));
1010a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,
1011a8e1175bSopenharmony_ci                                    &ctx->grp.G, self_test_rng, NULL));
1012a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,
1013a8e1175bSopenharmony_ci                                    &ctx->grp.G, self_test_rng, NULL));
1014a8e1175bSopenharmony_ci
1015a8e1175bSopenharmony_cicleanup:
1016a8e1175bSopenharmony_ci    return ret;
1017a8e1175bSopenharmony_ci}
1018a8e1175bSopenharmony_ci
1019a8e1175bSopenharmony_ci#endif /* ! MBEDTLS_ECJPAKE_ALT */
1020a8e1175bSopenharmony_ci
1021a8e1175bSopenharmony_ci/* For tests we don't need a secure RNG;
1022a8e1175bSopenharmony_ci * use the LGC from Numerical Recipes for simplicity */
1023a8e1175bSopenharmony_cistatic int ecjpake_lgc(void *p, unsigned char *out, size_t len)
1024a8e1175bSopenharmony_ci{
1025a8e1175bSopenharmony_ci    static uint32_t x = 42;
1026a8e1175bSopenharmony_ci    (void) p;
1027a8e1175bSopenharmony_ci
1028a8e1175bSopenharmony_ci    while (len > 0) {
1029a8e1175bSopenharmony_ci        size_t use_len = len > 4 ? 4 : len;
1030a8e1175bSopenharmony_ci        x = 1664525 * x + 1013904223;
1031a8e1175bSopenharmony_ci        memcpy(out, &x, use_len);
1032a8e1175bSopenharmony_ci        out += use_len;
1033a8e1175bSopenharmony_ci        len -= use_len;
1034a8e1175bSopenharmony_ci    }
1035a8e1175bSopenharmony_ci
1036a8e1175bSopenharmony_ci    return 0;
1037a8e1175bSopenharmony_ci}
1038a8e1175bSopenharmony_ci
1039a8e1175bSopenharmony_ci#define TEST_ASSERT(x)    \
1040a8e1175bSopenharmony_ci    do {                    \
1041a8e1175bSopenharmony_ci        if (x)             \
1042a8e1175bSopenharmony_ci        ret = 0;        \
1043a8e1175bSopenharmony_ci        else                \
1044a8e1175bSopenharmony_ci        {                   \
1045a8e1175bSopenharmony_ci            ret = 1;        \
1046a8e1175bSopenharmony_ci            goto cleanup;   \
1047a8e1175bSopenharmony_ci        }                   \
1048a8e1175bSopenharmony_ci    } while (0)
1049a8e1175bSopenharmony_ci
1050a8e1175bSopenharmony_ci/*
1051a8e1175bSopenharmony_ci * Checkup routine
1052a8e1175bSopenharmony_ci */
1053a8e1175bSopenharmony_ciint mbedtls_ecjpake_self_test(int verbose)
1054a8e1175bSopenharmony_ci{
1055a8e1175bSopenharmony_ci    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1056a8e1175bSopenharmony_ci    mbedtls_ecjpake_context cli;
1057a8e1175bSopenharmony_ci    mbedtls_ecjpake_context srv;
1058a8e1175bSopenharmony_ci    unsigned char buf[512], pms[32];
1059a8e1175bSopenharmony_ci    size_t len, pmslen;
1060a8e1175bSopenharmony_ci
1061a8e1175bSopenharmony_ci    mbedtls_ecjpake_init(&cli);
1062a8e1175bSopenharmony_ci    mbedtls_ecjpake_init(&srv);
1063a8e1175bSopenharmony_ci
1064a8e1175bSopenharmony_ci    if (verbose != 0) {
1065a8e1175bSopenharmony_ci        mbedtls_printf("  ECJPAKE test #0 (setup): ");
1066a8e1175bSopenharmony_ci    }
1067a8e1175bSopenharmony_ci
1068a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,
1069a8e1175bSopenharmony_ci                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1070a8e1175bSopenharmony_ci                                      ecjpake_test_password,
1071a8e1175bSopenharmony_ci                                      sizeof(ecjpake_test_password)) == 0);
1072a8e1175bSopenharmony_ci
1073a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,
1074a8e1175bSopenharmony_ci                                      MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,
1075a8e1175bSopenharmony_ci                                      ecjpake_test_password,
1076a8e1175bSopenharmony_ci                                      sizeof(ecjpake_test_password)) == 0);
1077a8e1175bSopenharmony_ci
1078a8e1175bSopenharmony_ci    if (verbose != 0) {
1079a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
1080a8e1175bSopenharmony_ci    }
1081a8e1175bSopenharmony_ci
1082a8e1175bSopenharmony_ci    if (verbose != 0) {
1083a8e1175bSopenharmony_ci        mbedtls_printf("  ECJPAKE test #1 (random handshake): ");
1084a8e1175bSopenharmony_ci    }
1085a8e1175bSopenharmony_ci
1086a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,
1087a8e1175bSopenharmony_ci                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1088a8e1175bSopenharmony_ci
1089a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);
1090a8e1175bSopenharmony_ci
1091a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,
1092a8e1175bSopenharmony_ci                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1093a8e1175bSopenharmony_ci
1094a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);
1095a8e1175bSopenharmony_ci
1096a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,
1097a8e1175bSopenharmony_ci                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1098a8e1175bSopenharmony_ci
1099a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);
1100a8e1175bSopenharmony_ci
1101a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1102a8e1175bSopenharmony_ci                                              pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);
1103a8e1175bSopenharmony_ci
1104a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,
1105a8e1175bSopenharmony_ci                                                buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1106a8e1175bSopenharmony_ci
1107a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);
1108a8e1175bSopenharmony_ci
1109a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1110a8e1175bSopenharmony_ci                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1111a8e1175bSopenharmony_ci
1112a8e1175bSopenharmony_ci    TEST_ASSERT(len == pmslen);
1113a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, pms, len) == 0);
1114a8e1175bSopenharmony_ci
1115a8e1175bSopenharmony_ci    if (verbose != 0) {
1116a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
1117a8e1175bSopenharmony_ci    }
1118a8e1175bSopenharmony_ci
1119a8e1175bSopenharmony_ci#if !defined(MBEDTLS_ECJPAKE_ALT)
1120a8e1175bSopenharmony_ci    /* 'reference handshake' tests can only be run against implementations
1121a8e1175bSopenharmony_ci     * for which we have 100% control over how the random ephemeral keys
1122a8e1175bSopenharmony_ci     * are generated. This is only the case for the internal Mbed TLS
1123a8e1175bSopenharmony_ci     * implementation, so these tests are skipped in case the internal
1124a8e1175bSopenharmony_ci     * implementation is swapped out for an alternative one. */
1125a8e1175bSopenharmony_ci    if (verbose != 0) {
1126a8e1175bSopenharmony_ci        mbedtls_printf("  ECJPAKE test #2 (reference handshake): ");
1127a8e1175bSopenharmony_ci    }
1128a8e1175bSopenharmony_ci
1129a8e1175bSopenharmony_ci    /* Simulate generation of round one */
1130a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,
1131a8e1175bSopenharmony_ci                                      ecjpake_test_x1, sizeof(ecjpake_test_x1),
1132a8e1175bSopenharmony_ci                                      ecjpake_test_x2, sizeof(ecjpake_test_x2)));
1133a8e1175bSopenharmony_ci
1134a8e1175bSopenharmony_ci    MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,
1135a8e1175bSopenharmony_ci                                      ecjpake_test_x3, sizeof(ecjpake_test_x3),
1136a8e1175bSopenharmony_ci                                      ecjpake_test_x4, sizeof(ecjpake_test_x4)));
1137a8e1175bSopenharmony_ci
1138a8e1175bSopenharmony_ci    /* Read round one */
1139a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,
1140a8e1175bSopenharmony_ci                                               ecjpake_test_cli_one,
1141a8e1175bSopenharmony_ci                                               sizeof(ecjpake_test_cli_one)) == 0);
1142a8e1175bSopenharmony_ci
1143a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,
1144a8e1175bSopenharmony_ci                                               ecjpake_test_srv_one,
1145a8e1175bSopenharmony_ci                                               sizeof(ecjpake_test_srv_one)) == 0);
1146a8e1175bSopenharmony_ci
1147a8e1175bSopenharmony_ci    /* Skip generation of round two, read round two */
1148a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,
1149a8e1175bSopenharmony_ci                                               ecjpake_test_srv_two,
1150a8e1175bSopenharmony_ci                                               sizeof(ecjpake_test_srv_two)) == 0);
1151a8e1175bSopenharmony_ci
1152a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,
1153a8e1175bSopenharmony_ci                                               ecjpake_test_cli_two,
1154a8e1175bSopenharmony_ci                                               sizeof(ecjpake_test_cli_two)) == 0);
1155a8e1175bSopenharmony_ci
1156a8e1175bSopenharmony_ci    /* Server derives PMS */
1157a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,
1158a8e1175bSopenharmony_ci                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1159a8e1175bSopenharmony_ci
1160a8e1175bSopenharmony_ci    TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1161a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1162a8e1175bSopenharmony_ci
1163a8e1175bSopenharmony_ci    /* Server derives K as unsigned binary data */
1164a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,
1165a8e1175bSopenharmony_ci                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1166a8e1175bSopenharmony_ci
1167a8e1175bSopenharmony_ci    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1168a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1169a8e1175bSopenharmony_ci
1170a8e1175bSopenharmony_ci    memset(buf, 0, len);   /* Avoid interferences with next step */
1171a8e1175bSopenharmony_ci
1172a8e1175bSopenharmony_ci    /* Client derives PMS */
1173a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,
1174a8e1175bSopenharmony_ci                                              buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1175a8e1175bSopenharmony_ci
1176a8e1175bSopenharmony_ci    TEST_ASSERT(len == sizeof(ecjpake_test_pms));
1177a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);
1178a8e1175bSopenharmony_ci
1179a8e1175bSopenharmony_ci    /* Client derives K as unsigned binary data */
1180a8e1175bSopenharmony_ci    TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,
1181a8e1175bSopenharmony_ci                                                 buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);
1182a8e1175bSopenharmony_ci
1183a8e1175bSopenharmony_ci    TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));
1184a8e1175bSopenharmony_ci    TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);
1185a8e1175bSopenharmony_ci
1186a8e1175bSopenharmony_ci    if (verbose != 0) {
1187a8e1175bSopenharmony_ci        mbedtls_printf("passed\n");
1188a8e1175bSopenharmony_ci    }
1189a8e1175bSopenharmony_ci#endif /* ! MBEDTLS_ECJPAKE_ALT */
1190a8e1175bSopenharmony_ci
1191a8e1175bSopenharmony_cicleanup:
1192a8e1175bSopenharmony_ci    mbedtls_ecjpake_free(&cli);
1193a8e1175bSopenharmony_ci    mbedtls_ecjpake_free(&srv);
1194a8e1175bSopenharmony_ci
1195a8e1175bSopenharmony_ci    if (ret != 0) {
1196a8e1175bSopenharmony_ci        if (verbose != 0) {
1197a8e1175bSopenharmony_ci            mbedtls_printf("failed\n");
1198a8e1175bSopenharmony_ci        }
1199a8e1175bSopenharmony_ci
1200a8e1175bSopenharmony_ci        ret = 1;
1201a8e1175bSopenharmony_ci    }
1202a8e1175bSopenharmony_ci
1203a8e1175bSopenharmony_ci    if (verbose != 0) {
1204a8e1175bSopenharmony_ci        mbedtls_printf("\n");
1205a8e1175bSopenharmony_ci    }
1206a8e1175bSopenharmony_ci
1207a8e1175bSopenharmony_ci    return ret;
1208a8e1175bSopenharmony_ci}
1209a8e1175bSopenharmony_ci
1210a8e1175bSopenharmony_ci#undef TEST_ASSERT
1211a8e1175bSopenharmony_ci
1212a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
1213a8e1175bSopenharmony_ci
1214a8e1175bSopenharmony_ci#endif /* MBEDTLS_SELF_TEST */
1215a8e1175bSopenharmony_ci
1216a8e1175bSopenharmony_ci#endif /* MBEDTLS_ECJPAKE_C */
1217