1e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include "jpake.h"
2e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
3e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include <openssl/crypto.h>
4e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include <openssl/sha.h>
5e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include <openssl/err.h>
6e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#include <memory.h>
7e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
8e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/*
9e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu * In the definition, (xa, xb, xc, xd) are Alice's (x1, x2, x3, x4) or
10e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu * Bob's (x3, x4, x1, x2). If you see what I mean.
11e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu */
12e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
13e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugutypedef struct
14e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
15e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    char *name;  /* Must be unique */
16e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    char *peer_name;
17e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *p;
18e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *g;
19e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *q;
20e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *gxc; /* Alice's g^{x3} or Bob's g^{x1} */
21e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *gxd; /* Alice's g^{x4} or Bob's g^{x2} */
22e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    } JPAKE_CTX_PUBLIC;
23e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
24e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustruct JPAKE_CTX
25e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
26e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_CTX_PUBLIC p;
27e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *secret;   /* The shared secret */
28e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_CTX *ctx;
29e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *xa;       /* Alice's x1 or Bob's x3 */
30e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *xb;       /* Alice's x2 or Bob's x4 */
31e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *key;      /* The calculated (shared) key */
32e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    };
33e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
34e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void JPAKE_ZKP_init(JPAKE_ZKP *zkp)
35e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
36e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    zkp->gr = BN_new();
37e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    zkp->b = BN_new();
38e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
39e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
40e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void JPAKE_ZKP_release(JPAKE_ZKP *zkp)
41e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
42e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(zkp->b);
43e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(zkp->gr);
44e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
45e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
46e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/* Two birds with one stone - make the global name as expected */
47e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#define JPAKE_STEP_PART_init	JPAKE_STEP2_init
48e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu#define JPAKE_STEP_PART_release	JPAKE_STEP2_release
49e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
50e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP_PART_init(JPAKE_STEP_PART *p)
51e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
52e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    p->gx = BN_new();
53e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_ZKP_init(&p->zkpx);
54e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
55e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
56e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP_PART_release(JPAKE_STEP_PART *p)
57e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
58e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_ZKP_release(&p->zkpx);
59e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(p->gx);
60e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
61e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
62e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP1_init(JPAKE_STEP1 *s1)
63e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
64e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_STEP_PART_init(&s1->p1);
65e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_STEP_PART_init(&s1->p2);
66e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
67e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
68e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP1_release(JPAKE_STEP1 *s1)
69e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
70e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_STEP_PART_release(&s1->p2);
71e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_STEP_PART_release(&s1->p1);
72e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
73e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
74e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void JPAKE_CTX_init(JPAKE_CTX *ctx, const char *name,
75e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			   const char *peer_name, const BIGNUM *p,
76e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			   const BIGNUM *g, const BIGNUM *q,
77e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			   const BIGNUM *secret)
78e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
79e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.name = OPENSSL_strdup(name);
80e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.peer_name = OPENSSL_strdup(peer_name);
81e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.p = BN_dup(p);
82e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.g = BN_dup(g);
83e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.q = BN_dup(q);
84e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->secret = BN_dup(secret);
85e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
86e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.gxc = BN_new();
87e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->p.gxd = BN_new();
88e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
89e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->xa = BN_new();
90e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->xb = BN_new();
91e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->key = BN_new();
92e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    ctx->ctx = BN_CTX_new();
93e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
94e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
95e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void JPAKE_CTX_release(JPAKE_CTX *ctx)
96e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
97e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_CTX_free(ctx->ctx);
98e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_clear_free(ctx->key);
99e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_clear_free(ctx->xb);
100e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_clear_free(ctx->xa);
101e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
102e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(ctx->p.gxd);
103e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(ctx->p.gxc);
104e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
105e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_clear_free(ctx->secret);
106e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(ctx->p.q);
107e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(ctx->p.g);
108e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(ctx->p.p);
109e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_free(ctx->p.peer_name);
110e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_free(ctx->p.name);
111e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
112e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    memset(ctx, '\0', sizeof *ctx);
113e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
114e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
115e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra ModaduguJPAKE_CTX *JPAKE_CTX_new(const char *name, const char *peer_name,
116e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			 const BIGNUM *p, const BIGNUM *g, const BIGNUM *q,
117e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			 const BIGNUM *secret)
118e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
119e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_CTX *ctx = OPENSSL_malloc(sizeof *ctx);
120e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
121e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_CTX_init(ctx, name, peer_name, p, g, q, secret);
122e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
123e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return ctx;
124e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
125e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
126e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_CTX_free(JPAKE_CTX *ctx)
127e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
128e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    JPAKE_CTX_release(ctx);
129e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_free(ctx);
130e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
131e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
132e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void hashlength(SHA_CTX *sha, size_t l)
133e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
134e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    unsigned char b[2];
135e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    OPENSSL_assert(l <= 0xffff);
137e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    b[0] = l >> 8;
138e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    b[1] = l&0xff;
139e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Update(sha, b, 2);
140e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
141e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
142e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void hashstring(SHA_CTX *sha, const char *string)
143e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
144e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    size_t l = strlen(string);
145e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
146e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashlength(sha, l);
147e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Update(sha, string, l);
148e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
149e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
150e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void hashbn(SHA_CTX *sha, const BIGNUM *bn)
151e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
152e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    size_t l = BN_num_bytes(bn);
153e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    unsigned char *bin = OPENSSL_malloc(l);
154e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
155e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashlength(sha, l);
156e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_bn2bin(bn, bin);
157e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Update(sha, bin, l);
158e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    OPENSSL_free(bin);
159e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
160e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
161e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/* h=hash(g, g^r, g^x, name) */
162e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void zkp_hash(BIGNUM *h, const BIGNUM *zkpg, const JPAKE_STEP_PART *p,
163e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		     const char *proof_name)
164e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
165e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    unsigned char md[SHA_DIGEST_LENGTH];
166e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA_CTX sha;
167e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
168e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
169e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * XXX: hash should not allow moving of the boundaries - Java code
170e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * is flawed in this respect. Length encoding seems simplest.
171e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
172e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Init(&sha);
173e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashbn(&sha, zkpg);
174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom    OPENSSL_assert(!BN_is_zero(p->zkpx.gr));
175e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashbn(&sha, p->zkpx.gr);
176e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashbn(&sha, p->gx);
177e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashstring(&sha, proof_name);
178e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Final(md, &sha);
179e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_bin2bn(md, SHA_DIGEST_LENGTH, h);
180e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
181e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
182e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/*
183e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu * Prove knowledge of x
184e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu * Note that p->gx has already been calculated
185e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu */
186e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void generate_zkp(JPAKE_STEP_PART *p, const BIGNUM *x,
187e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			 const BIGNUM *zkpg, JPAKE_CTX *ctx)
188e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
189e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *r = BN_new();
190e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *h = BN_new();
191e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t = BN_new();
192e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
193e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
194e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * r in [0,q)
195e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * XXX: Java chooses r in [0, 2^160) - i.e. distribution not uniform
196e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
197e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_rand_range(r, ctx->p.q);
198e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* g^r */
199e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(p->zkpx.gr, zkpg, r, ctx->p.p, ctx->ctx);
200e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
201e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* h=hash... */
202e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    zkp_hash(h, zkpg, p, ctx->p.name);
203e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
204e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* b = r - x*h */
205e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t, x, h, ctx->p.q, ctx->ctx);
206e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_sub(p->zkpx.b, r, t, ctx->p.q, ctx->ctx);
207e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
208e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
209e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t);
210e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(h);
211e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(r);
212e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
213e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
214e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int verify_zkp(const JPAKE_STEP_PART *p, const BIGNUM *zkpg,
215e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu		      JPAKE_CTX *ctx)
216e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
217e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *h = BN_new();
218e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t1 = BN_new();
219e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t2 = BN_new();
220e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t3 = BN_new();
221e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    int ret = 0;
222e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
223e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    zkp_hash(h, zkpg, p, ctx->p.peer_name);
224e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
225e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t1 = g^b */
226e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t1, zkpg, p->zkpx.b, ctx->p.p, ctx->ctx);
227e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t2 = (g^x)^h = g^{hx} */
228e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t2, p->gx, h, ctx->p.p, ctx->ctx);
229e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t3 = t1 * t2 = g^{hx} * g^b = g^{hx+b} = g^r (allegedly) */
230e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t3, t1, t2, ctx->p.p, ctx->ctx);
231e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
232e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* verify t3 == g^r */
233e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(BN_cmp(t3, p->zkpx.gr) == 0)
234e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	ret = 1;
235e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    else
236e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_VERIFY_ZKP, JPAKE_R_ZKP_VERIFY_FAILED);
237e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
238e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
239e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t3);
240e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t2);
241e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t1);
242e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(h);
243e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
244e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return ret;
245e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
246e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
247e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void generate_step_part(JPAKE_STEP_PART *p, const BIGNUM *x,
248e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu			       const BIGNUM *g, JPAKE_CTX *ctx)
249e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
250e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(p->gx, g, x, ctx->p.p, ctx->ctx);
251e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    generate_zkp(p, x, g, ctx);
252e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
253e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
254e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/* Generate each party's random numbers. xa is in [0, q), xb is in [1, q). */
255e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void genrand(JPAKE_CTX *ctx)
256e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
257e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *qm1;
258e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
259e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* xa in [0, q) */
260e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_rand_range(ctx->xa, ctx->p.q);
261e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
262e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* q-1 */
263e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    qm1 = BN_new();
264e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_copy(qm1, ctx->p.q);
265e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_sub_word(qm1, 1);
266e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
267e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* ... and xb in [0, q-1) */
268e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_rand_range(ctx->xb, qm1);
269e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* [1, q) */
270e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_add_word(ctx->xb, 1);
271e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
272e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
273e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(qm1);
274e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
275e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
276e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP1_generate(JPAKE_STEP1 *send, JPAKE_CTX *ctx)
277e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
278e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    genrand(ctx);
279e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    generate_step_part(&send->p1, ctx->xa, ctx->p.g, ctx);
280e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    generate_step_part(&send->p2, ctx->xb, ctx->p.g, ctx);
281e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
282e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
283e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
284e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
285976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom/* g^x is a legal value */
286976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstromstatic int is_legal(const BIGNUM *gx, const JPAKE_CTX *ctx)
287976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    {
288976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    BIGNUM *t;
289976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    int res;
290976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
291976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    if(BN_is_negative(gx) || BN_is_zero(gx) || BN_cmp(gx, ctx->p.p) >= 0)
292976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	return 0;
293976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
294976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    t = BN_new();
295976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    BN_mod_exp(t, gx, ctx->p.q, ctx->p.p, ctx->ctx);
296976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    res = BN_is_one(t);
297976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    BN_free(t);
298976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
299976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    return res;
300976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    }
301976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
302e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP1_process(JPAKE_CTX *ctx, const JPAKE_STEP1 *received)
303e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
304976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    if(!is_legal(received->p1.gx, ctx))
305976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	{
306976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X3_IS_NOT_LEGAL);
307976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	return 0;
308976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	}
309976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
310976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom    if(!is_legal(received->p2.gx, ctx))
311976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	{
312976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X4_IS_NOT_LEGAL);
313976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	return 0;
314976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom	}
315976a034585c7e8ff9dda5ebe032f399b78887f70Brian Carlstrom
316e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* verify their ZKP(xc) */
317e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(!verify_zkp(&received->p1, ctx->p.g, ctx))
318e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	{
319e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X3_FAILED);
320e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	return 0;
321e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	}
322e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
323e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* verify their ZKP(xd) */
324e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(!verify_zkp(&received->p2, ctx->p.g, ctx))
325e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	{
326e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_VERIFY_X4_FAILED);
327e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	return 0;
328e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	}
329e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
330e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* g^xd != 1 */
331e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(BN_is_one(received->p2.gx))
332e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	{
333e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP1_PROCESS, JPAKE_R_G_TO_THE_X4_IS_ONE);
334e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	return 0;
335e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	}
336e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
337e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* Save the bits we need for later */
338e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_copy(ctx->p.gxc, received->p1.gx);
339e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_copy(ctx->p.gxd, received->p2.gx);
340e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
341e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
342e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
343e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
344e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
345e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP2_generate(JPAKE_STEP2 *send, JPAKE_CTX *ctx)
346e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
347e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t1 = BN_new();
348e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t2 = BN_new();
349e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
350e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
351e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * X = g^{(xa + xc + xd) * xb * s}
352e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * t1 = g^xa
353e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
354e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t1, ctx->p.g, ctx->xa, ctx->p.p, ctx->ctx);
355e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t2 = t1 * g^{xc} = g^{xa} * g^{xc} = g^{xa + xc} */
356e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t2, t1, ctx->p.gxc, ctx->p.p, ctx->ctx);
357e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t1 = t2 * g^{xd} = g^{xa + xc + xd} */
358e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t1, t2, ctx->p.gxd, ctx->p.p, ctx->ctx);
359e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t2 = xb * s */
360e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t2, ctx->xb, ctx->secret, ctx->p.q, ctx->ctx);
361e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
362e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
363e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * ZKP(xb * s)
364e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * XXX: this is kinda funky, because we're using
365e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    *
366e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * g' = g^{xa + xc + xd}
367e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    *
368e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * as the generator, which means X is g'^{xb * s}
369e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * X = t1^{t2} = t1^{xb * s} = g^{(xa + xc + xd) * xb * s}
370e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
371e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    generate_step_part(send, t2, t1, ctx);
372e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
373e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
374e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t1);
375e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t2);
376e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
377e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
378e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
379e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
380e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu/* gx = g^{xc + xa + xb} * xd * s */
381e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic int compute_key(JPAKE_CTX *ctx, const BIGNUM *gx)
382e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
383e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t1 = BN_new();
384e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t2 = BN_new();
385e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t3 = BN_new();
386e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
387e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
388e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * K = (gx/g^{xb * xd * s})^{xb}
389e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    *   = (g^{(xc + xa + xb) * xd * s - xb * xd *s})^{xb}
390e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    *   = (g^{(xa + xc) * xd * s})^{xb}
391e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    *   = g^{(xa + xc) * xb * xd * s}
392e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * [which is the same regardless of who calculates it]
393e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
394e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
395e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t1 = (g^{xd})^{xb} = g^{xb * xd} */
396e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t1, ctx->p.gxd, ctx->xb, ctx->p.p, ctx->ctx);
397e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t2 = -s = q-s */
398e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_sub(t2, ctx->p.q, ctx->secret);
399e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t3 = t1^t2 = g^{-xb * xd * s} */
400e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t3, t1, t2, ctx->p.p, ctx->ctx);
401e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t1 = gx * t3 = X/g^{xb * xd * s} */
402e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t1, gx, t3, ctx->p.p, ctx->ctx);
403e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* K = t1^{xb} */
404e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(ctx->key, t1, ctx->xb, ctx->p.p, ctx->ctx);
405e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
406e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
407e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t3);
408e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t2);
409e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t1);
410e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
411e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
412e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
413e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
414e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP2_process(JPAKE_CTX *ctx, const JPAKE_STEP2 *received)
415e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
416e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t1 = BN_new();
417e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BIGNUM *t2 = BN_new();
418e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    int ret = 0;
419e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
420e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /*
421e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * g' = g^{xc + xa + xb} [from our POV]
422e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    * t1 = xa + xb
423e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    */
424e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_add(t1, ctx->xa, ctx->xb, ctx->p.q, ctx->ctx);
425e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t2 = g^{t1} = g^{xa+xb} */
426e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_exp(t2, ctx->p.g, t1, ctx->p.p, ctx->ctx);
427e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* t1 = g^{xc} * t2 = g^{xc + xa + xb} */
428e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_mod_mul(t1, ctx->p.gxc, t2, ctx->p.p, ctx->ctx);
429e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
430e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(verify_zkp(received, t1, ctx))
431e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	ret = 1;
432e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    else
433e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP2_PROCESS, JPAKE_R_VERIFY_B_FAILED);
434e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
435e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    compute_key(ctx, received->gx);
436e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
437e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu   /* cleanup */
438e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t2);
439e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    BN_free(t1);
440e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
441e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return ret;
442e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
443e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
444e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugustatic void quickhashbn(unsigned char *md, const BIGNUM *bn)
445e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
446e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA_CTX sha;
447e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
448e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Init(&sha);
449e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    hashbn(&sha, bn);
450e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1_Final(md, &sha);
451e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
452e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
453e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP3A_init(JPAKE_STEP3A *s3a)
454e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {}
455e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
456e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP3A_generate(JPAKE_STEP3A *send, JPAKE_CTX *ctx)
457e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
458e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    quickhashbn(send->hhk, ctx->key);
459e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1(send->hhk, sizeof send->hhk, send->hhk);
460e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
461e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
462e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
463e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
464e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP3A_process(JPAKE_CTX *ctx, const JPAKE_STEP3A *received)
465e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
466e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    unsigned char hhk[SHA_DIGEST_LENGTH];
467e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
468e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    quickhashbn(hhk, ctx->key);
469e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    SHA1(hhk, sizeof hhk, hhk);
470e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(memcmp(hhk, received->hhk, sizeof hhk))
471e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	{
472e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP3A_PROCESS, JPAKE_R_HASH_OF_HASH_OF_KEY_MISMATCH);
473e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	return 0;
474e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	}
475e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
476e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
477e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
478e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP3A_release(JPAKE_STEP3A *s3a)
479e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {}
480e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
481e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP3B_init(JPAKE_STEP3B *s3b)
482e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {}
483e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
484e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP3B_generate(JPAKE_STEP3B *send, JPAKE_CTX *ctx)
485e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
486e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    quickhashbn(send->hk, ctx->key);
487e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
488e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
489e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
490e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
491e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguint JPAKE_STEP3B_process(JPAKE_CTX *ctx, const JPAKE_STEP3B *received)
492e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
493e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    unsigned char hk[SHA_DIGEST_LENGTH];
494e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
495e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    quickhashbn(hk, ctx->key);
496e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    if(memcmp(hk, received->hk, sizeof hk))
497e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	{
498e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	JPAKEerr(JPAKE_F_JPAKE_STEP3B_PROCESS, JPAKE_R_HASH_OF_KEY_MISMATCH);
499e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	return 0;
500e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu	}
501e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return 1;
502e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
503e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
504e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguvoid JPAKE_STEP3B_release(JPAKE_STEP3B *s3b)
505e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {}
506e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
507e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modaduguconst BIGNUM *JPAKE_get_shared_key(JPAKE_CTX *ctx)
508e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    {
509e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    return ctx->key;
510e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu    }
511e45f106cb6b47af1f21efe76e933bdea2f5dd1caNagendra Modadugu
512