summaryrefslogtreecommitdiff
path: root/jpake.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2008-11-05 16:20:46 +1100
committerDamien Miller <djm@mindrot.org>2008-11-05 16:20:46 +1100
commit01ed2272a1545336173bf3aef66fbccc3494c8d8 (patch)
treea77f115d3b8964f0b6fcc604f9dea87d15143d7e /jpake.c
parent6f66d34308af787613d5525729953665f26367ee (diff)
- djm@cvs.openbsd.org 2008/11/04 08:22:13
[auth.h auth2.c monitor.c monitor.h monitor_wrap.c monitor_wrap.h] [readconf.c readconf.h servconf.c servconf.h ssh2.h ssh_config.5] [sshconnect2.c sshd_config.5 jpake.c jpake.h schnorr.c auth2-jpake.c] [Makefile.in] Add support for an experimental zero-knowledge password authentication method using the J-PAKE protocol described in F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling", 16th Workshop on Security Protocols, Cambridge, April 2008. This method allows password-based authentication without exposing the password to the server. Instead, the client and server exchange cryptographic proofs to demonstrate of knowledge of the password while revealing nothing useful to an attacker or compromised endpoint. This is experimental, work-in-progress code and is presently compiled-time disabled (turn on -DJPAKE in Makefile.inc). "just commit it. It isn't too intrusive." deraadt@
Diffstat (limited to 'jpake.c')
-rw-r--r--jpake.c604
1 files changed, 604 insertions, 0 deletions
diff --git a/jpake.c b/jpake.c
new file mode 100644
index 000000000..565f2e255
--- /dev/null
+++ b/jpake.c
@@ -0,0 +1,604 @@
1/* $OpenBSD: jpake.c,v 1.1 2008/11/04 08:22:12 djm Exp $ */
2/*
3 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * Shared components of zero-knowledge password auth using J-PAKE protocol
20 * as described in:
21 *
22 * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
23 * 16th Workshop on Security Protocols, Cambridge, April 2008
24 *
25 * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
26 */
27
28#include "includes.h"
29
30#include <sys/types.h>
31
32#include <stdio.h>
33#include <string.h>
34#include <stdarg.h>
35
36#include <openssl/bn.h>
37#include <openssl/evp.h>
38
39#include "xmalloc.h"
40#include "ssh2.h"
41#include "key.h"
42#include "hostfile.h"
43#include "auth.h"
44#include "buffer.h"
45#include "packet.h"
46#include "dispatch.h"
47#include "log.h"
48
49#include "jpake.h"
50
51#ifdef JPAKE
52
53/* RFC3526 group 5, 1536 bits */
54#define JPAKE_GROUP_G "2"
55#define JPAKE_GROUP_P \
56 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" \
57 "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" \
58 "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
59 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" \
60 "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \
61 "9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
62
63struct jpake_group *
64jpake_default_group(void)
65{
66 struct jpake_group *ret;
67
68 ret = xmalloc(sizeof(*ret));
69 ret->p = ret->q = ret->g = NULL;
70 if (BN_hex2bn(&ret->p, JPAKE_GROUP_P) == 0 ||
71 BN_hex2bn(&ret->g, JPAKE_GROUP_G) == 0)
72 fatal("%s: BN_hex2bn", __func__);
73 /* Subgroup order is p/2 (p is a safe prime) */
74 if ((ret->q = BN_new()) == NULL)
75 fatal("%s: BN_new", __func__);
76 if (BN_rshift1(ret->q, ret->p) != 1)
77 fatal("%s: BN_rshift1", __func__);
78
79 return ret;
80}
81
82/*
83 * Generate uniformly distributed random number in range (1, high).
84 * Return number on success, NULL on failure.
85 */
86BIGNUM *
87bn_rand_range_gt_one(const BIGNUM *high)
88{
89 BIGNUM *r, *tmp;
90 int success = -1;
91
92 if ((tmp = BN_new()) == NULL) {
93 error("%s: BN_new", __func__);
94 return NULL;
95 }
96 if ((r = BN_new()) == NULL) {
97 error("%s: BN_new failed", __func__);
98 goto out;
99 }
100 if (BN_set_word(tmp, 2) != 1) {
101 error("%s: BN_set_word(tmp, 2)", __func__);
102 goto out;
103 }
104 if (BN_sub(tmp, high, tmp) == -1) {
105 error("%s: BN_sub failed (tmp = high - 2)", __func__);
106 goto out;
107 }
108 if (BN_rand_range(r, tmp) == -1) {
109 error("%s: BN_rand_range failed", __func__);
110 goto out;
111 }
112 if (BN_set_word(tmp, 2) != 1) {
113 error("%s: BN_set_word(tmp, 2)", __func__);
114 goto out;
115 }
116 if (BN_add(r, r, tmp) == -1) {
117 error("%s: BN_add failed (r = r + 2)", __func__);
118 goto out;
119 }
120 success = 0;
121 out:
122 BN_clear_free(tmp);
123 if (success == 0)
124 return r;
125 BN_clear_free(r);
126 return NULL;
127}
128
129/*
130 * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success,
131 * with digest via 'digestp' (caller to free) and length via 'lenp'.
132 * Returns -1 on failure.
133 */
134int
135hash_buffer(const u_char *buf, u_int len, const EVP_MD *md,
136 u_char **digestp, u_int *lenp)
137{
138 u_char digest[EVP_MAX_MD_SIZE];
139 u_int digest_len;
140 EVP_MD_CTX evp_md_ctx;
141 int success = -1;
142
143 EVP_MD_CTX_init(&evp_md_ctx);
144
145 if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) {
146 error("%s: EVP_DigestInit_ex", __func__);
147 goto out;
148 }
149 if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) {
150 error("%s: EVP_DigestUpdate", __func__);
151 goto out;
152 }
153 if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) {
154 error("%s: EVP_DigestFinal_ex", __func__);
155 goto out;
156 }
157 *digestp = xmalloc(digest_len);
158 *lenp = digest_len;
159 memcpy(*digestp, digest, *lenp);
160 success = 0;
161 out:
162 EVP_MD_CTX_cleanup(&evp_md_ctx);
163 bzero(digest, sizeof(digest));
164 digest_len = 0;
165 return success;
166}
167
168/* print formatted string followed by bignum */
169void
170jpake_debug3_bn(const BIGNUM *n, const char *fmt, ...)
171{
172 char *out, *h;
173 va_list args;
174
175 out = NULL;
176 va_start(args, fmt);
177 vasprintf(&out, fmt, args);
178 va_end(args);
179 if (out == NULL)
180 fatal("%s: vasprintf failed", __func__);
181
182 if (n == NULL)
183 debug3("%s(null)", out);
184 else {
185 h = BN_bn2hex(n);
186 debug3("%s0x%s", out, h);
187 free(h);
188 }
189 free(out);
190}
191
192/* print formatted string followed by buffer contents in hex */
193void
194jpake_debug3_buf(const u_char *buf, u_int len, const char *fmt, ...)
195{
196 char *out, h[65];
197 u_int i, j;
198 va_list args;
199
200 out = NULL;
201 va_start(args, fmt);
202 vasprintf(&out, fmt, args);
203 va_end(args);
204 if (out == NULL)
205 fatal("%s: vasprintf failed", __func__);
206
207 debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : "");
208 free(out);
209 if (buf == NULL)
210 return;
211
212 *h = '\0';
213 for (i = j = 0; i < len; i++) {
214 snprintf(h + j, sizeof(h) - j, "%02x", buf[i]);
215 j += 2;
216 if (j >= sizeof(h) - 1 || i == len - 1) {
217 debug3(" %s", h);
218 *h = '\0';
219 j = 0;
220 }
221 }
222}
223
224struct jpake_ctx *
225jpake_new(void)
226{
227 struct jpake_ctx *ret;
228
229 ret = xcalloc(1, sizeof(*ret));
230
231 ret->grp = jpake_default_group();
232
233 ret->s = ret->k = NULL;
234 ret->x1 = ret->x2 = ret->x3 = ret->x4 = NULL;
235 ret->g_x1 = ret->g_x2 = ret->g_x3 = ret->g_x4 = NULL;
236 ret->a = ret->b = NULL;
237
238 ret->client_id = ret->server_id = NULL;
239 ret->h_k_cid_sessid = ret->h_k_sid_sessid = NULL;
240
241 debug3("%s: alloc %p", __func__, ret);
242
243 return ret;
244}
245
246
247void
248jpake_free(struct jpake_ctx *pctx)
249{
250 debug3("%s: free %p", __func__, pctx);
251
252#define JPAKE_BN_CLEAR_FREE(v) \
253 do { \
254 if ((v) != NULL) { \
255 BN_clear_free(v); \
256 (v) = NULL; \
257 } \
258 } while (0)
259#define JPAKE_BUF_CLEAR_FREE(v, l) \
260 do { \
261 if ((v) != NULL) { \
262 bzero((v), (l)); \
263 xfree(v); \
264 (v) = NULL; \
265 (l) = 0; \
266 } \
267 } while (0)
268
269 JPAKE_BN_CLEAR_FREE(pctx->s);
270 JPAKE_BN_CLEAR_FREE(pctx->k);
271 JPAKE_BN_CLEAR_FREE(pctx->x1);
272 JPAKE_BN_CLEAR_FREE(pctx->x2);
273 JPAKE_BN_CLEAR_FREE(pctx->x3);
274 JPAKE_BN_CLEAR_FREE(pctx->x4);
275 JPAKE_BN_CLEAR_FREE(pctx->g_x1);
276 JPAKE_BN_CLEAR_FREE(pctx->g_x2);
277 JPAKE_BN_CLEAR_FREE(pctx->g_x3);
278 JPAKE_BN_CLEAR_FREE(pctx->g_x4);
279 JPAKE_BN_CLEAR_FREE(pctx->a);
280 JPAKE_BN_CLEAR_FREE(pctx->b);
281
282 JPAKE_BUF_CLEAR_FREE(pctx->client_id, pctx->client_id_len);
283 JPAKE_BUF_CLEAR_FREE(pctx->server_id, pctx->server_id_len);
284 JPAKE_BUF_CLEAR_FREE(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
285 JPAKE_BUF_CLEAR_FREE(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
286
287#undef JPAKE_BN_CLEAR_FREE
288#undef JPAKE_BUF_CLEAR_FREE
289
290 bzero(pctx, sizeof(pctx));
291 xfree(pctx);
292}
293
294/* dump entire jpake_ctx. NB. includes private values! */
295void
296jpake_dump(struct jpake_ctx *pctx, const char *fmt, ...)
297{
298 char *out;
299 va_list args;
300
301 out = NULL;
302 va_start(args, fmt);
303 vasprintf(&out, fmt, args);
304 va_end(args);
305 if (out == NULL)
306 fatal("%s: vasprintf failed", __func__);
307
308 debug3("%s: %s (ctx at %p)", __func__, out, pctx);
309 if (pctx == NULL) {
310 free(out);
311 return;
312 }
313
314#define JPAKE_DUMP_BN(a) do { \
315 if ((a) != NULL) \
316 JPAKE_DEBUG_BN(((a), "%s = ", #a)); \
317 } while (0)
318#define JPAKE_DUMP_BUF(a, b) do { \
319 if ((a) != NULL) \
320 JPAKE_DEBUG_BUF((a, b, "%s", #a)); \
321 } while (0)
322
323 JPAKE_DUMP_BN(pctx->s);
324 JPAKE_DUMP_BN(pctx->k);
325 JPAKE_DUMP_BN(pctx->x1);
326 JPAKE_DUMP_BN(pctx->x2);
327 JPAKE_DUMP_BN(pctx->x3);
328 JPAKE_DUMP_BN(pctx->x4);
329 JPAKE_DUMP_BN(pctx->g_x1);
330 JPAKE_DUMP_BN(pctx->g_x2);
331 JPAKE_DUMP_BN(pctx->g_x3);
332 JPAKE_DUMP_BN(pctx->g_x4);
333 JPAKE_DUMP_BN(pctx->a);
334 JPAKE_DUMP_BN(pctx->b);
335
336 JPAKE_DUMP_BUF(pctx->client_id, pctx->client_id_len);
337 JPAKE_DUMP_BUF(pctx->server_id, pctx->server_id_len);
338 JPAKE_DUMP_BUF(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
339 JPAKE_DUMP_BUF(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
340
341 debug3("%s: %s done", __func__, out);
342 free(out);
343}
344
345/* Shared parts of step 1 exchange calculation */
346void
347jpake_step1(struct jpake_group *grp,
348 u_char **id, u_int *id_len,
349 BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
350 u_char **priv1_proof, u_int *priv1_proof_len,
351 u_char **priv2_proof, u_int *priv2_proof_len)
352{
353 BN_CTX *bn_ctx;
354
355 if ((bn_ctx = BN_CTX_new()) == NULL)
356 fatal("%s: BN_CTX_new", __func__);
357
358 /* Random nonce to prevent replay */
359 *id = xmalloc(KZP_ID_LEN);
360 *id_len = KZP_ID_LEN;
361 arc4random_buf(*id, *id_len);
362
363 /*
364 * x1/x3 is a random element of Zq
365 * x2/x4 is a random element of Z*q
366 * We also exclude [1] from x1/x3 candidates and [0, 1] from
367 * x2/x4 candiates to avoid possible degeneracy (i.e. g^0, g^1).
368 */
369 if ((*priv1 = bn_rand_range_gt_one(grp->q)) == NULL ||
370 (*priv2 = bn_rand_range_gt_one(grp->q)) == NULL)
371 fatal("%s: bn_rand_range_gt_one", __func__);
372
373 /*
374 * client: g_x1 = g^x1 mod p / server: g_x3 = g^x3 mod p
375 * client: g_x2 = g^x2 mod p / server: g_x4 = g^x4 mod p
376 */
377 if ((*g_priv1 = BN_new()) == NULL ||
378 (*g_priv2 = BN_new()) == NULL)
379 fatal("%s: BN_new", __func__);
380 if (BN_mod_exp(*g_priv1, grp->g, *priv1, grp->p, bn_ctx) == -1)
381 fatal("%s: BN_mod_exp", __func__);
382 if (BN_mod_exp(*g_priv2, grp->g, *priv2, grp->p, bn_ctx) == -1)
383 fatal("%s: BN_mod_exp", __func__);
384
385 /* Generate proofs for holding x1/x3 and x2/x4 */
386 if (schnorr_sign(grp->p, grp->q, grp->g,
387 *priv1, *g_priv1, *id, *id_len,
388 priv1_proof, priv1_proof_len) != 0)
389 fatal("%s: schnorr_sign", __func__);
390 if (schnorr_sign(grp->p, grp->q, grp->g,
391 *priv2, *g_priv2, *id, *id_len,
392 priv2_proof, priv2_proof_len) != 0)
393 fatal("%s: schnorr_sign", __func__);
394
395 BN_CTX_free(bn_ctx);
396}
397
398/* Shared parts of step 2 exchange calculation */
399void
400jpake_step2(struct jpake_group *grp, BIGNUM *s,
401 BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
402 const u_char *theirid, u_int theirid_len,
403 const u_char *myid, u_int myid_len,
404 const u_char *theirpub1_proof, u_int theirpub1_proof_len,
405 const u_char *theirpub2_proof, u_int theirpub2_proof_len,
406 BIGNUM **newpub,
407 u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
408{
409 BN_CTX *bn_ctx;
410 BIGNUM *tmp, *exponent;
411
412 /* Validate peer's step 1 values */
413 if (BN_cmp(theirpub1, BN_value_one()) <= 0)
414 fatal("%s: theirpub1 <= 1", __func__);
415 if (BN_cmp(theirpub2, BN_value_one()) <= 0)
416 fatal("%s: theirpub2 <= 1", __func__);
417
418 if (schnorr_verify(grp->p, grp->q, grp->g, theirpub1,
419 theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1)
420 fatal("%s: schnorr_verify theirpub1 failed", __func__);
421 if (schnorr_verify(grp->p, grp->q, grp->g, theirpub2,
422 theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1)
423 fatal("%s: schnorr_verify theirpub2 failed", __func__);
424
425 if ((bn_ctx = BN_CTX_new()) == NULL)
426 fatal("%s: BN_CTX_new", __func__);
427
428 if ((*newpub = BN_new()) == NULL ||
429 (tmp = BN_new()) == NULL ||
430 (exponent = BN_new()) == NULL)
431 fatal("%s: BN_new", __func__);
432
433 /*
434 * client: exponent = x2 * s mod p
435 * server: exponent = x4 * s mod p
436 */
437 if (BN_mod_mul(exponent, mypriv2, s, grp->q, bn_ctx) != 1)
438 fatal("%s: BN_mod_mul (exponent = mypriv2 * s mod p)",
439 __func__);
440
441 /*
442 * client: tmp = g^(x1 + x3 + x4) mod p
443 * server: tmp = g^(x1 + x2 + x3) mod p
444 */
445 if (BN_mod_mul(tmp, mypub1, theirpub1, grp->p, bn_ctx) != 1)
446 fatal("%s: BN_mod_mul (tmp = mypub1 * theirpub1 mod p)",
447 __func__);
448 if (BN_mod_mul(tmp, tmp, theirpub2, grp->p, bn_ctx) != 1)
449 fatal("%s: BN_mod_mul (tmp = tmp * theirpub2 mod p)", __func__);
450
451 /*
452 * client: a = tmp^exponent = g^((x1+x3+x4) * x2 * s) mod p
453 * server: b = tmp^exponent = g^((x1+x2+x3) * x4 * s) mod p
454 */
455 if (BN_mod_exp(*newpub, tmp, exponent, grp->p, bn_ctx) != 1)
456 fatal("%s: BN_mod_mul (newpub = tmp^exponent mod p)", __func__);
457
458 JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
459 JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__));
460
461 /* Note the generator here is 'tmp', not g */
462 if (schnorr_sign(grp->p, grp->q, tmp, exponent, *newpub,
463 myid, myid_len,
464 newpub_exponent_proof, newpub_exponent_proof_len) != 0)
465 fatal("%s: schnorr_sign newpub", __func__);
466
467 BN_clear_free(tmp); /* XXX stash for later use? */
468 BN_clear_free(exponent); /* XXX stash for later use? (yes, in conf) */
469
470 BN_CTX_free(bn_ctx);
471}
472
473/* Confirmation hash calculation */
474void
475jpake_confirm_hash(const BIGNUM *k,
476 const u_char *endpoint_id, u_int endpoint_id_len,
477 const u_char *sess_id, u_int sess_id_len,
478 u_char **confirm_hash, u_int *confirm_hash_len)
479{
480 Buffer b;
481
482 /*
483 * Calculate confirmation proof:
484 * client: H(k || client_id || session_id)
485 * server: H(k || server_id || session_id)
486 */
487 buffer_init(&b);
488 buffer_put_bignum2(&b, k);
489 buffer_put_string(&b, endpoint_id, endpoint_id_len);
490 buffer_put_string(&b, sess_id, sess_id_len);
491 if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
492 confirm_hash, confirm_hash_len) != 0)
493 fatal("%s: hash_buffer", __func__);
494 buffer_free(&b);
495}
496
497/* Shared parts of key derivation and confirmation calculation */
498void
499jpake_key_confirm(struct jpake_group *grp, BIGNUM *s, BIGNUM *step2_val,
500 BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
501 BIGNUM *theirpub1, BIGNUM *theirpub2,
502 const u_char *my_id, u_int my_id_len,
503 const u_char *their_id, u_int their_id_len,
504 const u_char *sess_id, u_int sess_id_len,
505 const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
506 BIGNUM **k,
507 u_char **confirm_hash, u_int *confirm_hash_len)
508{
509 BN_CTX *bn_ctx;
510 BIGNUM *tmp;
511
512 if ((bn_ctx = BN_CTX_new()) == NULL)
513 fatal("%s: BN_CTX_new", __func__);
514 if ((tmp = BN_new()) == NULL ||
515 (*k = BN_new()) == NULL)
516 fatal("%s: BN_new", __func__);
517
518 /* Validate step 2 values */
519 if (BN_cmp(step2_val, BN_value_one()) <= 0)
520 fatal("%s: step2_val <= 1", __func__);
521
522 /*
523 * theirpriv2_s_proof is calculated with a different generator:
524 * tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1
525 * Calculate it here so we can check the signature.
526 */
527 if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1)
528 fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__);
529 if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1)
530 fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__);
531
532 JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
533
534 if (schnorr_verify(grp->p, grp->q, tmp, step2_val,
535 their_id, their_id_len,
536 theirpriv2_s_proof, theirpriv2_s_proof_len) != 1)
537 fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__);
538
539 /*
540 * Derive shared key:
541 * client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s)
542 * server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s)
543 *
544 * Computed as:
545 * client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p
546 * server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p
547 */
548 if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1)
549 fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__);
550 if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1)
551 fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__);
552 if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1)
553 fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__);
554 if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1)
555 fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__);
556 if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1)
557 fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__);
558
559 BN_CTX_free(bn_ctx);
560 BN_clear_free(tmp);
561
562 jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len,
563 confirm_hash, confirm_hash_len);
564}
565
566/*
567 * Calculate and check confirmation hash from peer. Returns 1 on success
568 * 0 on failure/mismatch.
569 */
570int
571jpake_check_confirm(const BIGNUM *k,
572 const u_char *peer_id, u_int peer_id_len,
573 const u_char *sess_id, u_int sess_id_len,
574 const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
575{
576 u_char *expected_confirm_hash;
577 u_int expected_confirm_hash_len;
578 int success = 0;
579
580 /* Calculate and verify expected confirmation hash */
581 jpake_confirm_hash(k, peer_id, peer_id_len, sess_id, sess_id_len,
582 &expected_confirm_hash, &expected_confirm_hash_len);
583
584 JPAKE_DEBUG_BUF((expected_confirm_hash, expected_confirm_hash_len,
585 "%s: expected confirm hash", __func__));
586 JPAKE_DEBUG_BUF((peer_confirm_hash, peer_confirm_hash_len,
587 "%s: received confirm hash", __func__));
588
589 if (peer_confirm_hash_len != expected_confirm_hash_len)
590 error("%s: confirmation length mismatch (my %u them %u)",
591 __func__, expected_confirm_hash_len, peer_confirm_hash_len);
592 else if (memcmp(peer_confirm_hash, expected_confirm_hash,
593 expected_confirm_hash_len) == 0)
594 success = 1;
595 bzero(expected_confirm_hash, expected_confirm_hash_len);
596 xfree(expected_confirm_hash);
597 debug3("%s: success = %d", __func__, success);
598 return success;
599}
600
601/* XXX main() function with tests */
602
603#endif /* JPAKE */
604