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#include <assert.h>
8193645Ssimon
9193645Ssimon/*
10193645Ssimon * In the definition, (xa, xb, xc, xd) are Alice's (x1, x2, x3, x4) or
11193645Ssimon * Bob's (x3, x4, x1, x2). If you see what I mean.
12193645Ssimon */
13193645Ssimon
14296465Sdelphijtypedef struct {
15296465Sdelphij    char *name;                 /* Must be unique */
16193645Ssimon    char *peer_name;
17193645Ssimon    BIGNUM *p;
18193645Ssimon    BIGNUM *g;
19193645Ssimon    BIGNUM *q;
20296465Sdelphij    BIGNUM *gxc;                /* Alice's g^{x3} or Bob's g^{x1} */
21296465Sdelphij    BIGNUM *gxd;                /* Alice's g^{x4} or Bob's g^{x2} */
22296465Sdelphij} JPAKE_CTX_PUBLIC;
23193645Ssimon
24296465Sdelphijstruct JPAKE_CTX {
25193645Ssimon    JPAKE_CTX_PUBLIC p;
26296465Sdelphij    BIGNUM *secret;             /* The shared secret */
27193645Ssimon    BN_CTX *ctx;
28296465Sdelphij    BIGNUM *xa;                 /* Alice's x1 or Bob's x3 */
29296465Sdelphij    BIGNUM *xb;                 /* Alice's x2 or Bob's x4 */
30296465Sdelphij    BIGNUM *key;                /* The calculated (shared) key */
31296465Sdelphij};
32193645Ssimon
33193645Ssimonstatic void JPAKE_ZKP_init(JPAKE_ZKP *zkp)
34296465Sdelphij{
35193645Ssimon    zkp->gr = BN_new();
36193645Ssimon    zkp->b = BN_new();
37296465Sdelphij}
38193645Ssimon
39193645Ssimonstatic void JPAKE_ZKP_release(JPAKE_ZKP *zkp)
40296465Sdelphij{
41193645Ssimon    BN_free(zkp->b);
42193645Ssimon    BN_free(zkp->gr);
43296465Sdelphij}
44193645Ssimon
45193645Ssimon/* Two birds with one stone - make the global name as expected */
46296465Sdelphij#define JPAKE_STEP_PART_init    JPAKE_STEP2_init
47296465Sdelphij#define JPAKE_STEP_PART_release JPAKE_STEP2_release
48193645Ssimon
49193645Ssimonvoid JPAKE_STEP_PART_init(JPAKE_STEP_PART *p)
50296465Sdelphij{
51193645Ssimon    p->gx = BN_new();
52193645Ssimon    JPAKE_ZKP_init(&p->zkpx);
53296465Sdelphij}
54193645Ssimon
55193645Ssimonvoid JPAKE_STEP_PART_release(JPAKE_STEP_PART *p)
56296465Sdelphij{
57193645Ssimon    JPAKE_ZKP_release(&p->zkpx);
58193645Ssimon    BN_free(p->gx);
59296465Sdelphij}
60193645Ssimon
61193645Ssimonvoid JPAKE_STEP1_init(JPAKE_STEP1 *s1)
62296465Sdelphij{
63193645Ssimon    JPAKE_STEP_PART_init(&s1->p1);
64193645Ssimon    JPAKE_STEP_PART_init(&s1->p2);
65296465Sdelphij}
66193645Ssimon
67193645Ssimonvoid JPAKE_STEP1_release(JPAKE_STEP1 *s1)
68296465Sdelphij{
69193645Ssimon    JPAKE_STEP_PART_release(&s1->p2);
70193645Ssimon    JPAKE_STEP_PART_release(&s1->p1);
71296465Sdelphij}
72193645Ssimon
73193645Ssimonstatic void JPAKE_CTX_init(JPAKE_CTX *ctx, const char *name,
74296465Sdelphij                           const char *peer_name, const BIGNUM *p,
75296465Sdelphij                           const BIGNUM *g, const BIGNUM *q,
76296465Sdelphij                           const BIGNUM *secret)
77296465Sdelphij{
78193645Ssimon    ctx->p.name = OPENSSL_strdup(name);
79193645Ssimon    ctx->p.peer_name = OPENSSL_strdup(peer_name);
80193645Ssimon    ctx->p.p = BN_dup(p);
81193645Ssimon    ctx->p.g = BN_dup(g);
82193645Ssimon    ctx->p.q = BN_dup(q);
83193645Ssimon    ctx->secret = BN_dup(secret);
84193645Ssimon
85193645Ssimon    ctx->p.gxc = BN_new();
86193645Ssimon    ctx->p.gxd = BN_new();
87193645Ssimon
88193645Ssimon    ctx->xa = BN_new();
89193645Ssimon    ctx->xb = BN_new();
90193645Ssimon    ctx->key = BN_new();
91193645Ssimon    ctx->ctx = BN_CTX_new();
92296465Sdelphij}
93296465Sdelphij
94193645Ssimonstatic void JPAKE_CTX_release(JPAKE_CTX *ctx)
95296465Sdelphij{
96193645Ssimon    BN_CTX_free(ctx->ctx);
97193645Ssimon    BN_clear_free(ctx->key);
98193645Ssimon    BN_clear_free(ctx->xb);
99193645Ssimon    BN_clear_free(ctx->xa);
100193645Ssimon
101193645Ssimon    BN_free(ctx->p.gxd);
102193645Ssimon    BN_free(ctx->p.gxc);
103193645Ssimon
104193645Ssimon    BN_clear_free(ctx->secret);
105193645Ssimon    BN_free(ctx->p.q);
106193645Ssimon    BN_free(ctx->p.g);
107193645Ssimon    BN_free(ctx->p.p);
108193645Ssimon    OPENSSL_free(ctx->p.peer_name);
109193645Ssimon    OPENSSL_free(ctx->p.name);
110193645Ssimon
111193645Ssimon    memset(ctx, '\0', sizeof *ctx);
112296465Sdelphij}
113296465Sdelphij
114193645SsimonJPAKE_CTX *JPAKE_CTX_new(const char *name, const char *peer_name,
115296465Sdelphij                         const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
116296465Sdelphij                         const BIGNUM *secret)
117296465Sdelphij{
118193645Ssimon    JPAKE_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
119193645Ssimon
120193645Ssimon    JPAKE_CTX_init(ctx, name, peer_name, p, g, q, secret);
121193645Ssimon
122193645Ssimon    return ctx;
123296465Sdelphij}
124193645Ssimon
125193645Ssimonvoid JPAKE_CTX_free(JPAKE_CTX *ctx)
126296465Sdelphij{
127193645Ssimon    JPAKE_CTX_release(ctx);
128193645Ssimon    OPENSSL_free(ctx);
129296465Sdelphij}
130193645Ssimon
131193645Ssimonstatic void hashlength(SHA_CTX *sha, size_t l)
132296465Sdelphij{
133193645Ssimon    unsigned char b[2];
134193645Ssimon
135193645Ssimon    assert(l <= 0xffff);
136193645Ssimon    b[0] = l >> 8;
137296465Sdelphij    b[1] = l & 0xff;
138193645Ssimon    SHA1_Update(sha, b, 2);
139296465Sdelphij}
140193645Ssimon
141193645Ssimonstatic void hashstring(SHA_CTX *sha, const char *string)
142296465Sdelphij{
143193645Ssimon    size_t l = strlen(string);
144193645Ssimon
145193645Ssimon    hashlength(sha, l);
146193645Ssimon    SHA1_Update(sha, string, l);
147296465Sdelphij}
148193645Ssimon
149193645Ssimonstatic void hashbn(SHA_CTX *sha, const BIGNUM *bn)
150296465Sdelphij{
151193645Ssimon    size_t l = BN_num_bytes(bn);
152193645Ssimon    unsigned char *bin = OPENSSL_malloc(l);
153193645Ssimon
154193645Ssimon    hashlength(sha, l);
155193645Ssimon    BN_bn2bin(bn, bin);
156193645Ssimon    SHA1_Update(sha, bin, l);
157193645Ssimon    OPENSSL_free(bin);
158296465Sdelphij}
159193645Ssimon
160193645Ssimon/* h=hash(g, g^r, g^x, name) */
161193645Ssimonstatic void zkp_hash(BIGNUM *h, const BIGNUM *zkpg, const JPAKE_STEP_PART *p,
162296465Sdelphij                     const char *proof_name)
163296465Sdelphij{
164193645Ssimon    unsigned char md[SHA_DIGEST_LENGTH];
165193645Ssimon    SHA_CTX sha;
166193645Ssimon
167296465Sdelphij    /*
168296465Sdelphij     * XXX: hash should not allow moving of the boundaries - Java code
169296465Sdelphij     * is flawed in this respect. Length encoding seems simplest.
170296465Sdelphij     */
171193645Ssimon    SHA1_Init(&sha);
172193645Ssimon    hashbn(&sha, zkpg);
173193645Ssimon    assert(!BN_is_zero(p->zkpx.gr));
174193645Ssimon    hashbn(&sha, p->zkpx.gr);
175193645Ssimon    hashbn(&sha, p->gx);
176193645Ssimon    hashstring(&sha, proof_name);
177193645Ssimon    SHA1_Final(md, &sha);
178193645Ssimon    BN_bin2bn(md, SHA_DIGEST_LENGTH, h);
179296465Sdelphij}
180193645Ssimon
181193645Ssimon/*
182193645Ssimon * Prove knowledge of x
183193645Ssimon * Note that p->gx has already been calculated
184193645Ssimon */
185193645Ssimonstatic void generate_zkp(JPAKE_STEP_PART *p, const BIGNUM *x,
186296465Sdelphij                         const BIGNUM *zkpg, JPAKE_CTX *ctx)
187296465Sdelphij{
188193645Ssimon    BIGNUM *r = BN_new();
189193645Ssimon    BIGNUM *h = BN_new();
190193645Ssimon    BIGNUM *t = BN_new();
191193645Ssimon
192296465Sdelphij   /*-
193193645Ssimon    * r in [0,q)
194193645Ssimon    * XXX: Java chooses r in [0, 2^160) - i.e. distribution not uniform
195193645Ssimon    */
196193645Ssimon    BN_rand_range(r, ctx->p.q);
197296465Sdelphij    /* g^r */
198193645Ssimon    BN_mod_exp(p->zkpx.gr, zkpg, r, ctx->p.p, ctx->ctx);
199193645Ssimon
200296465Sdelphij    /* h=hash... */
201193645Ssimon    zkp_hash(h, zkpg, p, ctx->p.name);
202193645Ssimon
203296465Sdelphij    /* b = r - x*h */
204193645Ssimon    BN_mod_mul(t, x, h, ctx->p.q, ctx->ctx);
205193645Ssimon    BN_mod_sub(p->zkpx.b, r, t, ctx->p.q, ctx->ctx);
206193645Ssimon
207296465Sdelphij    /* cleanup */
208193645Ssimon    BN_free(t);
209193645Ssimon    BN_free(h);
210193645Ssimon    BN_free(r);
211296465Sdelphij}
212193645Ssimon
213193645Ssimonstatic int verify_zkp(const JPAKE_STEP_PART *p, const BIGNUM *zkpg,
214296465Sdelphij                      JPAKE_CTX *ctx)
215296465Sdelphij{
216193645Ssimon    BIGNUM *h = BN_new();
217193645Ssimon    BIGNUM *t1 = BN_new();
218193645Ssimon    BIGNUM *t2 = BN_new();
219193645Ssimon    BIGNUM *t3 = BN_new();
220193645Ssimon    int ret = 0;
221193645Ssimon
222193645Ssimon    zkp_hash(h, zkpg, p, ctx->p.peer_name);
223193645Ssimon
224296465Sdelphij    /* t1 = g^b */
225193645Ssimon    BN_mod_exp(t1, zkpg, p->zkpx.b, ctx->p.p, ctx->ctx);
226296465Sdelphij    /* t2 = (g^x)^h = g^{hx} */
227193645Ssimon    BN_mod_exp(t2, p->gx, h, ctx->p.p, ctx->ctx);
228296465Sdelphij    /* t3 = t1 * t2 = g^{hx} * g^b = g^{hx+b} = g^r (allegedly) */
229193645Ssimon    BN_mod_mul(t3, t1, t2, ctx->p.p, ctx->ctx);
230193645Ssimon
231296465Sdelphij    /* verify t3 == g^r */
232296465Sdelphij    if (BN_cmp(t3, p->zkpx.gr) == 0)
233296465Sdelphij        ret = 1;
234193645Ssimon    else
235296465Sdelphij        JPAKEerr(JPAKE_F_VERIFY_ZKP, JPAKE_R_ZKP_VERIFY_FAILED);
236193645Ssimon
237296465Sdelphij    /* cleanup */
238193645Ssimon    BN_free(t3);
239193645Ssimon    BN_free(t2);
240193645Ssimon    BN_free(t1);
241193645Ssimon    BN_free(h);
242193645Ssimon
243193645Ssimon    return ret;
244296465Sdelphij}
245193645Ssimon
246193645Ssimonstatic void generate_step_part(JPAKE_STEP_PART *p, const BIGNUM *x,
247296465Sdelphij                               const BIGNUM *g, JPAKE_CTX *ctx)
248296465Sdelphij{
249193645Ssimon    BN_mod_exp(p->gx, g, x, ctx->p.p, ctx->ctx);
250193645Ssimon    generate_zkp(p, x, g, ctx);
251296465Sdelphij}
252193645Ssimon
253193645Ssimon/* Generate each party's random numbers. xa is in [0, q), xb is in [1, q). */
254193645Ssimonstatic void genrand(JPAKE_CTX *ctx)
255296465Sdelphij{
256193645Ssimon    BIGNUM *qm1;
257193645Ssimon
258296465Sdelphij    /* xa in [0, q) */
259193645Ssimon    BN_rand_range(ctx->xa, ctx->p.q);
260193645Ssimon
261296465Sdelphij    /* q-1 */
262193645Ssimon    qm1 = BN_new();
263193645Ssimon    BN_copy(qm1, ctx->p.q);
264193645Ssimon    BN_sub_word(qm1, 1);
265193645Ssimon
266296465Sdelphij    /* ... and xb in [0, q-1) */
267193645Ssimon    BN_rand_range(ctx->xb, qm1);
268296465Sdelphij    /* [1, q) */
269193645Ssimon    BN_add_word(ctx->xb, 1);
270193645Ssimon
271296465Sdelphij    /* cleanup */
272193645Ssimon    BN_free(qm1);
273296465Sdelphij}
274193645Ssimon
275193645Ssimonint JPAKE_STEP1_generate(JPAKE_STEP1 *send, JPAKE_CTX *ctx)
276296465Sdelphij{
277193645Ssimon    genrand(ctx);
278193645Ssimon    generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx);
279193645Ssimon    generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx);
280193645Ssimon
281193645Ssimon    return 1;
282296465Sdelphij}
283193645Ssimon
284216166Ssimon/* g^x is a legal value */
285216166Ssimonstatic int is_legal(const BIGNUM *gx, const JPAKE_CTX *ctx)
286296465Sdelphij{
287216166Ssimon    BIGNUM *t;
288216166Ssimon    int res;
289216166Ssimon
290296465Sdelphij    if (BN_is_negative(gx) || BN_is_zero(gx) || BN_cmp(gx, ctx->p.p) >= 0)
291296465Sdelphij        return 0;
292296465Sdelphij
293216166Ssimon    t = BN_new();
294216166Ssimon    BN_mod_exp(t, gx, ctx->p.q, ctx->p.p, ctx->ctx);
295216166Ssimon    res = BN_is_one(t);
296216166Ssimon    BN_free(t);
297216166Ssimon
298216166Ssimon    return res;
299296465Sdelphij}
300216166Ssimon
301193645Ssimonint JPAKE_STEP1_process(JPAKE_CTX *ctx, const JPAKE_STEP1 *received)
302296465Sdelphij{
303296465Sdelphij    if (!is_legal(received->p1.gx, ctx)) {
304296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS,
305296465Sdelphij                 JPAKE_R_G_TO_THE_X3_IS_NOT_LEGAL);
306296465Sdelphij        return 0;
307296465Sdelphij    }
308216166Ssimon
309296465Sdelphij    if (!is_legal(received->p2.gx, ctx)) {
310296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS,
311296465Sdelphij                 JPAKE_R_G_TO_THE_X4_IS_NOT_LEGAL);
312296465Sdelphij        return 0;
313296465Sdelphij    }
314216166Ssimon
315216166Ssimon    /* verify their ZKP(xc) */
316296465Sdelphij    if (!verify_zkp(&received->p1, ctx->p.g, ctx)) {
317296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X3_FAILED);
318296465Sdelphij        return 0;
319296465Sdelphij    }
320193645Ssimon
321216166Ssimon    /* verify their ZKP(xd) */
322296465Sdelphij    if (!verify_zkp(&received->p2, ctx->p.g, ctx)) {
323296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X4_FAILED);
324296465Sdelphij        return 0;
325296465Sdelphij    }
326193645Ssimon
327216166Ssimon    /* g^xd != 1 */
328296465Sdelphij    if (BN_is_one(received->p2.gx)) {
329296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X4_IS_ONE);
330296465Sdelphij        return 0;
331296465Sdelphij    }
332193645Ssimon
333296465Sdelphij    /* Save the bits we need for later */
334193645Ssimon    BN_copy(ctx->p.gxc, received->p1.gx);
335193645Ssimon    BN_copy(ctx->p.gxd, received->p2.gx);
336193645Ssimon
337193645Ssimon    return 1;
338296465Sdelphij}
339193645Ssimon
340193645Ssimonint JPAKE_STEP2_generate(JPAKE_STEP2 *send, JPAKE_CTX *ctx)
341296465Sdelphij{
342193645Ssimon    BIGNUM *t1 = BN_new();
343193645Ssimon    BIGNUM *t2 = BN_new();
344193645Ssimon
345296465Sdelphij   /*-
346193645Ssimon    * X = g^{(xa + xc + xd) * xb * s}
347193645Ssimon    * t1 = g^xa
348193645Ssimon    */
349193645Ssimon    BN_mod_exp(t1, ctx->p.g, ctx->xa, ctx->p.p, ctx->ctx);
350296465Sdelphij    /* t2 = t1 * g^{xc} = g^{xa} * g^{xc} = g^{xa + xc} */
351193645Ssimon    BN_mod_mul(t2, t1, ctx->p.gxc, ctx->p.p, ctx->ctx);
352296465Sdelphij    /* t1 = t2 * g^{xd} = g^{xa + xc + xd} */
353193645Ssimon    BN_mod_mul(t1, t2, ctx->p.gxd, ctx->p.p, ctx->ctx);
354296465Sdelphij    /* t2 = xb * s */
355193645Ssimon    BN_mod_mul(t2, ctx->xb, ctx->secret, ctx->p.q, ctx->ctx);
356193645Ssimon
357296465Sdelphij   /*-
358193645Ssimon    * ZKP(xb * s)
359193645Ssimon    * XXX: this is kinda funky, because we're using
360193645Ssimon    *
361193645Ssimon    * g' = g^{xa + xc + xd}
362193645Ssimon    *
363193645Ssimon    * as the generator, which means X is g'^{xb * s}
364193645Ssimon    * X = t1^{t2} = t1^{xb * s} = g^{(xa + xc + xd) * xb * s}
365193645Ssimon    */
366193645Ssimon    generate_step_part(send, t2, t1, ctx);
367193645Ssimon
368296465Sdelphij    /* cleanup */
369193645Ssimon    BN_free(t1);
370193645Ssimon    BN_free(t2);
371193645Ssimon
372193645Ssimon    return 1;
373296465Sdelphij}
374193645Ssimon
375193645Ssimon/* gx = g^{xc + xa + xb} * xd * s */
376193645Ssimonstatic int compute_key(JPAKE_CTX *ctx, const BIGNUM *gx)
377296465Sdelphij{
378193645Ssimon    BIGNUM *t1 = BN_new();
379193645Ssimon    BIGNUM *t2 = BN_new();
380193645Ssimon    BIGNUM *t3 = BN_new();
381193645Ssimon
382296465Sdelphij   /*-
383193645Ssimon    * K = (gx/g^{xb * xd * s})^{xb}
384193645Ssimon    *   = (g^{(xc + xa + xb) * xd * s - xb * xd *s})^{xb}
385193645Ssimon    *   = (g^{(xa + xc) * xd * s})^{xb}
386193645Ssimon    *   = g^{(xa + xc) * xb * xd * s}
387193645Ssimon    * [which is the same regardless of who calculates it]
388193645Ssimon    */
389193645Ssimon
390296465Sdelphij    /* t1 = (g^{xd})^{xb} = g^{xb * xd} */
391193645Ssimon    BN_mod_exp(t1, ctx->p.gxd, ctx->xb, ctx->p.p, ctx->ctx);
392296465Sdelphij    /* t2 = -s = q-s */
393193645Ssimon    BN_sub(t2, ctx->p.q, ctx->secret);
394296465Sdelphij    /* t3 = t1^t2 = g^{-xb * xd * s} */
395193645Ssimon    BN_mod_exp(t3, t1, t2, ctx->p.p, ctx->ctx);
396296465Sdelphij    /* t1 = gx * t3 = X/g^{xb * xd * s} */
397193645Ssimon    BN_mod_mul(t1, gx, t3, ctx->p.p, ctx->ctx);
398296465Sdelphij    /* K = t1^{xb} */
399193645Ssimon    BN_mod_exp(ctx->key, t1, ctx->xb, ctx->p.p, ctx->ctx);
400193645Ssimon
401296465Sdelphij    /* cleanup */
402193645Ssimon    BN_free(t3);
403193645Ssimon    BN_free(t2);
404193645Ssimon    BN_free(t1);
405193645Ssimon
406193645Ssimon    return 1;
407296465Sdelphij}
408193645Ssimon
409193645Ssimonint JPAKE_STEP2_process(JPAKE_CTX *ctx, const JPAKE_STEP2 *received)
410296465Sdelphij{
411193645Ssimon    BIGNUM *t1 = BN_new();
412193645Ssimon    BIGNUM *t2 = BN_new();
413193645Ssimon    int ret = 0;
414193645Ssimon
415296465Sdelphij   /*-
416193645Ssimon    * g' = g^{xc + xa + xb} [from our POV]
417193645Ssimon    * t1 = xa + xb
418193645Ssimon    */
419193645Ssimon    BN_mod_add(t1, ctx->xa, ctx->xb, ctx->p.q, ctx->ctx);
420296465Sdelphij    /* t2 = g^{t1} = g^{xa+xb} */
421193645Ssimon    BN_mod_exp(t2, ctx->p.g, t1, ctx->p.p, ctx->ctx);
422296465Sdelphij    /* t1 = g^{xc} * t2 = g^{xc + xa + xb} */
423193645Ssimon    BN_mod_mul(t1, ctx->p.gxc, t2, ctx->p.p, ctx->ctx);
424193645Ssimon
425296465Sdelphij    if (verify_zkp(received, t1, ctx))
426296465Sdelphij        ret = 1;
427193645Ssimon    else
428296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP2_PROCESS, JPAKE_R_VERIFY_B_FAILED);
429193645Ssimon
430193645Ssimon    compute_key(ctx, received->gx);
431193645Ssimon
432296465Sdelphij    /* cleanup */
433193645Ssimon    BN_free(t2);
434193645Ssimon    BN_free(t1);
435193645Ssimon
436193645Ssimon    return ret;
437296465Sdelphij}
438193645Ssimon
439193645Ssimonstatic void quickhashbn(unsigned char *md, const BIGNUM *bn)
440296465Sdelphij{
441193645Ssimon    SHA_CTX sha;
442193645Ssimon
443193645Ssimon    SHA1_Init(&sha);
444193645Ssimon    hashbn(&sha, bn);
445193645Ssimon    SHA1_Final(md, &sha);
446296465Sdelphij}
447193645Ssimon
448193645Ssimonvoid JPAKE_STEP3A_init(JPAKE_STEP3A *s3a)
449296465Sdelphij{
450296465Sdelphij}
451193645Ssimon
452193645Ssimonint JPAKE_STEP3A_generate(JPAKE_STEP3A *send, JPAKE_CTX *ctx)
453296465Sdelphij{
454193645Ssimon    quickhashbn(send->hhk, ctx->key);
455193645Ssimon    SHA1(send->hhk, sizeof send->hhk, send->hhk);
456193645Ssimon
457193645Ssimon    return 1;
458296465Sdelphij}
459193645Ssimon
460193645Ssimonint JPAKE_STEP3A_process(JPAKE_CTX *ctx, const JPAKE_STEP3A *received)
461296465Sdelphij{
462193645Ssimon    unsigned char hhk[SHA_DIGEST_LENGTH];
463193645Ssimon
464193645Ssimon    quickhashbn(hhk, ctx->key);
465193645Ssimon    SHA1(hhk, sizeof hhk, hhk);
466296465Sdelphij    if (memcmp(hhk, received->hhk, sizeof hhk)) {
467296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP3A_PROCESS,
468296465Sdelphij                 JPAKE_R_HASH_OF_HASH_OF_KEY_MISMATCH);
469296465Sdelphij        return 0;
470296465Sdelphij    }
471193645Ssimon    return 1;
472296465Sdelphij}
473193645Ssimon
474193645Ssimonvoid JPAKE_STEP3A_release(JPAKE_STEP3A *s3a)
475296465Sdelphij{
476296465Sdelphij}
477193645Ssimon
478193645Ssimonvoid JPAKE_STEP3B_init(JPAKE_STEP3B *s3b)
479296465Sdelphij{
480296465Sdelphij}
481193645Ssimon
482193645Ssimonint JPAKE_STEP3B_generate(JPAKE_STEP3B *send, JPAKE_CTX *ctx)
483296465Sdelphij{
484193645Ssimon    quickhashbn(send->hk, ctx->key);
485193645Ssimon
486193645Ssimon    return 1;
487296465Sdelphij}
488193645Ssimon
489193645Ssimonint JPAKE_STEP3B_process(JPAKE_CTX *ctx, const JPAKE_STEP3B *received)
490296465Sdelphij{
491193645Ssimon    unsigned char hk[SHA_DIGEST_LENGTH];
492193645Ssimon
493193645Ssimon    quickhashbn(hk, ctx->key);
494296465Sdelphij    if (memcmp(hk, received->hk, sizeof hk)) {
495296465Sdelphij        JPAKEerr(JPAKE_F_JPAKE_STEP3B_PROCESS, JPAKE_R_HASH_OF_KEY_MISMATCH);
496296465Sdelphij        return 0;
497296465Sdelphij    }
498193645Ssimon    return 1;
499296465Sdelphij}
500193645Ssimon
501193645Ssimonvoid JPAKE_STEP3B_release(JPAKE_STEP3B *s3b)
502296465Sdelphij{
503296465Sdelphij}
504193645Ssimon
505193645Ssimonconst BIGNUM *JPAKE_get_shared_key(JPAKE_CTX *ctx)
506296465Sdelphij{
507193645Ssimon    return ctx->key;
508296465Sdelphij}
509