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