~ubuntu-branches/ubuntu/lucid/openssh/lucid

« back to all changes in this revision

Viewing changes to schnorr.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2010-01-26 13:07:40 UTC
  • mfrom: (1.13.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20100126130740-d7r70jqrqlbvz3r0
Tags: 1:5.3p1-1ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Add support for registering ConsoleKit sessions on login.
  - Drop openssh-blacklist and openssh-blacklist-extra to Suggests; they
    take up a lot of CD space, and I suspect that rolling them out in
    security updates has covered most affected systems now.
  - Convert to Upstart.  The init script is still here for the benefit of
    people running sshd in chroots.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $OpenBSD: schnorr.c,v 1.2 2009/02/18 04:31:21 djm Exp $ */
 
1
/* $OpenBSD: schnorr.c,v 1.3 2009/03/05 07:18:19 djm Exp $ */
2
2
/*
3
3
 * Copyright (c) 2008 Damien Miller.  All rights reserved.
4
4
 *
40
40
#include "buffer.h"
41
41
#include "log.h"
42
42
 
43
 
#include "jpake.h"
 
43
#include "schnorr.h"
 
44
 
 
45
#include "openbsd-compat/openssl-compat.h"
44
46
 
45
47
/* #define SCHNORR_DEBUG */             /* Privacy-violating debugging */
46
48
/* #define SCHNORR_MAIN */              /* Include main() selftest */
47
49
 
48
 
/* XXX */
49
 
/* Parametise signature hash? (sha256, sha1, etc.) */
50
 
/* Signature format - include type name, hash type, group params? */
51
 
 
52
50
#ifndef SCHNORR_DEBUG
53
51
# define SCHNORR_DEBUG_BN(a)
54
52
# define SCHNORR_DEBUG_BUF(a)
55
53
#else
56
 
# define SCHNORR_DEBUG_BN(a)    jpake_debug3_bn a
57
 
# define SCHNORR_DEBUG_BUF(a)   jpake_debug3_buf a
 
54
# define SCHNORR_DEBUG_BN(a)    debug3_bn a
 
55
# define SCHNORR_DEBUG_BUF(a)   debug3_buf a
58
56
#endif /* SCHNORR_DEBUG */
59
57
 
60
58
/*
61
59
 * Calculate hash component of Schnorr signature H(g || g^v || g^x || id)
62
 
 * using SHA1. Returns signature as bignum or NULL on error.
 
60
 * using the hash function defined by "evp_md". Returns signature as
 
61
 * bignum or NULL on error.
63
62
 */
64
63
static BIGNUM *
65
64
schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g,
66
 
    const BIGNUM *g_v, const BIGNUM *g_x,
 
65
    const EVP_MD *evp_md, const BIGNUM *g_v, const BIGNUM *g_x,
67
66
    const u_char *id, u_int idlen)
68
67
{
69
68
        u_char *digest;
70
69
        u_int digest_len;
71
70
        BIGNUM *h;
72
 
        EVP_MD_CTX evp_md_ctx;
73
71
        Buffer b;
74
72
        int success = -1;
75
73
 
79
77
        }
80
78
 
81
79
        buffer_init(&b);
82
 
        EVP_MD_CTX_init(&evp_md_ctx);
83
80
 
84
81
        /* h = H(g || p || q || g^v || g^x || id) */
85
82
        buffer_put_bignum2(&b, g);
91
88
 
92
89
        SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
93
90
            "%s: hashblob", __func__));
94
 
        if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
 
91
        if (hash_buffer(buffer_ptr(&b), buffer_len(&b), evp_md,
95
92
            &digest, &digest_len) != 0) {
96
93
                error("%s: hash_buffer", __func__);
97
94
                goto out;
104
101
        SCHNORR_DEBUG_BN((h, "%s: h = ", __func__));
105
102
 out:
106
103
        buffer_free(&b);
107
 
        EVP_MD_CTX_cleanup(&evp_md_ctx);
108
104
        bzero(digest, digest_len);
109
105
        xfree(digest);
110
106
        digest_len = 0;
117
113
/*
118
114
 * Generate Schnorr signature to prove knowledge of private value 'x' used
119
115
 * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
 
116
 * using the hash function "evp_md".
120
117
 * 'idlen' bytes from 'id' will be included in the signature hash as an anti-
121
118
 * replay salt.
122
 
 * On success, 0 is returned and *siglen bytes of signature are returned in
123
 
 * *sig (caller to free). Returns -1 on failure.
 
119
 * 
 
120
 * On success, 0 is returned. The signature values are returned as *e_p
 
121
 * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values.
 
122
 * On failure, -1 is returned.
124
123
 */
125
124
int
126
125
schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
127
 
    const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
128
 
    u_char **sig, u_int *siglen)
 
126
    const EVP_MD *evp_md, const BIGNUM *x, const BIGNUM *g_x,
 
127
    const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p)
129
128
{
130
129
        int success = -1;
131
 
        Buffer b;
132
130
        BIGNUM *h, *tmp, *v, *g_v, *r;
133
131
        BN_CTX *bn_ctx;
134
132
 
171
169
        SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__));
172
170
 
173
171
        /* h = H(g || g^v || g^x || id) */
174
 
        if ((h = schnorr_hash(grp_p, grp_q, grp_g, g_v, g_x,
 
172
        if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, g_v, g_x,
175
173
            id, idlen)) == NULL) {
176
174
                error("%s: schnorr_hash failed", __func__);
177
175
                goto out;
186
184
                error("%s: BN_mod_mul (r = v - tmp)", __func__);
187
185
                goto out;
188
186
        }
 
187
        SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__));
189
188
        SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
190
189
 
191
 
        /* Signature is (g_v, r) */
 
190
        *e_p = g_v;
 
191
        *r_p = r;
 
192
 
 
193
        success = 0;
 
194
 out:
 
195
        BN_CTX_free(bn_ctx);
 
196
        if (h != NULL)
 
197
                BN_clear_free(h);
 
198
        if (v != NULL)
 
199
                BN_clear_free(v);
 
200
        BN_clear_free(tmp);
 
201
 
 
202
        return success;
 
203
}
 
204
 
 
205
/*
 
206
 * Generate Schnorr signature to prove knowledge of private value 'x' used
 
207
 * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
 
208
 * using a SHA256 hash.
 
209
 * 'idlen' bytes from 'id' will be included in the signature hash as an anti-
 
210
 * replay salt.
 
211
 * On success, 0 is returned and *siglen bytes of signature are returned in
 
212
 * *sig (caller to free). Returns -1 on failure.
 
213
 */
 
214
int
 
215
schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
 
216
    const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
 
217
    u_char **sig, u_int *siglen)
 
218
{
 
219
        Buffer b;
 
220
        BIGNUM *r, *e;
 
221
 
 
222
        if (schnorr_sign(grp_p, grp_q, grp_g, EVP_sha256(),
 
223
            x, g_x, id, idlen, &r, &e) != 0)
 
224
                return -1;
 
225
 
 
226
        /* Signature is (e, r) */
192
227
        buffer_init(&b);
193
228
        /* XXX sigtype-hash as string? */
194
 
        buffer_put_bignum2(&b, g_v);
 
229
        buffer_put_bignum2(&b, e);
195
230
        buffer_put_bignum2(&b, r);
196
231
        *siglen = buffer_len(&b);
197
232
        *sig = xmalloc(*siglen);
199
234
        SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
200
235
            "%s: sigblob", __func__));
201
236
        buffer_free(&b);
202
 
        success = 0;
203
 
 out:
204
 
        BN_CTX_free(bn_ctx);
205
 
        if (h != NULL)
206
 
                BN_clear_free(h);
207
 
        if (v != NULL)
208
 
                BN_clear_free(v);
 
237
 
209
238
        BN_clear_free(r);
210
 
        BN_clear_free(g_v);
211
 
        BN_clear_free(tmp);
 
239
        BN_clear_free(e);
212
240
 
213
 
        return success;
 
241
        return 0;
214
242
}
215
243
 
216
244
/*
217
 
 * Verify Schnorr signature 'sig' of length 'siglen' against public exponent
218
 
 * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g'.
 
245
 * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against
 
246
 * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and
 
247
 * 'grp_g' using hash "evp_md".
219
248
 * Signature hash will be salted with 'idlen' bytes from 'id'.
220
249
 * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
221
250
 */
222
251
int
223
252
schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
224
 
    const BIGNUM *g_x, const u_char *id, u_int idlen,
225
 
    const u_char *sig, u_int siglen)
 
253
    const EVP_MD *evp_md, const BIGNUM *g_x, const u_char *id, u_int idlen,
 
254
    const BIGNUM *r, const BIGNUM *e)
226
255
{
227
256
        int success = -1;
228
 
        Buffer b;
229
 
        BIGNUM *g_v, *h, *r, *g_xh, *g_r, *expected;
 
257
        BIGNUM *h, *g_xh, *g_r, *expected;
230
258
        BN_CTX *bn_ctx;
231
 
        u_int rlen;
232
259
 
233
260
        SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
234
261
 
238
265
                return -1;
239
266
        }
240
267
 
241
 
        g_v = h = r = g_xh = g_r = expected = NULL;
 
268
        h = g_xh = g_r = expected = NULL;
242
269
        if ((bn_ctx = BN_CTX_new()) == NULL) {
243
270
                error("%s: BN_CTX_new", __func__);
244
271
                goto out;
245
272
        }
246
 
        if ((g_v = BN_new()) == NULL ||
247
 
            (r = BN_new()) == NULL ||
248
 
            (g_xh = BN_new()) == NULL ||
 
273
        if ((g_xh = BN_new()) == NULL ||
249
274
            (g_r = BN_new()) == NULL ||
250
275
            (expected = BN_new()) == NULL) {
251
276
                error("%s: BN_new", __func__);
252
277
                goto out;
253
278
        }
254
279
 
255
 
        /* Extract g^v and r from signature blob */
256
 
        buffer_init(&b);
257
 
        buffer_append(&b, sig, siglen);
258
 
        SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
259
 
            "%s: sigblob", __func__));
260
 
        buffer_get_bignum2(&b, g_v);
261
 
        buffer_get_bignum2(&b, r);
262
 
        rlen = buffer_len(&b);
263
 
        buffer_free(&b);
264
 
        if (rlen != 0) {
265
 
                error("%s: remaining bytes in signature %d", __func__, rlen);
266
 
                goto out;
267
 
        }
268
 
        buffer_free(&b);
269
 
        SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__));
 
280
        SCHNORR_DEBUG_BN((e, "%s: e = ", __func__));
270
281
        SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
271
282
 
272
283
        /* h = H(g || g^v || g^x || id) */
273
 
        if ((h = schnorr_hash(grp_p, grp_q, grp_g, g_v, g_x,
 
284
        if ((h = schnorr_hash(grp_p, grp_q, grp_g, evp_md, e, g_x,
274
285
            id, idlen)) == NULL) {
275
286
                error("%s: schnorr_hash failed", __func__);
276
287
                goto out;
297
308
        }
298
309
        SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__));
299
310
 
300
 
        /* Check g_v == expected */
301
 
        success = BN_cmp(expected, g_v) == 0;
 
311
        /* Check e == expected */
 
312
        success = BN_cmp(expected, e) == 0;
302
313
 out:
303
314
        BN_CTX_free(bn_ctx);
304
315
        if (h != NULL)
305
316
                BN_clear_free(h);
306
 
        BN_clear_free(g_v);
307
 
        BN_clear_free(r);
308
317
        BN_clear_free(g_xh);
309
318
        BN_clear_free(g_r);
310
319
        BN_clear_free(expected);
311
320
        return success;
312
321
}
313
322
 
 
323
/*
 
324
 * Verify Schnorr signature 'sig' of length 'siglen' against public exponent
 
325
 * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a
 
326
 * SHA256 hash.
 
327
 * Signature hash will be salted with 'idlen' bytes from 'id'.
 
328
 * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
 
329
 */
 
330
int
 
331
schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q,
 
332
    const BIGNUM *grp_g,
 
333
    const BIGNUM *g_x, const u_char *id, u_int idlen,
 
334
    const u_char *sig, u_int siglen)
 
335
{
 
336
        Buffer b;
 
337
        int ret = -1;
 
338
        u_int rlen;
 
339
        BIGNUM *r, *e;
 
340
 
 
341
        e = r = NULL;
 
342
        if ((e = BN_new()) == NULL ||
 
343
            (r = BN_new()) == NULL) {
 
344
                error("%s: BN_new", __func__);
 
345
                goto out;
 
346
        }
 
347
 
 
348
        /* Extract g^v and r from signature blob */
 
349
        buffer_init(&b);
 
350
        buffer_append(&b, sig, siglen);
 
351
        SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
 
352
            "%s: sigblob", __func__));
 
353
        buffer_get_bignum2(&b, e);
 
354
        buffer_get_bignum2(&b, r);
 
355
        rlen = buffer_len(&b);
 
356
        buffer_free(&b);
 
357
        if (rlen != 0) {
 
358
                error("%s: remaining bytes in signature %d", __func__, rlen);
 
359
                goto out;
 
360
        }
 
361
 
 
362
        ret = schnorr_verify(grp_p, grp_q, grp_g, EVP_sha256(),
 
363
            g_x, id, idlen, r, e);
 
364
 out:
 
365
        BN_clear_free(e);
 
366
        BN_clear_free(r);
 
367
 
 
368
        return ret;
 
369
}
 
370
 
 
371
/* Helper functions */
 
372
 
 
373
/*
 
374
 * Generate uniformly distributed random number in range (1, high).
 
375
 * Return number on success, NULL on failure.
 
376
 */
 
377
BIGNUM *
 
378
bn_rand_range_gt_one(const BIGNUM *high)
 
379
{
 
380
        BIGNUM *r, *tmp;
 
381
        int success = -1;
 
382
 
 
383
        if ((tmp = BN_new()) == NULL) {
 
384
                error("%s: BN_new", __func__);
 
385
                return NULL;
 
386
        }
 
387
        if ((r = BN_new()) == NULL) {
 
388
                error("%s: BN_new failed", __func__);
 
389
                goto out;
 
390
        }
 
391
        if (BN_set_word(tmp, 2) != 1) {
 
392
                error("%s: BN_set_word(tmp, 2)", __func__);
 
393
                goto out;
 
394
        }
 
395
        if (BN_sub(tmp, high, tmp) == -1) {
 
396
                error("%s: BN_sub failed (tmp = high - 2)", __func__);
 
397
                goto out;
 
398
        }
 
399
        if (BN_rand_range(r, tmp) == -1) {
 
400
                error("%s: BN_rand_range failed", __func__);
 
401
                goto out;
 
402
        }
 
403
        if (BN_set_word(tmp, 2) != 1) {
 
404
                error("%s: BN_set_word(tmp, 2)", __func__);
 
405
                goto out;
 
406
        }
 
407
        if (BN_add(r, r, tmp) == -1) {
 
408
                error("%s: BN_add failed (r = r + 2)", __func__);
 
409
                goto out;
 
410
        }
 
411
        success = 0;
 
412
 out:
 
413
        BN_clear_free(tmp);
 
414
        if (success == 0)
 
415
                return r;
 
416
        BN_clear_free(r);
 
417
        return NULL;
 
418
}
 
419
 
 
420
/*
 
421
 * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success,
 
422
 * with digest via 'digestp' (caller to free) and length via 'lenp'.
 
423
 * Returns -1 on failure.
 
424
 */
 
425
int
 
426
hash_buffer(const u_char *buf, u_int len, const EVP_MD *md,
 
427
    u_char **digestp, u_int *lenp)
 
428
{
 
429
        u_char digest[EVP_MAX_MD_SIZE];
 
430
        u_int digest_len;
 
431
        EVP_MD_CTX evp_md_ctx;
 
432
        int success = -1;
 
433
 
 
434
        EVP_MD_CTX_init(&evp_md_ctx);
 
435
 
 
436
        if (EVP_DigestInit_ex(&evp_md_ctx, md, NULL) != 1) {
 
437
                error("%s: EVP_DigestInit_ex", __func__);
 
438
                goto out;
 
439
        }
 
440
        if (EVP_DigestUpdate(&evp_md_ctx, buf, len) != 1) {
 
441
                error("%s: EVP_DigestUpdate", __func__);
 
442
                goto out;
 
443
        }
 
444
        if (EVP_DigestFinal_ex(&evp_md_ctx, digest, &digest_len) != 1) {
 
445
                error("%s: EVP_DigestFinal_ex", __func__);
 
446
                goto out;
 
447
        }
 
448
        *digestp = xmalloc(digest_len);
 
449
        *lenp = digest_len;
 
450
        memcpy(*digestp, digest, *lenp);
 
451
        success = 0;
 
452
 out:
 
453
        EVP_MD_CTX_cleanup(&evp_md_ctx);
 
454
        bzero(digest, sizeof(digest));
 
455
        digest_len = 0;
 
456
        return success;
 
457
}
 
458
 
 
459
/* print formatted string followed by bignum */
 
460
void
 
461
debug3_bn(const BIGNUM *n, const char *fmt, ...)
 
462
{
 
463
        char *out, *h;
 
464
        va_list args;
 
465
 
 
466
        out = NULL;
 
467
        va_start(args, fmt);
 
468
        vasprintf(&out, fmt, args);
 
469
        va_end(args);
 
470
        if (out == NULL)
 
471
                fatal("%s: vasprintf failed", __func__);
 
472
 
 
473
        if (n == NULL)
 
474
                debug3("%s(null)", out);
 
475
        else {
 
476
                h = BN_bn2hex(n);
 
477
                debug3("%s0x%s", out, h);
 
478
                free(h);
 
479
        }
 
480
        free(out);
 
481
}
 
482
 
 
483
/* print formatted string followed by buffer contents in hex */
 
484
void
 
485
debug3_buf(const u_char *buf, u_int len, const char *fmt, ...)
 
486
{
 
487
        char *out, h[65];
 
488
        u_int i, j;
 
489
        va_list args;
 
490
 
 
491
        out = NULL;
 
492
        va_start(args, fmt);
 
493
        vasprintf(&out, fmt, args);
 
494
        va_end(args);
 
495
        if (out == NULL)
 
496
                fatal("%s: vasprintf failed", __func__);
 
497
 
 
498
        debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : "");
 
499
        free(out);
 
500
        if (buf == NULL)
 
501
                return;
 
502
 
 
503
        *h = '\0';
 
504
        for (i = j = 0; i < len; i++) {
 
505
                snprintf(h + j, sizeof(h) - j, "%02x", buf[i]);
 
506
                j += 2;
 
507
                if (j >= sizeof(h) - 1 || i == len - 1) {
 
508
                        debug3("    %s", h);
 
509
                        *h = '\0';
 
510
                        j = 0;
 
511
                }
 
512
        }
 
513
}
 
514
 
 
515
/*
 
516
 * Construct a MODP group from hex strings p (which must be a safe
 
517
 * prime) and g, automatically calculating subgroup q as (p / 2)
 
518
 */
 
519
struct modp_group *
 
520
modp_group_from_g_and_safe_p(const char *grp_g, const char *grp_p)
 
521
{
 
522
        struct modp_group *ret;
 
523
 
 
524
        ret = xmalloc(sizeof(*ret));
 
525
        ret->p = ret->q = ret->g = NULL;
 
526
        if (BN_hex2bn(&ret->p, grp_p) == 0 ||
 
527
            BN_hex2bn(&ret->g, grp_g) == 0)
 
528
                fatal("%s: BN_hex2bn", __func__);
 
529
        /* Subgroup order is p/2 (p is a safe prime) */
 
530
        if ((ret->q = BN_new()) == NULL)
 
531
                fatal("%s: BN_new", __func__);
 
532
        if (BN_rshift1(ret->q, ret->p) != 1)
 
533
                fatal("%s: BN_rshift1", __func__);
 
534
 
 
535
        return ret;
 
536
}
 
537
 
 
538
void
 
539
modp_group_free(struct modp_group *grp)
 
540
{
 
541
        if (grp->g != NULL)
 
542
                BN_clear_free(grp->g);
 
543
        if (grp->p != NULL)
 
544
                BN_clear_free(grp->p);
 
545
        if (grp->q != NULL)
 
546
                BN_clear_free(grp->q);
 
547
        bzero(grp, sizeof(*grp));
 
548
        xfree(grp);
 
549
}
 
550
 
 
551
/* main() function for self-test */
 
552
 
314
553
#ifdef SCHNORR_MAIN
315
554
static void
316
555
schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q,
328
567
 
329
568
        if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1)
330
569
                fatal("%s: g_x", __func__);
331
 
        if (schnorr_sign(grp_p, grp_q, grp_g, x, g_x, "junk", 4, &sig, &siglen))
 
570
        if (schnorr_sign_buf(grp_p, grp_q, grp_g, x, g_x, "junk", 4,
 
571
            &sig, &siglen))
332
572
                fatal("%s: schnorr_sign", __func__);
333
 
        if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "junk", 4,
 
573
        if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
334
574
            sig, siglen) != 1)
335
575
                fatal("%s: verify fail", __func__);
336
 
        if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "JUNK", 4,
 
576
        if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "JUNK", 4,
337
577
            sig, siglen) != 0)
338
578
                fatal("%s: verify should have failed (bad ID)", __func__);
339
579
        sig[4] ^= 1;
340
 
        if (schnorr_verify(grp_p, grp_q, grp_g, g_x, "junk", 4,
 
580
        if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
341
581
            sig, siglen) != 0)
342
582
                fatal("%s: verify should have failed (bit error)", __func__);
343
583
        xfree(sig);
349
589
schnorr_selftest(void)
350
590
{
351
591
        BIGNUM *x;
352
 
        struct jpake_group *grp;
 
592
        struct modp_group *grp;
353
593
        u_int i;
354
594
        char *hh;
355
595