1193645Ssimon#include "jpake.h" 2193645Ssimon 3193645Ssimon#include <openssl/crypto.h> 4193645Ssimon#include <openssl/sha.h> 5193645Ssimon#include <openssl/err.h> 6193645Ssimon#include <memory.h> 7193645Ssimon 8193645Ssimon/* 9193645Ssimon * In the definition, (xa, xb, xc, xd) are Alice's (x1, x2, x3, x4) or 10193645Ssimon * Bob's (x3, x4, x1, x2). If you see what I mean. 11193645Ssimon */ 12193645Ssimon 13280304Sjkimtypedef struct { 14280304Sjkim char *name; /* Must be unique */ 15193645Ssimon char *peer_name; 16193645Ssimon BIGNUM *p; 17193645Ssimon BIGNUM *g; 18193645Ssimon BIGNUM *q; 19280304Sjkim BIGNUM *gxc; /* Alice's g^{x3} or Bob's g^{x1} */ 20280304Sjkim BIGNUM *gxd; /* Alice's g^{x4} or Bob's g^{x2} */ 21280304Sjkim} JPAKE_CTX_PUBLIC; 22193645Ssimon 23280304Sjkimstruct JPAKE_CTX { 24193645Ssimon JPAKE_CTX_PUBLIC p; 25280304Sjkim BIGNUM *secret; /* The shared secret */ 26193645Ssimon BN_CTX *ctx; 27280304Sjkim BIGNUM *xa; /* Alice's x1 or Bob's x3 */ 28280304Sjkim BIGNUM *xb; /* Alice's x2 or Bob's x4 */ 29280304Sjkim BIGNUM *key; /* The calculated (shared) key */ 30280304Sjkim}; 31193645Ssimon 32193645Ssimonstatic void JPAKE_ZKP_init(JPAKE_ZKP *zkp) 33280304Sjkim{ 34193645Ssimon zkp->gr = BN_new(); 35193645Ssimon zkp->b = BN_new(); 36280304Sjkim} 37193645Ssimon 38193645Ssimonstatic void JPAKE_ZKP_release(JPAKE_ZKP *zkp) 39280304Sjkim{ 40193645Ssimon BN_free(zkp->b); 41193645Ssimon BN_free(zkp->gr); 42280304Sjkim} 43193645Ssimon 44193645Ssimon/* Two birds with one stone - make the global name as expected */ 45280304Sjkim#define JPAKE_STEP_PART_init JPAKE_STEP2_init 46280304Sjkim#define JPAKE_STEP_PART_release JPAKE_STEP2_release 47193645Ssimon 48193645Ssimonvoid JPAKE_STEP_PART_init(JPAKE_STEP_PART *p) 49280304Sjkim{ 50193645Ssimon p->gx = BN_new(); 51193645Ssimon JPAKE_ZKP_init(&p->zkpx); 52280304Sjkim} 53193645Ssimon 54193645Ssimonvoid JPAKE_STEP_PART_release(JPAKE_STEP_PART *p) 55280304Sjkim{ 56193645Ssimon JPAKE_ZKP_release(&p->zkpx); 57193645Ssimon BN_free(p->gx); 58280304Sjkim} 59193645Ssimon 60193645Ssimonvoid JPAKE_STEP1_init(JPAKE_STEP1 *s1) 61280304Sjkim{ 62193645Ssimon JPAKE_STEP_PART_init(&s1->p1); 63193645Ssimon JPAKE_STEP_PART_init(&s1->p2); 64280304Sjkim} 65193645Ssimon 66193645Ssimonvoid JPAKE_STEP1_release(JPAKE_STEP1 *s1) 67280304Sjkim{ 68193645Ssimon JPAKE_STEP_PART_release(&s1->p2); 69193645Ssimon JPAKE_STEP_PART_release(&s1->p1); 70280304Sjkim} 71193645Ssimon 72193645Ssimonstatic void JPAKE_CTX_init(JPAKE_CTX *ctx, const char *name, 73280304Sjkim const char *peer_name, const BIGNUM *p, 74280304Sjkim const BIGNUM *g, const BIGNUM *q, 75280304Sjkim const BIGNUM *secret) 76280304Sjkim{ 77193645Ssimon ctx->p.name = OPENSSL_strdup(name); 78193645Ssimon ctx->p.peer_name = OPENSSL_strdup(peer_name); 79193645Ssimon ctx->p.p = BN_dup(p); 80193645Ssimon ctx->p.g = BN_dup(g); 81193645Ssimon ctx->p.q = BN_dup(q); 82193645Ssimon ctx->secret = BN_dup(secret); 83193645Ssimon 84193645Ssimon ctx->p.gxc = BN_new(); 85193645Ssimon ctx->p.gxd = BN_new(); 86193645Ssimon 87193645Ssimon ctx->xa = BN_new(); 88193645Ssimon ctx->xb = BN_new(); 89193645Ssimon ctx->key = BN_new(); 90193645Ssimon ctx->ctx = BN_CTX_new(); 91280304Sjkim} 92280304Sjkim 93193645Ssimonstatic void JPAKE_CTX_release(JPAKE_CTX *ctx) 94280304Sjkim{ 95193645Ssimon BN_CTX_free(ctx->ctx); 96193645Ssimon BN_clear_free(ctx->key); 97193645Ssimon BN_clear_free(ctx->xb); 98193645Ssimon BN_clear_free(ctx->xa); 99193645Ssimon 100193645Ssimon BN_free(ctx->p.gxd); 101193645Ssimon BN_free(ctx->p.gxc); 102193645Ssimon 103193645Ssimon BN_clear_free(ctx->secret); 104193645Ssimon BN_free(ctx->p.q); 105193645Ssimon BN_free(ctx->p.g); 106193645Ssimon BN_free(ctx->p.p); 107193645Ssimon OPENSSL_free(ctx->p.peer_name); 108193645Ssimon OPENSSL_free(ctx->p.name); 109193645Ssimon 110193645Ssimon memset(ctx, '\0', sizeof *ctx); 111280304Sjkim} 112280304Sjkim 113193645SsimonJPAKE_CTX *JPAKE_CTX_new(const char *name, const char *peer_name, 114280304Sjkim const BIGNUM *p, const BIGNUM *g, const BIGNUM *q, 115280304Sjkim const BIGNUM *secret) 116280304Sjkim{ 117193645Ssimon JPAKE_CTX *ctx = OPENSSL_malloc(sizeof *ctx); 118193645Ssimon 119193645Ssimon JPAKE_CTX_init(ctx, name, peer_name, p, g, q, secret); 120193645Ssimon 121193645Ssimon return ctx; 122280304Sjkim} 123193645Ssimon 124193645Ssimonvoid JPAKE_CTX_free(JPAKE_CTX *ctx) 125280304Sjkim{ 126193645Ssimon JPAKE_CTX_release(ctx); 127193645Ssimon OPENSSL_free(ctx); 128280304Sjkim} 129193645Ssimon 130193645Ssimonstatic void hashlength(SHA_CTX *sha, size_t l) 131280304Sjkim{ 132193645Ssimon unsigned char b[2]; 133193645Ssimon 134238405Sjkim OPENSSL_assert(l <= 0xffff); 135193645Ssimon b[0] = l >> 8; 136280304Sjkim b[1] = l & 0xff; 137193645Ssimon SHA1_Update(sha, b, 2); 138280304Sjkim} 139193645Ssimon 140193645Ssimonstatic void hashstring(SHA_CTX *sha, const char *string) 141280304Sjkim{ 142193645Ssimon size_t l = strlen(string); 143193645Ssimon 144193645Ssimon hashlength(sha, l); 145193645Ssimon SHA1_Update(sha, string, l); 146280304Sjkim} 147193645Ssimon 148193645Ssimonstatic void hashbn(SHA_CTX *sha, const BIGNUM *bn) 149280304Sjkim{ 150193645Ssimon size_t l = BN_num_bytes(bn); 151193645Ssimon unsigned char *bin = OPENSSL_malloc(l); 152193645Ssimon 153193645Ssimon hashlength(sha, l); 154193645Ssimon BN_bn2bin(bn, bin); 155193645Ssimon SHA1_Update(sha, bin, l); 156193645Ssimon OPENSSL_free(bin); 157280304Sjkim} 158193645Ssimon 159193645Ssimon/* h=hash(g, g^r, g^x, name) */ 160193645Ssimonstatic void zkp_hash(BIGNUM *h, const BIGNUM *zkpg, const JPAKE_STEP_PART *p, 161280304Sjkim const char *proof_name) 162280304Sjkim{ 163193645Ssimon unsigned char md[SHA_DIGEST_LENGTH]; 164193645Ssimon SHA_CTX sha; 165193645Ssimon 166280304Sjkim /* 167280304Sjkim * XXX: hash should not allow moving of the boundaries - Java code 168280304Sjkim * is flawed in this respect. Length encoding seems simplest. 169280304Sjkim */ 170193645Ssimon SHA1_Init(&sha); 171193645Ssimon hashbn(&sha, zkpg); 172238405Sjkim OPENSSL_assert(!BN_is_zero(p->zkpx.gr)); 173193645Ssimon hashbn(&sha, p->zkpx.gr); 174193645Ssimon hashbn(&sha, p->gx); 175193645Ssimon hashstring(&sha, proof_name); 176193645Ssimon SHA1_Final(md, &sha); 177193645Ssimon BN_bin2bn(md, SHA_DIGEST_LENGTH, h); 178280304Sjkim} 179193645Ssimon 180193645Ssimon/* 181193645Ssimon * Prove knowledge of x 182193645Ssimon * Note that p->gx has already been calculated 183193645Ssimon */ 184193645Ssimonstatic void generate_zkp(JPAKE_STEP_PART *p, const BIGNUM *x, 185280304Sjkim const BIGNUM *zkpg, JPAKE_CTX *ctx) 186280304Sjkim{ 187193645Ssimon BIGNUM *r = BN_new(); 188193645Ssimon BIGNUM *h = BN_new(); 189193645Ssimon BIGNUM *t = BN_new(); 190193645Ssimon 191280304Sjkim /*- 192193645Ssimon * r in [0,q) 193193645Ssimon * XXX: Java chooses r in [0, 2^160) - i.e. distribution not uniform 194193645Ssimon */ 195193645Ssimon BN_rand_range(r, ctx->p.q); 196280304Sjkim /* g^r */ 197193645Ssimon BN_mod_exp(p->zkpx.gr, zkpg, r, ctx->p.p, ctx->ctx); 198193645Ssimon 199280304Sjkim /* h=hash... */ 200193645Ssimon zkp_hash(h, zkpg, p, ctx->p.name); 201193645Ssimon 202280304Sjkim /* b = r - x*h */ 203193645Ssimon BN_mod_mul(t, x, h, ctx->p.q, ctx->ctx); 204193645Ssimon BN_mod_sub(p->zkpx.b, r, t, ctx->p.q, ctx->ctx); 205193645Ssimon 206280304Sjkim /* cleanup */ 207193645Ssimon BN_free(t); 208193645Ssimon BN_free(h); 209193645Ssimon BN_free(r); 210280304Sjkim} 211193645Ssimon 212193645Ssimonstatic int verify_zkp(const JPAKE_STEP_PART *p, const BIGNUM *zkpg, 213280304Sjkim JPAKE_CTX *ctx) 214280304Sjkim{ 215193645Ssimon BIGNUM *h = BN_new(); 216193645Ssimon BIGNUM *t1 = BN_new(); 217193645Ssimon BIGNUM *t2 = BN_new(); 218193645Ssimon BIGNUM *t3 = BN_new(); 219193645Ssimon int ret = 0; 220193645Ssimon 221291721Sjkim if (h == NULL || t1 == NULL || t2 == NULL || t3 == NULL) 222291721Sjkim goto end; 223291721Sjkim 224193645Ssimon zkp_hash(h, zkpg, p, ctx->p.peer_name); 225193645Ssimon 226280304Sjkim /* t1 = g^b */ 227193645Ssimon BN_mod_exp(t1, zkpg, p->zkpx.b, ctx->p.p, ctx->ctx); 228280304Sjkim /* t2 = (g^x)^h = g^{hx} */ 229193645Ssimon BN_mod_exp(t2, p->gx, h, ctx->p.p, ctx->ctx); 230280304Sjkim /* t3 = t1 * t2 = g^{hx} * g^b = g^{hx+b} = g^r (allegedly) */ 231193645Ssimon BN_mod_mul(t3, t1, t2, ctx->p.p, ctx->ctx); 232193645Ssimon 233280304Sjkim /* verify t3 == g^r */ 234280304Sjkim if (BN_cmp(t3, p->zkpx.gr) == 0) 235280304Sjkim ret = 1; 236193645Ssimon else 237280304Sjkim JPAKEerr(JPAKE_F_VERIFY_ZKP, JPAKE_R_ZKP_VERIFY_FAILED); 238193645Ssimon 239291721Sjkimend: 240280304Sjkim /* cleanup */ 241193645Ssimon BN_free(t3); 242193645Ssimon BN_free(t2); 243193645Ssimon BN_free(t1); 244193645Ssimon BN_free(h); 245193645Ssimon 246193645Ssimon return ret; 247280304Sjkim} 248193645Ssimon 249193645Ssimonstatic void generate_step_part(JPAKE_STEP_PART *p, const BIGNUM *x, 250280304Sjkim const BIGNUM *g, JPAKE_CTX *ctx) 251280304Sjkim{ 252193645Ssimon BN_mod_exp(p->gx, g, x, ctx->p.p, ctx->ctx); 253193645Ssimon generate_zkp(p, x, g, ctx); 254280304Sjkim} 255193645Ssimon 256193645Ssimon/* Generate each party's random numbers. xa is in [0, q), xb is in [1, q). */ 257193645Ssimonstatic void genrand(JPAKE_CTX *ctx) 258280304Sjkim{ 259193645Ssimon BIGNUM *qm1; 260193645Ssimon 261280304Sjkim /* xa in [0, q) */ 262193645Ssimon BN_rand_range(ctx->xa, ctx->p.q); 263193645Ssimon 264280304Sjkim /* q-1 */ 265193645Ssimon qm1 = BN_new(); 266193645Ssimon BN_copy(qm1, ctx->p.q); 267193645Ssimon BN_sub_word(qm1, 1); 268193645Ssimon 269280304Sjkim /* ... and xb in [0, q-1) */ 270193645Ssimon BN_rand_range(ctx->xb, qm1); 271280304Sjkim /* [1, q) */ 272193645Ssimon BN_add_word(ctx->xb, 1); 273193645Ssimon 274280304Sjkim /* cleanup */ 275193645Ssimon BN_free(qm1); 276280304Sjkim} 277193645Ssimon 278193645Ssimonint JPAKE_STEP1_generate(JPAKE_STEP1 *send, JPAKE_CTX *ctx) 279280304Sjkim{ 280193645Ssimon genrand(ctx); 281193645Ssimon generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx); 282193645Ssimon generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx); 283193645Ssimon 284193645Ssimon return 1; 285280304Sjkim} 286193645Ssimon 287216166Ssimon/* g^x is a legal value */ 288216166Ssimonstatic int is_legal(const BIGNUM *gx, const JPAKE_CTX *ctx) 289280304Sjkim{ 290216166Ssimon BIGNUM *t; 291216166Ssimon int res; 292216166Ssimon 293280304Sjkim if (BN_is_negative(gx) || BN_is_zero(gx) || BN_cmp(gx, ctx->p.p) >= 0) 294280304Sjkim return 0; 295280304Sjkim 296216166Ssimon t = BN_new(); 297216166Ssimon BN_mod_exp(t, gx, ctx->p.q, ctx->p.p, ctx->ctx); 298216166Ssimon res = BN_is_one(t); 299216166Ssimon BN_free(t); 300216166Ssimon 301216166Ssimon return res; 302280304Sjkim} 303216166Ssimon 304193645Ssimonint JPAKE_STEP1_process(JPAKE_CTX *ctx, const JPAKE_STEP1 *received) 305280304Sjkim{ 306280304Sjkim if (!is_legal(received->p1.gx, ctx)) { 307280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, 308280304Sjkim JPAKE_R_G_TO_THE_X3_IS_NOT_LEGAL); 309280304Sjkim return 0; 310280304Sjkim } 311216166Ssimon 312280304Sjkim if (!is_legal(received->p2.gx, ctx)) { 313280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, 314280304Sjkim JPAKE_R_G_TO_THE_X4_IS_NOT_LEGAL); 315280304Sjkim return 0; 316280304Sjkim } 317216166Ssimon 318280304Sjkim /* verify their ZKP(xc) */ 319280304Sjkim if (!verify_zkp(&received->p1, ctx->p.g, ctx)) { 320280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X3_FAILED); 321280304Sjkim return 0; 322280304Sjkim } 323193645Ssimon 324280304Sjkim /* verify their ZKP(xd) */ 325280304Sjkim if (!verify_zkp(&received->p2, ctx->p.g, ctx)) { 326280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X4_FAILED); 327280304Sjkim return 0; 328280304Sjkim } 329193645Ssimon 330280304Sjkim /* g^xd != 1 */ 331280304Sjkim if (BN_is_one(received->p2.gx)) { 332280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X4_IS_ONE); 333280304Sjkim return 0; 334280304Sjkim } 335193645Ssimon 336280304Sjkim /* Save the bits we need for later */ 337193645Ssimon BN_copy(ctx->p.gxc, received->p1.gx); 338193645Ssimon BN_copy(ctx->p.gxd, received->p2.gx); 339193645Ssimon 340193645Ssimon return 1; 341280304Sjkim} 342193645Ssimon 343193645Ssimonint JPAKE_STEP2_generate(JPAKE_STEP2 *send, JPAKE_CTX *ctx) 344280304Sjkim{ 345193645Ssimon BIGNUM *t1 = BN_new(); 346193645Ssimon BIGNUM *t2 = BN_new(); 347193645Ssimon 348280304Sjkim /*- 349193645Ssimon * X = g^{(xa + xc + xd) * xb * s} 350193645Ssimon * t1 = g^xa 351193645Ssimon */ 352193645Ssimon BN_mod_exp(t1, ctx->p.g, ctx->xa, ctx->p.p, ctx->ctx); 353280304Sjkim /* t2 = t1 * g^{xc} = g^{xa} * g^{xc} = g^{xa + xc} */ 354193645Ssimon BN_mod_mul(t2, t1, ctx->p.gxc, ctx->p.p, ctx->ctx); 355280304Sjkim /* t1 = t2 * g^{xd} = g^{xa + xc + xd} */ 356193645Ssimon BN_mod_mul(t1, t2, ctx->p.gxd, ctx->p.p, ctx->ctx); 357280304Sjkim /* t2 = xb * s */ 358193645Ssimon BN_mod_mul(t2, ctx->xb, ctx->secret, ctx->p.q, ctx->ctx); 359193645Ssimon 360280304Sjkim /*- 361193645Ssimon * ZKP(xb * s) 362193645Ssimon * XXX: this is kinda funky, because we're using 363193645Ssimon * 364193645Ssimon * g' = g^{xa + xc + xd} 365193645Ssimon * 366193645Ssimon * as the generator, which means X is g'^{xb * s} 367193645Ssimon * X = t1^{t2} = t1^{xb * s} = g^{(xa + xc + xd) * xb * s} 368193645Ssimon */ 369193645Ssimon generate_step_part(send, t2, t1, ctx); 370193645Ssimon 371280304Sjkim /* cleanup */ 372193645Ssimon BN_free(t1); 373193645Ssimon BN_free(t2); 374193645Ssimon 375193645Ssimon return 1; 376280304Sjkim} 377193645Ssimon 378193645Ssimon/* gx = g^{xc + xa + xb} * xd * s */ 379193645Ssimonstatic int compute_key(JPAKE_CTX *ctx, const BIGNUM *gx) 380280304Sjkim{ 381193645Ssimon BIGNUM *t1 = BN_new(); 382193645Ssimon BIGNUM *t2 = BN_new(); 383193645Ssimon BIGNUM *t3 = BN_new(); 384193645Ssimon 385280304Sjkim /*- 386193645Ssimon * K = (gx/g^{xb * xd * s})^{xb} 387193645Ssimon * = (g^{(xc + xa + xb) * xd * s - xb * xd *s})^{xb} 388193645Ssimon * = (g^{(xa + xc) * xd * s})^{xb} 389193645Ssimon * = g^{(xa + xc) * xb * xd * s} 390193645Ssimon * [which is the same regardless of who calculates it] 391193645Ssimon */ 392193645Ssimon 393280304Sjkim /* t1 = (g^{xd})^{xb} = g^{xb * xd} */ 394193645Ssimon BN_mod_exp(t1, ctx->p.gxd, ctx->xb, ctx->p.p, ctx->ctx); 395280304Sjkim /* t2 = -s = q-s */ 396193645Ssimon BN_sub(t2, ctx->p.q, ctx->secret); 397280304Sjkim /* t3 = t1^t2 = g^{-xb * xd * s} */ 398193645Ssimon BN_mod_exp(t3, t1, t2, ctx->p.p, ctx->ctx); 399280304Sjkim /* t1 = gx * t3 = X/g^{xb * xd * s} */ 400193645Ssimon BN_mod_mul(t1, gx, t3, ctx->p.p, ctx->ctx); 401280304Sjkim /* K = t1^{xb} */ 402193645Ssimon BN_mod_exp(ctx->key, t1, ctx->xb, ctx->p.p, ctx->ctx); 403193645Ssimon 404280304Sjkim /* cleanup */ 405193645Ssimon BN_free(t3); 406193645Ssimon BN_free(t2); 407193645Ssimon BN_free(t1); 408193645Ssimon 409193645Ssimon return 1; 410280304Sjkim} 411193645Ssimon 412193645Ssimonint JPAKE_STEP2_process(JPAKE_CTX *ctx, const JPAKE_STEP2 *received) 413280304Sjkim{ 414193645Ssimon BIGNUM *t1 = BN_new(); 415193645Ssimon BIGNUM *t2 = BN_new(); 416193645Ssimon int ret = 0; 417193645Ssimon 418280304Sjkim /*- 419193645Ssimon * g' = g^{xc + xa + xb} [from our POV] 420193645Ssimon * t1 = xa + xb 421193645Ssimon */ 422193645Ssimon BN_mod_add(t1, ctx->xa, ctx->xb, ctx->p.q, ctx->ctx); 423280304Sjkim /* t2 = g^{t1} = g^{xa+xb} */ 424193645Ssimon BN_mod_exp(t2, ctx->p.g, t1, ctx->p.p, ctx->ctx); 425280304Sjkim /* t1 = g^{xc} * t2 = g^{xc + xa + xb} */ 426193645Ssimon BN_mod_mul(t1, ctx->p.gxc, t2, ctx->p.p, ctx->ctx); 427193645Ssimon 428280304Sjkim if (verify_zkp(received, t1, ctx)) 429280304Sjkim ret = 1; 430193645Ssimon else 431280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP2_PROCESS, JPAKE_R_VERIFY_B_FAILED); 432193645Ssimon 433193645Ssimon compute_key(ctx, received->gx); 434193645Ssimon 435280304Sjkim /* cleanup */ 436193645Ssimon BN_free(t2); 437193645Ssimon BN_free(t1); 438193645Ssimon 439193645Ssimon return ret; 440280304Sjkim} 441193645Ssimon 442193645Ssimonstatic void quickhashbn(unsigned char *md, const BIGNUM *bn) 443280304Sjkim{ 444193645Ssimon SHA_CTX sha; 445193645Ssimon 446193645Ssimon SHA1_Init(&sha); 447193645Ssimon hashbn(&sha, bn); 448193645Ssimon SHA1_Final(md, &sha); 449280304Sjkim} 450193645Ssimon 451193645Ssimonvoid JPAKE_STEP3A_init(JPAKE_STEP3A *s3a) 452280304Sjkim{ 453280304Sjkim} 454193645Ssimon 455193645Ssimonint JPAKE_STEP3A_generate(JPAKE_STEP3A *send, JPAKE_CTX *ctx) 456280304Sjkim{ 457193645Ssimon quickhashbn(send->hhk, ctx->key); 458193645Ssimon SHA1(send->hhk, sizeof send->hhk, send->hhk); 459193645Ssimon 460193645Ssimon return 1; 461280304Sjkim} 462193645Ssimon 463193645Ssimonint JPAKE_STEP3A_process(JPAKE_CTX *ctx, const JPAKE_STEP3A *received) 464280304Sjkim{ 465193645Ssimon unsigned char hhk[SHA_DIGEST_LENGTH]; 466193645Ssimon 467193645Ssimon quickhashbn(hhk, ctx->key); 468193645Ssimon SHA1(hhk, sizeof hhk, hhk); 469280304Sjkim if (memcmp(hhk, received->hhk, sizeof hhk)) { 470280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP3A_PROCESS, 471280304Sjkim JPAKE_R_HASH_OF_HASH_OF_KEY_MISMATCH); 472280304Sjkim return 0; 473280304Sjkim } 474193645Ssimon return 1; 475280304Sjkim} 476193645Ssimon 477193645Ssimonvoid JPAKE_STEP3A_release(JPAKE_STEP3A *s3a) 478280304Sjkim{ 479280304Sjkim} 480193645Ssimon 481193645Ssimonvoid JPAKE_STEP3B_init(JPAKE_STEP3B *s3b) 482280304Sjkim{ 483280304Sjkim} 484193645Ssimon 485193645Ssimonint JPAKE_STEP3B_generate(JPAKE_STEP3B *send, JPAKE_CTX *ctx) 486280304Sjkim{ 487193645Ssimon quickhashbn(send->hk, ctx->key); 488193645Ssimon 489193645Ssimon return 1; 490280304Sjkim} 491193645Ssimon 492193645Ssimonint JPAKE_STEP3B_process(JPAKE_CTX *ctx, const JPAKE_STEP3B *received) 493280304Sjkim{ 494193645Ssimon unsigned char hk[SHA_DIGEST_LENGTH]; 495193645Ssimon 496193645Ssimon quickhashbn(hk, ctx->key); 497280304Sjkim if (memcmp(hk, received->hk, sizeof hk)) { 498280304Sjkim JPAKEerr(JPAKE_F_JPAKE_STEP3B_PROCESS, JPAKE_R_HASH_OF_KEY_MISMATCH); 499280304Sjkim return 0; 500280304Sjkim } 501193645Ssimon return 1; 502280304Sjkim} 503193645Ssimon 504193645Ssimonvoid JPAKE_STEP3B_release(JPAKE_STEP3B *s3b) 505280304Sjkim{ 506280304Sjkim} 507193645Ssimon 508193645Ssimonconst BIGNUM *JPAKE_get_shared_key(JPAKE_CTX *ctx) 509280304Sjkim{ 510193645Ssimon return ctx->key; 511280304Sjkim} 512