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