Path: blob/master/thirdparty/mbedtls/library/ecjpake.c
9898 views
/*1* Elliptic curve J-PAKE2*3* Copyright The Mbed TLS Contributors4* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later5*/67/*8* References in the code are to the Thread v1.0 Specification,9* available to members of the Thread Group http://threadgroup.org/10*/1112#include "common.h"1314#if defined(MBEDTLS_ECJPAKE_C)1516#include "mbedtls/ecjpake.h"17#include "mbedtls/platform_util.h"18#include "mbedtls/error.h"1920#include <string.h>2122#if !defined(MBEDTLS_ECJPAKE_ALT)2324/*25* Convert a mbedtls_ecjpake_role to identifier string26*/27static const char * const ecjpake_id[] = {28"client",29"server"30};3132#define ID_MINE (ecjpake_id[ctx->role])33#define ID_PEER (ecjpake_id[1 - ctx->role])3435/**36* Helper to Compute a hash from md_type37*/38static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,39const unsigned char *input, size_t ilen,40unsigned char *output)41{42return mbedtls_md(mbedtls_md_info_from_type(md_type),43input, ilen, output);44}4546/*47* Initialize context48*/49void mbedtls_ecjpake_init(mbedtls_ecjpake_context *ctx)50{51ctx->md_type = MBEDTLS_MD_NONE;52mbedtls_ecp_group_init(&ctx->grp);53ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;5455mbedtls_ecp_point_init(&ctx->Xm1);56mbedtls_ecp_point_init(&ctx->Xm2);57mbedtls_ecp_point_init(&ctx->Xp1);58mbedtls_ecp_point_init(&ctx->Xp2);59mbedtls_ecp_point_init(&ctx->Xp);6061mbedtls_mpi_init(&ctx->xm1);62mbedtls_mpi_init(&ctx->xm2);63mbedtls_mpi_init(&ctx->s);64}6566/*67* Free context68*/69void mbedtls_ecjpake_free(mbedtls_ecjpake_context *ctx)70{71if (ctx == NULL) {72return;73}7475ctx->md_type = MBEDTLS_MD_NONE;76mbedtls_ecp_group_free(&ctx->grp);7778mbedtls_ecp_point_free(&ctx->Xm1);79mbedtls_ecp_point_free(&ctx->Xm2);80mbedtls_ecp_point_free(&ctx->Xp1);81mbedtls_ecp_point_free(&ctx->Xp2);82mbedtls_ecp_point_free(&ctx->Xp);8384mbedtls_mpi_free(&ctx->xm1);85mbedtls_mpi_free(&ctx->xm2);86mbedtls_mpi_free(&ctx->s);87}8889/*90* Setup context91*/92int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,93mbedtls_ecjpake_role role,94mbedtls_md_type_t hash,95mbedtls_ecp_group_id curve,96const unsigned char *secret,97size_t len)98{99int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;100101if (role != MBEDTLS_ECJPAKE_CLIENT && role != MBEDTLS_ECJPAKE_SERVER) {102return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;103}104105ctx->role = role;106107if ((mbedtls_md_info_from_type(hash)) == NULL) {108return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;109}110111ctx->md_type = hash;112113MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ctx->grp, curve));114115MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->s, secret, len));116117cleanup:118if (ret != 0) {119mbedtls_ecjpake_free(ctx);120}121122return ret;123}124125int mbedtls_ecjpake_set_point_format(mbedtls_ecjpake_context *ctx,126int point_format)127{128switch (point_format) {129case MBEDTLS_ECP_PF_UNCOMPRESSED:130case MBEDTLS_ECP_PF_COMPRESSED:131ctx->point_format = point_format;132return 0;133default:134return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;135}136}137138/*139* Check if context is ready for use140*/141int mbedtls_ecjpake_check(const mbedtls_ecjpake_context *ctx)142{143if (ctx->md_type == MBEDTLS_MD_NONE ||144ctx->grp.id == MBEDTLS_ECP_DP_NONE ||145ctx->s.p == NULL) {146return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;147}148149return 0;150}151152/*153* Write a point plus its length to a buffer154*/155static int ecjpake_write_len_point(unsigned char **p,156const unsigned char *end,157const mbedtls_ecp_group *grp,158const int pf,159const mbedtls_ecp_point *P)160{161int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;162size_t len;163164/* Need at least 4 for length plus 1 for point */165if (end < *p || end - *p < 5) {166return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;167}168169ret = mbedtls_ecp_point_write_binary(grp, P, pf,170&len, *p + 4, (size_t) (end - (*p + 4)));171if (ret != 0) {172return ret;173}174175MBEDTLS_PUT_UINT32_BE(len, *p, 0);176177*p += 4 + len;178179return 0;180}181182/*183* Size of the temporary buffer for ecjpake_hash:184* 3 EC points plus their length, plus ID and its length (4 + 6 bytes)185*/186#define ECJPAKE_HASH_BUF_LEN (3 * (4 + MBEDTLS_ECP_MAX_PT_LEN) + 4 + 6)187188/*189* Compute hash for ZKP (7.4.2.2.2.1)190*/191static int ecjpake_hash(const mbedtls_md_type_t md_type,192const mbedtls_ecp_group *grp,193const int pf,194const mbedtls_ecp_point *G,195const mbedtls_ecp_point *V,196const mbedtls_ecp_point *X,197const char *id,198mbedtls_mpi *h)199{200int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;201unsigned char buf[ECJPAKE_HASH_BUF_LEN];202unsigned char *p = buf;203const unsigned char *end = buf + sizeof(buf);204const size_t id_len = strlen(id);205unsigned char hash[MBEDTLS_MD_MAX_SIZE];206207/* Write things to temporary buffer */208MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));209MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, V));210MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, X));211212if (end - p < 4) {213return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;214}215216MBEDTLS_PUT_UINT32_BE(id_len, p, 0);217p += 4;218219if (end < p || (size_t) (end - p) < id_len) {220return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;221}222223memcpy(p, id, id_len);224p += id_len;225226/* Compute hash */227MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,228buf, (size_t) (p - buf), hash));229230/* Turn it into an integer mod n */231MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,232mbedtls_md_get_size_from_type(md_type)));233MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));234235cleanup:236return ret;237}238239/*240* Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)241*/242static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,243const mbedtls_ecp_group *grp,244const int pf,245const mbedtls_ecp_point *G,246const mbedtls_ecp_point *X,247const char *id,248const unsigned char **p,249const unsigned char *end)250{251int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;252mbedtls_ecp_point V, VV;253mbedtls_mpi r, h;254size_t r_len;255256mbedtls_ecp_point_init(&V);257mbedtls_ecp_point_init(&VV);258mbedtls_mpi_init(&r);259mbedtls_mpi_init(&h);260261/*262* struct {263* ECPoint V;264* opaque r<1..2^8-1>;265* } ECSchnorrZKP;266*/267if (end < *p) {268return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;269}270271MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));272273if (end < *p || (size_t) (end - *p) < 1) {274ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;275goto cleanup;276}277278r_len = *(*p)++;279280if (end < *p || (size_t) (end - *p) < r_len || r_len == 0) {281ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;282goto cleanup;283}284285MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&r, *p, r_len));286*p += r_len;287288/*289* Verification290*/291MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));292MBEDTLS_MPI_CHK(mbedtls_ecp_muladd((mbedtls_ecp_group *) grp,293&VV, &h, X, &r, G));294295if (mbedtls_ecp_point_cmp(&VV, &V) != 0) {296ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;297goto cleanup;298}299300cleanup:301mbedtls_ecp_point_free(&V);302mbedtls_ecp_point_free(&VV);303mbedtls_mpi_free(&r);304mbedtls_mpi_free(&h);305306return ret;307}308309/*310* Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)311*/312static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,313const mbedtls_ecp_group *grp,314const int pf,315const mbedtls_ecp_point *G,316const mbedtls_mpi *x,317const mbedtls_ecp_point *X,318const char *id,319unsigned char **p,320const unsigned char *end,321int (*f_rng)(void *, unsigned char *, size_t),322void *p_rng)323{324int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;325mbedtls_ecp_point V;326mbedtls_mpi v;327mbedtls_mpi h; /* later recycled to hold r */328size_t len;329330if (end < *p) {331return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;332}333334mbedtls_ecp_point_init(&V);335mbedtls_mpi_init(&v);336mbedtls_mpi_init(&h);337338/* Compute signature */339MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp,340G, &v, &V, f_rng, p_rng));341MBEDTLS_MPI_CHK(ecjpake_hash(md_type, grp, pf, G, &V, X, id, &h));342MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&h, &h, x)); /* x*h */343MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&h, &v, &h)); /* v - x*h */344MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&h, &h, &grp->N)); /* r */345346/* Write it out */347MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,348pf, &len, *p, (size_t) (end - *p)));349*p += len;350351len = mbedtls_mpi_size(&h); /* actually r */352if (end < *p || (size_t) (end - *p) < 1 + len || len > 255) {353ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;354goto cleanup;355}356357*(*p)++ = MBEDTLS_BYTE_0(len);358MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, *p, len)); /* r */359*p += len;360361cleanup:362mbedtls_ecp_point_free(&V);363mbedtls_mpi_free(&v);364mbedtls_mpi_free(&h);365366return ret;367}368369/*370* Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof371* Output: verified public key X372*/373static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,374const mbedtls_ecp_group *grp,375const int pf,376const mbedtls_ecp_point *G,377mbedtls_ecp_point *X,378const char *id,379const unsigned char **p,380const unsigned char *end)381{382int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;383384if (end < *p) {385return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;386}387388/*389* struct {390* ECPoint X;391* ECSchnorrZKP zkp;392* } ECJPAKEKeyKP;393*/394MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));395if (mbedtls_ecp_is_zero(X)) {396ret = MBEDTLS_ERR_ECP_INVALID_KEY;397goto cleanup;398}399400MBEDTLS_MPI_CHK(ecjpake_zkp_read(md_type, grp, pf, G, X, id, p, end));401402cleanup:403return ret;404}405406/*407* Generate an ECJPAKEKeyKP408* Output: the serialized structure, plus private/public key pair409*/410static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,411const mbedtls_ecp_group *grp,412const int pf,413const mbedtls_ecp_point *G,414mbedtls_mpi *x,415mbedtls_ecp_point *X,416const char *id,417unsigned char **p,418const unsigned char *end,419int (*f_rng)(void *, unsigned char *, size_t),420void *p_rng)421{422int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;423size_t len;424425if (end < *p) {426return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;427}428429/* Generate key (7.4.2.3.1) and write it out */430MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,431f_rng, p_rng));432MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,433pf, &len, *p, (size_t) (end - *p)));434*p += len;435436/* Generate and write proof */437MBEDTLS_MPI_CHK(ecjpake_zkp_write(md_type, grp, pf, G, x, X, id,438p, end, f_rng, p_rng));439440cleanup:441return ret;442}443444/*445* Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs446* Outputs: verified peer public keys Xa, Xb447*/448static int ecjpake_kkpp_read(const mbedtls_md_type_t md_type,449const mbedtls_ecp_group *grp,450const int pf,451const mbedtls_ecp_point *G,452mbedtls_ecp_point *Xa,453mbedtls_ecp_point *Xb,454const char *id,455const unsigned char *buf,456size_t len)457{458int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;459const unsigned char *p = buf;460const unsigned char *end = buf + len;461462/*463* struct {464* ECJPAKEKeyKP ecjpake_key_kp_pair_list[2];465* } ECJPAKEKeyKPPairList;466*/467MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xa, id, &p, end));468MBEDTLS_MPI_CHK(ecjpake_kkp_read(md_type, grp, pf, G, Xb, id, &p, end));469470if (p != end) {471ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;472}473474cleanup:475return ret;476}477478/*479* Generate a ECJPAKEKeyKPPairList480* Outputs: the serialized structure, plus two private/public key pairs481*/482static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,483const mbedtls_ecp_group *grp,484const int pf,485const mbedtls_ecp_point *G,486mbedtls_mpi *xm1,487mbedtls_ecp_point *Xa,488mbedtls_mpi *xm2,489mbedtls_ecp_point *Xb,490const char *id,491unsigned char *buf,492size_t len,493size_t *olen,494int (*f_rng)(void *, unsigned char *, size_t),495void *p_rng)496{497int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;498unsigned char *p = buf;499const unsigned char *end = buf + len;500501MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm1, Xa, id,502&p, end, f_rng, p_rng));503MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,504&p, end, f_rng, p_rng));505506*olen = (size_t) (p - buf);507508cleanup:509return ret;510}511512/*513* Read and process the first round message514*/515int mbedtls_ecjpake_read_round_one(mbedtls_ecjpake_context *ctx,516const unsigned char *buf,517size_t len)518{519return ecjpake_kkpp_read(ctx->md_type, &ctx->grp, ctx->point_format,520&ctx->grp.G,521&ctx->Xp1, &ctx->Xp2, ID_PEER,522buf, len);523}524525/*526* Generate and write the first round message527*/528int mbedtls_ecjpake_write_round_one(mbedtls_ecjpake_context *ctx,529unsigned char *buf, size_t len, size_t *olen,530int (*f_rng)(void *, unsigned char *, size_t),531void *p_rng)532{533return ecjpake_kkpp_write(ctx->md_type, &ctx->grp, ctx->point_format,534&ctx->grp.G,535&ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2,536ID_MINE, buf, len, olen, f_rng, p_rng);537}538539/*540* Compute the sum of three points R = A + B + C541*/542static int ecjpake_ecp_add3(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,543const mbedtls_ecp_point *A,544const mbedtls_ecp_point *B,545const mbedtls_ecp_point *C)546{547int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;548mbedtls_mpi one;549550mbedtls_mpi_init(&one);551552MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));553MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, A, &one, B));554MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(grp, R, &one, R, &one, C));555556cleanup:557mbedtls_mpi_free(&one);558559return ret;560}561562/*563* Read and process second round message (C: 7.4.2.5, S: 7.4.2.6)564*/565int mbedtls_ecjpake_read_round_two(mbedtls_ecjpake_context *ctx,566const unsigned char *buf,567size_t len)568{569int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;570const unsigned char *p = buf;571const unsigned char *end = buf + len;572mbedtls_ecp_group grp;573mbedtls_ecp_point G; /* C: GB, S: GA */574575mbedtls_ecp_group_init(&grp);576mbedtls_ecp_point_init(&G);577578/*579* Server: GA = X3 + X4 + X1 (7.4.2.6.1)580* Client: GB = X1 + X2 + X3 (7.4.2.5.1)581* Unified: G = Xm1 + Xm2 + Xp1582* We need that before parsing in order to check Xp as we read it583*/584MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,585&ctx->Xm1, &ctx->Xm2, &ctx->Xp1));586587/*588* struct {589* ECParameters curve_params; // only client reading server msg590* ECJPAKEKeyKP ecjpake_key_kp;591* } Client/ServerECJPAKEParams;592*/593if (ctx->role == MBEDTLS_ECJPAKE_CLIENT) {594MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_group(&grp, &p, len));595if (grp.id != ctx->grp.id) {596ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;597goto cleanup;598}599}600601MBEDTLS_MPI_CHK(ecjpake_kkp_read(ctx->md_type, &ctx->grp,602ctx->point_format,603&G, &ctx->Xp, ID_PEER, &p, end));604605if (p != end) {606ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;607goto cleanup;608}609610cleanup:611mbedtls_ecp_group_free(&grp);612mbedtls_ecp_point_free(&G);613614return ret;615}616617/*618* Compute R = +/- X * S mod N, taking care not to leak S619*/620static int ecjpake_mul_secret(mbedtls_mpi *R, int sign,621const mbedtls_mpi *X,622const mbedtls_mpi *S,623const mbedtls_mpi *N,624int (*f_rng)(void *, unsigned char *, size_t),625void *p_rng)626{627int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;628mbedtls_mpi b; /* Blinding value, then s + N * blinding */629630mbedtls_mpi_init(&b);631632/* b = s + rnd-128-bit * N */633MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&b, 16, f_rng, p_rng));634MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&b, &b, N));635MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&b, &b, S));636637/* R = sign * X * b mod N */638MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(R, X, &b));639R->s *= sign;640MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(R, R, N));641642cleanup:643mbedtls_mpi_free(&b);644645return ret;646}647648/*649* Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6)650*/651int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,652unsigned char *buf, size_t len, size_t *olen,653int (*f_rng)(void *, unsigned char *, size_t),654void *p_rng)655{656int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;657mbedtls_ecp_point G; /* C: GA, S: GB */658mbedtls_ecp_point Xm; /* C: Xc, S: Xs */659mbedtls_mpi xm; /* C: xc, S: xs */660unsigned char *p = buf;661const unsigned char *end = buf + len;662size_t ec_len;663664mbedtls_ecp_point_init(&G);665mbedtls_ecp_point_init(&Xm);666mbedtls_mpi_init(&xm);667668/*669* First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1)670*671* Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA672* Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB673* Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G674*/675MBEDTLS_MPI_CHK(ecjpake_ecp_add3(&ctx->grp, &G,676&ctx->Xp1, &ctx->Xp2, &ctx->Xm1));677MBEDTLS_MPI_CHK(ecjpake_mul_secret(&xm, 1, &ctx->xm2, &ctx->s,678&ctx->grp.N, f_rng, p_rng));679MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &Xm, &xm, &G, f_rng, p_rng));680681/*682* Now write things out683*684* struct {685* ECParameters curve_params; // only server writing its message686* ECJPAKEKeyKP ecjpake_key_kp;687* } Client/ServerECJPAKEParams;688*/689if (ctx->role == MBEDTLS_ECJPAKE_SERVER) {690if (end < p) {691ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;692goto cleanup;693}694MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,695p, (size_t) (end - p)));696p += ec_len;697}698699if (end < p) {700ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;701goto cleanup;702}703MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,704ctx->point_format, &ec_len, p, (size_t) (end - p)));705p += ec_len;706707MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,708ctx->point_format,709&G, &xm, &Xm, ID_MINE,710&p, end, f_rng, p_rng));711712*olen = (size_t) (p - buf);713714cleanup:715mbedtls_ecp_point_free(&G);716mbedtls_ecp_point_free(&Xm);717mbedtls_mpi_free(&xm);718719return ret;720}721722/*723* Derive PMS (7.4.2.7 / 7.4.2.8)724*/725static int mbedtls_ecjpake_derive_k(mbedtls_ecjpake_context *ctx,726mbedtls_ecp_point *K,727int (*f_rng)(void *, unsigned char *, size_t),728void *p_rng)729{730int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;731mbedtls_mpi m_xm2_s, one;732733mbedtls_mpi_init(&m_xm2_s);734mbedtls_mpi_init(&one);735736MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1));737738/*739* Client: K = ( Xs - X4 * x2 * s ) * x2740* Server: K = ( Xc - X2 * x4 * s ) * x4741* Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2742*/743MBEDTLS_MPI_CHK(ecjpake_mul_secret(&m_xm2_s, -1, &ctx->xm2, &ctx->s,744&ctx->grp.N, f_rng, p_rng));745MBEDTLS_MPI_CHK(mbedtls_ecp_muladd(&ctx->grp, K,746&one, &ctx->Xp,747&m_xm2_s, &ctx->Xp2));748MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, K, &ctx->xm2, K,749f_rng, p_rng));750751cleanup:752mbedtls_mpi_free(&m_xm2_s);753mbedtls_mpi_free(&one);754755return ret;756}757758int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,759unsigned char *buf, size_t len, size_t *olen,760int (*f_rng)(void *, unsigned char *, size_t),761void *p_rng)762{763int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;764mbedtls_ecp_point K;765unsigned char kx[MBEDTLS_ECP_MAX_BYTES];766size_t x_bytes;767768*olen = mbedtls_md_get_size_from_type(ctx->md_type);769if (len < *olen) {770return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;771}772773mbedtls_ecp_point_init(&K);774775ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);776if (ret) {777goto cleanup;778}779780/* PMS = SHA-256( K.X ) */781x_bytes = (ctx->grp.pbits + 7) / 8;782MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K.X, kx, x_bytes));783MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(ctx->md_type,784kx, x_bytes, buf));785786cleanup:787mbedtls_ecp_point_free(&K);788789return ret;790}791792int mbedtls_ecjpake_write_shared_key(mbedtls_ecjpake_context *ctx,793unsigned char *buf, size_t len, size_t *olen,794int (*f_rng)(void *, unsigned char *, size_t),795void *p_rng)796{797int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;798mbedtls_ecp_point K;799800mbedtls_ecp_point_init(&K);801802ret = mbedtls_ecjpake_derive_k(ctx, &K, f_rng, p_rng);803if (ret) {804goto cleanup;805}806807ret = mbedtls_ecp_point_write_binary(&ctx->grp, &K, ctx->point_format,808olen, buf, len);809if (ret != 0) {810goto cleanup;811}812813cleanup:814mbedtls_ecp_point_free(&K);815816return ret;817}818819#undef ID_MINE820#undef ID_PEER821822#endif /* ! MBEDTLS_ECJPAKE_ALT */823824#if defined(MBEDTLS_SELF_TEST)825826#include "mbedtls/platform.h"827828#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \829!defined(MBEDTLS_MD_CAN_SHA256)830int mbedtls_ecjpake_self_test(int verbose)831{832(void) verbose;833return 0;834}835#else836837static const unsigned char ecjpake_test_password[] = {8380x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74,8390x65, 0x73, 0x74840};841842#if !defined(MBEDTLS_ECJPAKE_ALT)843844static const unsigned char ecjpake_test_x1[] = {8450x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,8460x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,8470x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21848};849850static const unsigned char ecjpake_test_x2[] = {8510x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,8520x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,8530x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81854};855856static const unsigned char ecjpake_test_x3[] = {8570x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,8580x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,8590x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81860};861862static const unsigned char ecjpake_test_x4[] = {8630xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc,8640xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,8650xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1866};867868static const unsigned char ecjpake_test_cli_one[] = {8690x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19,8700x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44,8710xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad,8720xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62,8730x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9,8740x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d,8750x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e,8760x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e,8770xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73,8780x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22,8790x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce,8800x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00,8810x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b,8820xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e,8830xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62,8840xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5,8850x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb,8860x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35,8870x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0,8880x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb,8890xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47,8900xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39,8910x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97,8920x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40,8930x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d,8940xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa,8950x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d,8960x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0897};898899static const unsigned char ecjpake_test_srv_one[] = {9000x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb,9010xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18,9020x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47,9030x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f,9040xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7,9050xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d,9060x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64,9070x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36,9080x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2,9090xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec,9100x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16,9110x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96,9120x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3,9130x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19,9140x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f,9150x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8,9160x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7,9170x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea,9180x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5,9190x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6,9200x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31,9210xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d,9220x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8,9230x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee,9240x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84,9250x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f,9260xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80,9270xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12928};929930static const unsigned char ecjpake_test_srv_two[] = {9310x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23,9320xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c,9330xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f,9340xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca,9350x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26,9360xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55,9370x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38,9380xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6,9390x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9,9400xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4,9410x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2,9420x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8,9430x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd,9440x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c945};946947static const unsigned char ecjpake_test_cli_two[] = {9480x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46,9490x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb,9500x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72,9510x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce,9520xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98,9530x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31,9540xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15,9550xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36,9560x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8,9570x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45,9580xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d,9590x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58,9600x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82,9610xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c962};963964static const unsigned char ecjpake_test_shared_key[] = {9650x04, 0x01, 0xab, 0xe9, 0xf2, 0xc7, 0x3a, 0x99, 0x14, 0xcb, 0x1f, 0x80,9660xfb, 0x9d, 0xdb, 0x7e, 0x00, 0x12, 0xa8, 0x9c, 0x2f, 0x39, 0x27, 0x79,9670xf9, 0x64, 0x40, 0x14, 0x75, 0xea, 0xc1, 0x31, 0x28, 0x43, 0x8f, 0xe1,9680x12, 0x41, 0xd6, 0xc1, 0xe5, 0x5f, 0x7b, 0x80, 0x88, 0x94, 0xc9, 0xc0,9690x27, 0xa3, 0x34, 0x41, 0xf5, 0xcb, 0xa1, 0xfe, 0x6c, 0xc7, 0xe6, 0x12,9700x17, 0xc3, 0xde, 0x27, 0xb4,971};972973static const unsigned char ecjpake_test_pms[] = {9740xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7,9750x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9,9760xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51977};978979/*980* PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!981*982* This is the linear congruential generator from numerical recipes,983* except we only use the low byte as the output. See984* https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use985*/986static int self_test_rng(void *ctx, unsigned char *out, size_t len)987{988static uint32_t state = 42;989990(void) ctx;991992for (size_t i = 0; i < len; i++) {993state = state * 1664525u + 1013904223u;994out[i] = (unsigned char) state;995}996997return 0;998}9991000/* Load my private keys and generate the corresponding public keys */1001static int ecjpake_test_load(mbedtls_ecjpake_context *ctx,1002const unsigned char *xm1, size_t len1,1003const unsigned char *xm2, size_t len2)1004{1005int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;10061007MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm1, xm1, len1));1008MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ctx->xm2, xm2, len2));1009MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm1, &ctx->xm1,1010&ctx->grp.G, self_test_rng, NULL));1011MBEDTLS_MPI_CHK(mbedtls_ecp_mul(&ctx->grp, &ctx->Xm2, &ctx->xm2,1012&ctx->grp.G, self_test_rng, NULL));10131014cleanup:1015return ret;1016}10171018#endif /* ! MBEDTLS_ECJPAKE_ALT */10191020/* For tests we don't need a secure RNG;1021* use the LGC from Numerical Recipes for simplicity */1022static int ecjpake_lgc(void *p, unsigned char *out, size_t len)1023{1024static uint32_t x = 42;1025(void) p;10261027while (len > 0) {1028size_t use_len = len > 4 ? 4 : len;1029x = 1664525 * x + 1013904223;1030memcpy(out, &x, use_len);1031out += use_len;1032len -= use_len;1033}10341035return 0;1036}10371038#define TEST_ASSERT(x) \1039do { \1040if (x) \1041ret = 0; \1042else \1043{ \1044ret = 1; \1045goto cleanup; \1046} \1047} while (0)10481049/*1050* Checkup routine1051*/1052int mbedtls_ecjpake_self_test(int verbose)1053{1054int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;1055mbedtls_ecjpake_context cli;1056mbedtls_ecjpake_context srv;1057unsigned char buf[512], pms[32];1058size_t len, pmslen;10591060mbedtls_ecjpake_init(&cli);1061mbedtls_ecjpake_init(&srv);10621063if (verbose != 0) {1064mbedtls_printf(" ECJPAKE test #0 (setup): ");1065}10661067TEST_ASSERT(mbedtls_ecjpake_setup(&cli, MBEDTLS_ECJPAKE_CLIENT,1068MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,1069ecjpake_test_password,1070sizeof(ecjpake_test_password)) == 0);10711072TEST_ASSERT(mbedtls_ecjpake_setup(&srv, MBEDTLS_ECJPAKE_SERVER,1073MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1,1074ecjpake_test_password,1075sizeof(ecjpake_test_password)) == 0);10761077if (verbose != 0) {1078mbedtls_printf("passed\n");1079}10801081if (verbose != 0) {1082mbedtls_printf(" ECJPAKE test #1 (random handshake): ");1083}10841085TEST_ASSERT(mbedtls_ecjpake_write_round_one(&cli,1086buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);10871088TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv, buf, len) == 0);10891090TEST_ASSERT(mbedtls_ecjpake_write_round_one(&srv,1091buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);10921093TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli, buf, len) == 0);10941095TEST_ASSERT(mbedtls_ecjpake_write_round_two(&srv,1096buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);10971098TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli, buf, len) == 0);10991100TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,1101pms, sizeof(pms), &pmslen, ecjpake_lgc, NULL) == 0);11021103TEST_ASSERT(mbedtls_ecjpake_write_round_two(&cli,1104buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11051106TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv, buf, len) == 0);11071108TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,1109buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11101111TEST_ASSERT(len == pmslen);1112TEST_ASSERT(memcmp(buf, pms, len) == 0);11131114if (verbose != 0) {1115mbedtls_printf("passed\n");1116}11171118#if !defined(MBEDTLS_ECJPAKE_ALT)1119/* 'reference handshake' tests can only be run against implementations1120* for which we have 100% control over how the random ephemeral keys1121* are generated. This is only the case for the internal Mbed TLS1122* implementation, so these tests are skipped in case the internal1123* implementation is swapped out for an alternative one. */1124if (verbose != 0) {1125mbedtls_printf(" ECJPAKE test #2 (reference handshake): ");1126}11271128/* Simulate generation of round one */1129MBEDTLS_MPI_CHK(ecjpake_test_load(&cli,1130ecjpake_test_x1, sizeof(ecjpake_test_x1),1131ecjpake_test_x2, sizeof(ecjpake_test_x2)));11321133MBEDTLS_MPI_CHK(ecjpake_test_load(&srv,1134ecjpake_test_x3, sizeof(ecjpake_test_x3),1135ecjpake_test_x4, sizeof(ecjpake_test_x4)));11361137/* Read round one */1138TEST_ASSERT(mbedtls_ecjpake_read_round_one(&srv,1139ecjpake_test_cli_one,1140sizeof(ecjpake_test_cli_one)) == 0);11411142TEST_ASSERT(mbedtls_ecjpake_read_round_one(&cli,1143ecjpake_test_srv_one,1144sizeof(ecjpake_test_srv_one)) == 0);11451146/* Skip generation of round two, read round two */1147TEST_ASSERT(mbedtls_ecjpake_read_round_two(&cli,1148ecjpake_test_srv_two,1149sizeof(ecjpake_test_srv_two)) == 0);11501151TEST_ASSERT(mbedtls_ecjpake_read_round_two(&srv,1152ecjpake_test_cli_two,1153sizeof(ecjpake_test_cli_two)) == 0);11541155/* Server derives PMS */1156TEST_ASSERT(mbedtls_ecjpake_derive_secret(&srv,1157buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11581159TEST_ASSERT(len == sizeof(ecjpake_test_pms));1160TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);11611162/* Server derives K as unsigned binary data */1163TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&srv,1164buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11651166TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));1167TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);11681169memset(buf, 0, len); /* Avoid interferences with next step */11701171/* Client derives PMS */1172TEST_ASSERT(mbedtls_ecjpake_derive_secret(&cli,1173buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11741175TEST_ASSERT(len == sizeof(ecjpake_test_pms));1176TEST_ASSERT(memcmp(buf, ecjpake_test_pms, len) == 0);11771178/* Client derives K as unsigned binary data */1179TEST_ASSERT(mbedtls_ecjpake_write_shared_key(&cli,1180buf, sizeof(buf), &len, ecjpake_lgc, NULL) == 0);11811182TEST_ASSERT(len == sizeof(ecjpake_test_shared_key));1183TEST_ASSERT(memcmp(buf, ecjpake_test_shared_key, len) == 0);11841185if (verbose != 0) {1186mbedtls_printf("passed\n");1187}1188#endif /* ! MBEDTLS_ECJPAKE_ALT */11891190cleanup:1191mbedtls_ecjpake_free(&cli);1192mbedtls_ecjpake_free(&srv);11931194if (ret != 0) {1195if (verbose != 0) {1196mbedtls_printf("failed\n");1197}11981199ret = 1;1200}12011202if (verbose != 0) {1203mbedtls_printf("\n");1204}12051206return ret;1207}12081209#undef TEST_ASSERT12101211#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */12121213#endif /* MBEDTLS_SELF_TEST */12141215#endif /* MBEDTLS_ECJPAKE_C */121612171218