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
13296341Sdelphijtypedef struct {
14296341Sdelphij    char *name;                 /* Must be unique */
15193645Ssimon    char *peer_name;
16193645Ssimon    BIGNUM *p;
17193645Ssimon    BIGNUM *g;
18193645Ssimon    BIGNUM *q;
19296341Sdelphij    BIGNUM *gxc;                /* Alice's g^{x3} or Bob's g^{x1} */
20296341Sdelphij    BIGNUM *gxd;                /* Alice's g^{x4} or Bob's g^{x2} */
21296341Sdelphij} JPAKE_CTX_PUBLIC;
22193645Ssimon
23296341Sdelphijstruct JPAKE_CTX {
24193645Ssimon    JPAKE_CTX_PUBLIC p;
25296341Sdelphij    BIGNUM *secret;             /* The shared secret */
26193645Ssimon    BN_CTX *ctx;
27296341Sdelphij    BIGNUM *xa;                 /* Alice's x1 or Bob's x3 */
28296341Sdelphij    BIGNUM *xb;                 /* Alice's x2 or Bob's x4 */
29296341Sdelphij    BIGNUM *key;                /* The calculated (shared) key */
30296341Sdelphij};
31193645Ssimon
32193645Ssimonstatic void JPAKE_ZKP_init(JPAKE_ZKP *zkp)
33296341Sdelphij{
34193645Ssimon    zkp->gr = BN_new();
35193645Ssimon    zkp->b = BN_new();
36296341Sdelphij}
37193645Ssimon
38193645Ssimonstatic void JPAKE_ZKP_release(JPAKE_ZKP *zkp)
39296341Sdelphij{
40193645Ssimon    BN_free(zkp->b);
41193645Ssimon    BN_free(zkp->gr);
42296341Sdelphij}
43193645Ssimon
44193645Ssimon/* Two birds with one stone - make the global name as expected */
45296341Sdelphij#define JPAKE_STEP_PART_init    JPAKE_STEP2_init
46296341Sdelphij#define JPAKE_STEP_PART_release JPAKE_STEP2_release
47193645Ssimon
48193645Ssimonvoid JPAKE_STEP_PART_init(JPAKE_STEP_PART *p)
49296341Sdelphij{
50193645Ssimon    p->gx = BN_new();
51193645Ssimon    JPAKE_ZKP_init(&p->zkpx);
52296341Sdelphij}
53193645Ssimon
54193645Ssimonvoid JPAKE_STEP_PART_release(JPAKE_STEP_PART *p)
55296341Sdelphij{
56193645Ssimon    JPAKE_ZKP_release(&p->zkpx);
57193645Ssimon    BN_free(p->gx);
58296341Sdelphij}
59193645Ssimon
60193645Ssimonvoid JPAKE_STEP1_init(JPAKE_STEP1 *s1)
61296341Sdelphij{
62193645Ssimon    JPAKE_STEP_PART_init(&s1->p1);
63193645Ssimon    JPAKE_STEP_PART_init(&s1->p2);
64296341Sdelphij}
65193645Ssimon
66193645Ssimonvoid JPAKE_STEP1_release(JPAKE_STEP1 *s1)
67296341Sdelphij{
68193645Ssimon    JPAKE_STEP_PART_release(&s1->p2);
69193645Ssimon    JPAKE_STEP_PART_release(&s1->p1);
70296341Sdelphij}
71193645Ssimon
72193645Ssimonstatic void JPAKE_CTX_init(JPAKE_CTX *ctx, const char *name,
73296341Sdelphij                           const char *peer_name, const BIGNUM *p,
74296341Sdelphij                           const BIGNUM *g, const BIGNUM *q,
75296341Sdelphij                           const BIGNUM *secret)
76296341Sdelphij{
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();
91296341Sdelphij}
92296341Sdelphij
93193645Ssimonstatic void JPAKE_CTX_release(JPAKE_CTX *ctx)
94296341Sdelphij{
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);
111296341Sdelphij}
112296341Sdelphij
113193645SsimonJPAKE_CTX *JPAKE_CTX_new(const char *name, const char *peer_name,
114296341Sdelphij                         const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
115296341Sdelphij                         const BIGNUM *secret)
116296341Sdelphij{
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;
122296341Sdelphij}
123193645Ssimon
124193645Ssimonvoid JPAKE_CTX_free(JPAKE_CTX *ctx)
125296341Sdelphij{
126193645Ssimon    JPAKE_CTX_release(ctx);
127193645Ssimon    OPENSSL_free(ctx);
128296341Sdelphij}
129193645Ssimon
130193645Ssimonstatic void hashlength(SHA_CTX *sha, size_t l)
131296341Sdelphij{
132193645Ssimon    unsigned char b[2];
133193645Ssimon
134238405Sjkim    OPENSSL_assert(l <= 0xffff);
135193645Ssimon    b[0] = l >> 8;
136296341Sdelphij    b[1] = l & 0xff;
137193645Ssimon    SHA1_Update(sha, b, 2);
138296341Sdelphij}
139193645Ssimon
140193645Ssimonstatic void hashstring(SHA_CTX *sha, const char *string)
141296341Sdelphij{
142193645Ssimon    size_t l = strlen(string);
143193645Ssimon
144193645Ssimon    hashlength(sha, l);
145193645Ssimon    SHA1_Update(sha, string, l);
146296341Sdelphij}
147193645Ssimon
148193645Ssimonstatic void hashbn(SHA_CTX *sha, const BIGNUM *bn)
149296341Sdelphij{
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);
157296341Sdelphij}
158193645Ssimon
159193645Ssimon/* h=hash(g, g^r, g^x, name) */
160193645Ssimonstatic void zkp_hash(BIGNUM *h, const BIGNUM *zkpg, const JPAKE_STEP_PART *p,
161296341Sdelphij                     const char *proof_name)
162296341Sdelphij{
163193645Ssimon    unsigned char md[SHA_DIGEST_LENGTH];
164193645Ssimon    SHA_CTX sha;
165193645Ssimon
166296341Sdelphij    /*
167296341Sdelphij     * XXX: hash should not allow moving of the boundaries - Java code
168296341Sdelphij     * is flawed in this respect. Length encoding seems simplest.
169296341Sdelphij     */
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);
178296341Sdelphij}
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,
185296341Sdelphij                         const BIGNUM *zkpg, JPAKE_CTX *ctx)
186296341Sdelphij{
187193645Ssimon    BIGNUM *r = BN_new();
188193645Ssimon    BIGNUM *h = BN_new();
189193645Ssimon    BIGNUM *t = BN_new();
190193645Ssimon
191296341Sdelphij   /*-
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);
196296341Sdelphij    /* g^r */
197193645Ssimon    BN_mod_exp(p->zkpx.gr, zkpg, r, ctx->p.p, ctx->ctx);
198193645Ssimon
199296341Sdelphij    /* h=hash... */
200193645Ssimon    zkp_hash(h, zkpg, p, ctx->p.name);
201193645Ssimon
202296341Sdelphij    /* 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
206296341Sdelphij    /* cleanup */
207193645Ssimon    BN_free(t);
208193645Ssimon    BN_free(h);
209193645Ssimon    BN_free(r);
210296341Sdelphij}
211193645Ssimon
212193645Ssimonstatic int verify_zkp(const JPAKE_STEP_PART *p, const BIGNUM *zkpg,
213296341Sdelphij                      JPAKE_CTX *ctx)
214296341Sdelphij{
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
221193645Ssimon    zkp_hash(h, zkpg, p, ctx->p.peer_name);
222193645Ssimon
223296341Sdelphij    /* t1 = g^b */
224193645Ssimon    BN_mod_exp(t1, zkpg, p->zkpx.b, ctx->p.p, ctx->ctx);
225296341Sdelphij    /* t2 = (g^x)^h = g^{hx} */
226193645Ssimon    BN_mod_exp(t2, p->gx, h, ctx->p.p, ctx->ctx);
227296341Sdelphij    /* t3 = t1 * t2 = g^{hx} * g^b = g^{hx+b} = g^r (allegedly) */
228193645Ssimon    BN_mod_mul(t3, t1, t2, ctx->p.p, ctx->ctx);
229193645Ssimon
230296341Sdelphij    /* verify t3 == g^r */
231296341Sdelphij    if (BN_cmp(t3, p->zkpx.gr) == 0)
232296341Sdelphij        ret = 1;
233193645Ssimon    else
234296341Sdelphij        JPAKEerr(JPAKE_F_VERIFY_ZKP, JPAKE_R_ZKP_VERIFY_FAILED);
235193645Ssimon
236296341Sdelphij    /* cleanup */
237193645Ssimon    BN_free(t3);
238193645Ssimon    BN_free(t2);
239193645Ssimon    BN_free(t1);
240193645Ssimon    BN_free(h);
241193645Ssimon
242193645Ssimon    return ret;
243296341Sdelphij}
244193645Ssimon
245193645Ssimonstatic void generate_step_part(JPAKE_STEP_PART *p, const BIGNUM *x,
246296341Sdelphij                               const BIGNUM *g, JPAKE_CTX *ctx)
247296341Sdelphij{
248193645Ssimon    BN_mod_exp(p->gx, g, x, ctx->p.p, ctx->ctx);
249193645Ssimon    generate_zkp(p, x, g, ctx);
250296341Sdelphij}
251193645Ssimon
252193645Ssimon/* Generate each party's random numbers. xa is in [0, q), xb is in [1, q). */
253193645Ssimonstatic void genrand(JPAKE_CTX *ctx)
254296341Sdelphij{
255193645Ssimon    BIGNUM *qm1;
256193645Ssimon
257296341Sdelphij    /* xa in [0, q) */
258193645Ssimon    BN_rand_range(ctx->xa, ctx->p.q);
259193645Ssimon
260296341Sdelphij    /* q-1 */
261193645Ssimon    qm1 = BN_new();
262193645Ssimon    BN_copy(qm1, ctx->p.q);
263193645Ssimon    BN_sub_word(qm1, 1);
264193645Ssimon
265296341Sdelphij    /* ... and xb in [0, q-1) */
266193645Ssimon    BN_rand_range(ctx->xb, qm1);
267296341Sdelphij    /* [1, q) */
268193645Ssimon    BN_add_word(ctx->xb, 1);
269193645Ssimon
270296341Sdelphij    /* cleanup */
271193645Ssimon    BN_free(qm1);
272296341Sdelphij}
273193645Ssimon
274193645Ssimonint JPAKE_STEP1_generate(JPAKE_STEP1 *send, JPAKE_CTX *ctx)
275296341Sdelphij{
276193645Ssimon    genrand(ctx);
277193645Ssimon    generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx);
278193645Ssimon    generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx);
279193645Ssimon
280193645Ssimon    return 1;
281296341Sdelphij}
282193645Ssimon
283216166Ssimon/* g^x is a legal value */
284216166Ssimonstatic int is_legal(const BIGNUM *gx, const JPAKE_CTX *ctx)
285296341Sdelphij{
286216166Ssimon    BIGNUM *t;
287216166Ssimon    int res;
288216166Ssimon
289296341Sdelphij    if (BN_is_negative(gx) || BN_is_zero(gx) || BN_cmp(gx, ctx->p.p) >= 0)
290296341Sdelphij        return 0;
291296341Sdelphij
292216166Ssimon    t = BN_new();
293216166Ssimon    BN_mod_exp(t, gx, ctx->p.q, ctx->p.p, ctx->ctx);
294216166Ssimon    res = BN_is_one(t);
295216166Ssimon    BN_free(t);
296216166Ssimon
297216166Ssimon    return res;
298296341Sdelphij}
299216166Ssimon
300193645Ssimonint JPAKE_STEP1_process(JPAKE_CTX *ctx, const JPAKE_STEP1 *received)
301296341Sdelphij{
302296341Sdelphij    if (!is_legal(received->p1.gx, ctx)) {
303296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS,
304296341Sdelphij                 JPAKE_R_G_TO_THE_X3_IS_NOT_LEGAL);
305296341Sdelphij        return 0;
306296341Sdelphij    }
307216166Ssimon
308296341Sdelphij    if (!is_legal(received->p2.gx, ctx)) {
309296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS,
310296341Sdelphij                 JPAKE_R_G_TO_THE_X4_IS_NOT_LEGAL);
311296341Sdelphij        return 0;
312296341Sdelphij    }
313216166Ssimon
314296341Sdelphij    /* verify their ZKP(xc) */
315296341Sdelphij    if (!verify_zkp(&received->p1, ctx->p.g, ctx)) {
316296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X3_FAILED);
317296341Sdelphij        return 0;
318296341Sdelphij    }
319193645Ssimon
320296341Sdelphij    /* verify their ZKP(xd) */
321296341Sdelphij    if (!verify_zkp(&received->p2, ctx->p.g, ctx)) {
322296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X4_FAILED);
323296341Sdelphij        return 0;
324296341Sdelphij    }
325193645Ssimon
326296341Sdelphij    /* g^xd != 1 */
327296341Sdelphij    if (BN_is_one(received->p2.gx)) {
328296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X4_IS_ONE);
329296341Sdelphij        return 0;
330296341Sdelphij    }
331193645Ssimon
332296341Sdelphij    /* Save the bits we need for later */
333193645Ssimon    BN_copy(ctx->p.gxc, received->p1.gx);
334193645Ssimon    BN_copy(ctx->p.gxd, received->p2.gx);
335193645Ssimon
336193645Ssimon    return 1;
337296341Sdelphij}
338193645Ssimon
339193645Ssimonint JPAKE_STEP2_generate(JPAKE_STEP2 *send, JPAKE_CTX *ctx)
340296341Sdelphij{
341193645Ssimon    BIGNUM *t1 = BN_new();
342193645Ssimon    BIGNUM *t2 = BN_new();
343193645Ssimon
344296341Sdelphij   /*-
345193645Ssimon    * X = g^{(xa + xc + xd) * xb * s}
346193645Ssimon    * t1 = g^xa
347193645Ssimon    */
348193645Ssimon    BN_mod_exp(t1, ctx->p.g, ctx->xa, ctx->p.p, ctx->ctx);
349296341Sdelphij    /* t2 = t1 * g^{xc} = g^{xa} * g^{xc} = g^{xa + xc} */
350193645Ssimon    BN_mod_mul(t2, t1, ctx->p.gxc, ctx->p.p, ctx->ctx);
351296341Sdelphij    /* t1 = t2 * g^{xd} = g^{xa + xc + xd} */
352193645Ssimon    BN_mod_mul(t1, t2, ctx->p.gxd, ctx->p.p, ctx->ctx);
353296341Sdelphij    /* t2 = xb * s */
354193645Ssimon    BN_mod_mul(t2, ctx->xb, ctx->secret, ctx->p.q, ctx->ctx);
355193645Ssimon
356296341Sdelphij   /*-
357193645Ssimon    * ZKP(xb * s)
358193645Ssimon    * XXX: this is kinda funky, because we're using
359193645Ssimon    *
360193645Ssimon    * g' = g^{xa + xc + xd}
361193645Ssimon    *
362193645Ssimon    * as the generator, which means X is g'^{xb * s}
363193645Ssimon    * X = t1^{t2} = t1^{xb * s} = g^{(xa + xc + xd) * xb * s}
364193645Ssimon    */
365193645Ssimon    generate_step_part(send, t2, t1, ctx);
366193645Ssimon
367296341Sdelphij    /* cleanup */
368193645Ssimon    BN_free(t1);
369193645Ssimon    BN_free(t2);
370193645Ssimon
371193645Ssimon    return 1;
372296341Sdelphij}
373193645Ssimon
374193645Ssimon/* gx = g^{xc + xa + xb} * xd * s */
375193645Ssimonstatic int compute_key(JPAKE_CTX *ctx, const BIGNUM *gx)
376296341Sdelphij{
377193645Ssimon    BIGNUM *t1 = BN_new();
378193645Ssimon    BIGNUM *t2 = BN_new();
379193645Ssimon    BIGNUM *t3 = BN_new();
380193645Ssimon
381296341Sdelphij   /*-
382193645Ssimon    * K = (gx/g^{xb * xd * s})^{xb}
383193645Ssimon    *   = (g^{(xc + xa + xb) * xd * s - xb * xd *s})^{xb}
384193645Ssimon    *   = (g^{(xa + xc) * xd * s})^{xb}
385193645Ssimon    *   = g^{(xa + xc) * xb * xd * s}
386193645Ssimon    * [which is the same regardless of who calculates it]
387193645Ssimon    */
388193645Ssimon
389296341Sdelphij    /* t1 = (g^{xd})^{xb} = g^{xb * xd} */
390193645Ssimon    BN_mod_exp(t1, ctx->p.gxd, ctx->xb, ctx->p.p, ctx->ctx);
391296341Sdelphij    /* t2 = -s = q-s */
392193645Ssimon    BN_sub(t2, ctx->p.q, ctx->secret);
393296341Sdelphij    /* t3 = t1^t2 = g^{-xb * xd * s} */
394193645Ssimon    BN_mod_exp(t3, t1, t2, ctx->p.p, ctx->ctx);
395296341Sdelphij    /* t1 = gx * t3 = X/g^{xb * xd * s} */
396193645Ssimon    BN_mod_mul(t1, gx, t3, ctx->p.p, ctx->ctx);
397296341Sdelphij    /* K = t1^{xb} */
398193645Ssimon    BN_mod_exp(ctx->key, t1, ctx->xb, ctx->p.p, ctx->ctx);
399193645Ssimon
400296341Sdelphij    /* cleanup */
401193645Ssimon    BN_free(t3);
402193645Ssimon    BN_free(t2);
403193645Ssimon    BN_free(t1);
404193645Ssimon
405193645Ssimon    return 1;
406296341Sdelphij}
407193645Ssimon
408193645Ssimonint JPAKE_STEP2_process(JPAKE_CTX *ctx, const JPAKE_STEP2 *received)
409296341Sdelphij{
410193645Ssimon    BIGNUM *t1 = BN_new();
411193645Ssimon    BIGNUM *t2 = BN_new();
412193645Ssimon    int ret = 0;
413193645Ssimon
414296341Sdelphij   /*-
415193645Ssimon    * g' = g^{xc + xa + xb} [from our POV]
416193645Ssimon    * t1 = xa + xb
417193645Ssimon    */
418193645Ssimon    BN_mod_add(t1, ctx->xa, ctx->xb, ctx->p.q, ctx->ctx);
419296341Sdelphij    /* t2 = g^{t1} = g^{xa+xb} */
420193645Ssimon    BN_mod_exp(t2, ctx->p.g, t1, ctx->p.p, ctx->ctx);
421296341Sdelphij    /* t1 = g^{xc} * t2 = g^{xc + xa + xb} */
422193645Ssimon    BN_mod_mul(t1, ctx->p.gxc, t2, ctx->p.p, ctx->ctx);
423193645Ssimon
424296341Sdelphij    if (verify_zkp(received, t1, ctx))
425296341Sdelphij        ret = 1;
426193645Ssimon    else
427296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP2_PROCESS, JPAKE_R_VERIFY_B_FAILED);
428193645Ssimon
429193645Ssimon    compute_key(ctx, received->gx);
430193645Ssimon
431296341Sdelphij    /* cleanup */
432193645Ssimon    BN_free(t2);
433193645Ssimon    BN_free(t1);
434193645Ssimon
435193645Ssimon    return ret;
436296341Sdelphij}
437193645Ssimon
438193645Ssimonstatic void quickhashbn(unsigned char *md, const BIGNUM *bn)
439296341Sdelphij{
440193645Ssimon    SHA_CTX sha;
441193645Ssimon
442193645Ssimon    SHA1_Init(&sha);
443193645Ssimon    hashbn(&sha, bn);
444193645Ssimon    SHA1_Final(md, &sha);
445296341Sdelphij}
446193645Ssimon
447193645Ssimonvoid JPAKE_STEP3A_init(JPAKE_STEP3A *s3a)
448296341Sdelphij{
449296341Sdelphij}
450193645Ssimon
451193645Ssimonint JPAKE_STEP3A_generate(JPAKE_STEP3A *send, JPAKE_CTX *ctx)
452296341Sdelphij{
453193645Ssimon    quickhashbn(send->hhk, ctx->key);
454193645Ssimon    SHA1(send->hhk, sizeof send->hhk, send->hhk);
455193645Ssimon
456193645Ssimon    return 1;
457296341Sdelphij}
458193645Ssimon
459193645Ssimonint JPAKE_STEP3A_process(JPAKE_CTX *ctx, const JPAKE_STEP3A *received)
460296341Sdelphij{
461193645Ssimon    unsigned char hhk[SHA_DIGEST_LENGTH];
462193645Ssimon
463193645Ssimon    quickhashbn(hhk, ctx->key);
464193645Ssimon    SHA1(hhk, sizeof hhk, hhk);
465296341Sdelphij    if (memcmp(hhk, received->hhk, sizeof hhk)) {
466296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP3A_PROCESS,
467296341Sdelphij                 JPAKE_R_HASH_OF_HASH_OF_KEY_MISMATCH);
468296341Sdelphij        return 0;
469296341Sdelphij    }
470193645Ssimon    return 1;
471296341Sdelphij}
472193645Ssimon
473193645Ssimonvoid JPAKE_STEP3A_release(JPAKE_STEP3A *s3a)
474296341Sdelphij{
475296341Sdelphij}
476193645Ssimon
477193645Ssimonvoid JPAKE_STEP3B_init(JPAKE_STEP3B *s3b)
478296341Sdelphij{
479296341Sdelphij}
480193645Ssimon
481193645Ssimonint JPAKE_STEP3B_generate(JPAKE_STEP3B *send, JPAKE_CTX *ctx)
482296341Sdelphij{
483193645Ssimon    quickhashbn(send->hk, ctx->key);
484193645Ssimon
485193645Ssimon    return 1;
486296341Sdelphij}
487193645Ssimon
488193645Ssimonint JPAKE_STEP3B_process(JPAKE_CTX *ctx, const JPAKE_STEP3B *received)
489296341Sdelphij{
490193645Ssimon    unsigned char hk[SHA_DIGEST_LENGTH];
491193645Ssimon
492193645Ssimon    quickhashbn(hk, ctx->key);
493296341Sdelphij    if (memcmp(hk, received->hk, sizeof hk)) {
494296341Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP3B_PROCESS, JPAKE_R_HASH_OF_KEY_MISMATCH);
495296341Sdelphij        return 0;
496296341Sdelphij    }
497193645Ssimon    return 1;
498296341Sdelphij}
499193645Ssimon
500193645Ssimonvoid JPAKE_STEP3B_release(JPAKE_STEP3B *s3b)
501296341Sdelphij{
502296341Sdelphij}
503193645Ssimon
504193645Ssimonconst BIGNUM *JPAKE_get_shared_key(JPAKE_CTX *ctx)
505296341Sdelphij{
506193645Ssimon    return ctx->key;
507296341Sdelphij}
508