[BACK]Return to auth2-jpake.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/auth2-jpake.c, Revision 1.5

1.5     ! djm         1: /* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */
1.1       djm         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:  * Server side 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:
1.2       dtucker    28: #ifdef JPAKE
                     29:
1.1       djm        30: #include <sys/types.h>
                     31: #include <sys/param.h>
                     32:
                     33: #include <pwd.h>
                     34: #include <stdio.h>
                     35: #include <string.h>
                     36: #include <login_cap.h>
                     37:
                     38: #include <openssl/bn.h>
                     39: #include <openssl/evp.h>
                     40:
                     41: #include "xmalloc.h"
                     42: #include "ssh2.h"
                     43: #include "key.h"
                     44: #include "hostfile.h"
                     45: #include "auth.h"
                     46: #include "buffer.h"
                     47: #include "packet.h"
                     48: #include "dispatch.h"
                     49: #include "log.h"
                     50: #include "servconf.h"
                     51: #include "auth-options.h"
                     52: #include "canohost.h"
                     53: #ifdef GSSAPI
                     54: #include "ssh-gss.h"
                     55: #endif
                     56: #include "monitor_wrap.h"
                     57:
1.3       djm        58: #include "schnorr.h"
1.1       djm        59: #include "jpake.h"
                     60:
                     61: /*
                     62:  * XXX options->permit_empty_passwd (at the moment, they will be refused
                     63:  * anyway because they will mismatch on fake salt.
                     64:  */
                     65:
                     66: /* Dispatch handlers */
                     67: static void input_userauth_jpake_client_step1(int, u_int32_t, void *);
                     68: static void input_userauth_jpake_client_step2(int, u_int32_t, void *);
                     69: static void input_userauth_jpake_client_confirm(int, u_int32_t, void *);
                     70:
                     71: static int auth2_jpake_start(Authctxt *);
                     72:
                     73: /* import */
                     74: extern ServerOptions options;
                     75: extern u_char *session_id2;
                     76: extern u_int session_id2_len;
                     77:
                     78: /*
                     79:  * Attempt J-PAKE authentication.
                     80:  */
                     81: static int
                     82: userauth_jpake(Authctxt *authctxt)
                     83: {
                     84:        int authenticated = 0;
                     85:
                     86:        packet_check_eom();
                     87:
                     88:        debug("jpake-01@openssh.com requested");
                     89:
                     90:        if (authctxt->user != NULL) {
                     91:                if (authctxt->jpake_ctx == NULL)
                     92:                        authctxt->jpake_ctx = jpake_new();
                     93:                if (options.zero_knowledge_password_authentication)
                     94:                        authenticated = auth2_jpake_start(authctxt);
                     95:        }
                     96:
                     97:        return authenticated;
                     98: }
                     99:
                    100: Authmethod method_jpake = {
                    101:        "jpake-01@openssh.com",
                    102:        userauth_jpake,
                    103:        &options.zero_knowledge_password_authentication
                    104: };
                    105:
                    106: /* Clear context and callbacks */
                    107: void
                    108: auth2_jpake_stop(Authctxt *authctxt)
                    109: {
                    110:        /* unregister callbacks */
                    111:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
                    112:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
                    113:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
                    114:        if (authctxt->jpake_ctx != NULL) {
                    115:                jpake_free(authctxt->jpake_ctx);
                    116:                authctxt->jpake_ctx = NULL;
                    117:        }
                    118: }
                    119:
                    120: /* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */
                    121: static int
                    122: valid_crypt_salt(int c)
                    123: {
                    124:        if (c >= 'A' && c <= 'Z')
                    125:                return 1;
                    126:        if (c >= 'a' && c <= 'z')
                    127:                return 1;
                    128:        if (c >= '.' && c <= '9')
                    129:                return 1;
                    130:        return 0;
                    131: }
                    132:
                    133: /*
                    134:  * Derive fake salt as H(username || first_private_host_key)
                    135:  * This provides relatively stable fake salts for non-existent
                    136:  * users and avoids the jpake method becoming an account validity
                    137:  * oracle.
                    138:  */
                    139: static void
                    140: derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
                    141: {
                    142:        u_char *digest;
                    143:        u_int digest_len;
                    144:        Buffer b;
                    145:        Key *k;
                    146:
                    147:        buffer_init(&b);
                    148:        buffer_put_cstring(&b, username);
                    149:        if ((k = get_hostkey_by_index(0)) == NULL ||
                    150:            (k->flags & KEY_FLAG_EXT))
                    151:                fatal("%s: no hostkeys", __func__);
                    152:        switch (k->type) {
                    153:        case KEY_RSA1:
                    154:        case KEY_RSA:
                    155:                if (k->rsa->p == NULL || k->rsa->q == NULL)
                    156:                        fatal("%s: RSA key missing p and/or q", __func__);
                    157:                buffer_put_bignum2(&b, k->rsa->p);
                    158:                buffer_put_bignum2(&b, k->rsa->q);
                    159:                break;
                    160:        case KEY_DSA:
                    161:                if (k->dsa->priv_key == NULL)
                    162:                        fatal("%s: DSA key missing priv_key", __func__);
                    163:                buffer_put_bignum2(&b, k->dsa->priv_key);
1.4       djm       164:                break;
                    165:        case KEY_ECDSA:
                    166:                if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
                    167:                        fatal("%s: ECDSA key missing priv_key", __func__);
                    168:                buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
1.1       djm       169:                break;
                    170:        default:
                    171:                fatal("%s: unknown key type %d", __func__, k->type);
                    172:        }
                    173:        if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
                    174:            &digest, &digest_len) != 0)
                    175:                fatal("%s: hash_buffer", __func__);
                    176:        buffer_free(&b);
                    177:        if (len > digest_len)
                    178:                fatal("%s: not enough bytes for rawsalt (want %u have %u)",
                    179:                    __func__, len, digest_len);
                    180:        memcpy(rawsalt, digest, len);
                    181:        bzero(digest, digest_len);
                    182:        xfree(digest);
                    183: }
                    184:
                    185: /* ASCII an integer [0, 64) for inclusion in a password/salt */
                    186: static char
                    187: pw_encode64(u_int i64)
                    188: {
                    189:        const u_char e64[] =
                    190:            "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                    191:        return e64[i64 % 64];
                    192: }
                    193:
                    194: /* Generate ASCII salt bytes for user */
                    195: static char *
                    196: makesalt(u_int want, const char *user)
                    197: {
                    198:        u_char rawsalt[32];
                    199:        static char ret[33];
                    200:        u_int i;
                    201:
                    202:        if (want > sizeof(ret) - 1)
                    203:                fatal("%s: want %u", __func__, want);
                    204:
                    205:        derive_rawsalt(user, rawsalt, sizeof(rawsalt));
                    206:        bzero(ret, sizeof(ret));
                    207:        for (i = 0; i < want; i++)
                    208:                ret[i] = pw_encode64(rawsalt[i]);
                    209:        bzero(rawsalt, sizeof(rawsalt));
                    210:
                    211:        return ret;
                    212: }
                    213:
                    214: /*
                    215:  * Select the system's default password hashing scheme and generate
                    216:  * a stable fake salt under it for use by a non-existent account.
                    217:  * Prevents jpake method being used to infer the validity of accounts.
                    218:  */
                    219: static void
                    220: fake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme)
                    221: {
                    222:        char *rounds_s, *style;
                    223:        long long rounds;
                    224:        login_cap_t *lc;
                    225:
                    226:
                    227:        if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL &&
                    228:            (lc = login_getclass(NULL)) == NULL)
                    229:                fatal("%s: login_getclass failed", __func__);
                    230:        style = login_getcapstr(lc, "localcipher", NULL, NULL);
                    231:        if (style == NULL)
                    232:                style = xstrdup("blowfish,6");
                    233:        login_close(lc);
                    234:
                    235:        if ((rounds_s = strchr(style, ',')) != NULL)
                    236:                *rounds_s++ = '\0';
                    237:        rounds = strtonum(rounds_s, 1, 1<<31, NULL);
                    238:
                    239:        if (strcmp(style, "md5") == 0) {
                    240:                xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user));
                    241:                *scheme = xstrdup("md5");
                    242:        } else if (strcmp(style, "old") == 0) {
                    243:                *salt = xstrdup(makesalt(2, authctxt->user));
                    244:                *scheme = xstrdup("crypt");
                    245:        } else if (strcmp(style, "newsalt") == 0) {
                    246:                rounds = MAX(rounds, 7250);
                    247:                rounds = MIN(rounds, (1<<24) - 1);
                    248:                xasprintf(salt, "_%c%c%c%c%s",
                    249:                    pw_encode64(rounds), pw_encode64(rounds >> 6),
                    250:                    pw_encode64(rounds >> 12), pw_encode64(rounds >> 18),
                    251:                    makesalt(4, authctxt->user));
                    252:                *scheme = xstrdup("crypt-extended");
                    253:        } else {
                    254:                /* Default to blowfish */
                    255:                rounds = MAX(rounds, 3);
                    256:                rounds = MIN(rounds, 31);
                    257:                xasprintf(salt, "$2a$%02lld$%s", rounds,
                    258:                    makesalt(22, authctxt->user));
                    259:                *scheme = xstrdup("bcrypt");
                    260:        }
                    261:        xfree(style);
                    262:        debug3("%s: fake %s salt for user %s: %s",
                    263:            __func__, *scheme, authctxt->user, *salt);
                    264: }
                    265:
                    266: /*
                    267:  * Fetch password hashing scheme, password salt and derive shared secret
                    268:  * for user. If user does not exist, a fake but stable and user-unique
                    269:  * salt will be returned.
                    270:  */
                    271: void
                    272: auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
                    273:     char **hash_scheme, char **salt)
                    274: {
                    275:        char *cp;
                    276:        u_char *secret;
                    277:        u_int secret_len, salt_len;
                    278:
                    279: #ifdef JPAKE_DEBUG
                    280:        debug3("%s: valid %d pw %.5s...", __func__,
                    281:            authctxt->valid, authctxt->pw->pw_passwd);
                    282: #endif
                    283:
                    284:        *salt = NULL;
                    285:        *hash_scheme = NULL;
                    286:        if (authctxt->valid) {
                    287:                if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 &&
                    288:                    strlen(authctxt->pw->pw_passwd) > 28) {
                    289:                        /*
                    290:                         * old-variant bcrypt:
                    291:                         *     "$2$", 2 digit rounds, "$", 22 bytes salt
                    292:                         */
                    293:                        salt_len = 3 + 2 + 1 + 22 + 1;
                    294:                        *salt = xmalloc(salt_len);
                    295:                        strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
                    296:                        *hash_scheme = xstrdup("bcrypt");
                    297:                } else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 &&
                    298:                    strlen(authctxt->pw->pw_passwd) > 29) {
                    299:                        /*
                    300:                         * current-variant bcrypt:
                    301:                         *     "$2a$", 2 digit rounds, "$", 22 bytes salt
                    302:                         */
                    303:                        salt_len = 4 + 2 + 1 + 22 + 1;
                    304:                        *salt = xmalloc(salt_len);
                    305:                        strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
                    306:                        *hash_scheme = xstrdup("bcrypt");
                    307:                } else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 &&
                    308:                    strlen(authctxt->pw->pw_passwd) > 5) {
                    309:                        /*
                    310:                         * md5crypt:
                    311:                         *     "$1$", salt until "$"
                    312:                         */
                    313:                        cp = strchr(authctxt->pw->pw_passwd + 3, '$');
                    314:                        if (cp != NULL) {
                    315:                                salt_len = (cp - authctxt->pw->pw_passwd) + 1;
                    316:                                *salt = xmalloc(salt_len);
                    317:                                strlcpy(*salt, authctxt->pw->pw_passwd,
                    318:                                    salt_len);
                    319:                                *hash_scheme = xstrdup("md5crypt");
                    320:                        }
                    321:                } else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 &&
                    322:                    strlen(authctxt->pw->pw_passwd) > 9) {
                    323:                        /*
                    324:                         * BSDI extended crypt:
                    325:                         *     "_", 4 digits count, 4 chars salt
                    326:                         */
                    327:                        salt_len = 1 + 4 + 4 + 1;
                    328:                        *salt = xmalloc(salt_len);
                    329:                        strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
                    330:                        *hash_scheme = xstrdup("crypt-extended");
                    331:                } else if (strlen(authctxt->pw->pw_passwd) == 13  &&
                    332:                    valid_crypt_salt(authctxt->pw->pw_passwd[0]) &&
                    333:                    valid_crypt_salt(authctxt->pw->pw_passwd[1])) {
                    334:                        /*
                    335:                         * traditional crypt:
                    336:                         *     2 chars salt
                    337:                         */
                    338:                        salt_len = 2 + 1;
                    339:                        *salt = xmalloc(salt_len);
                    340:                        strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
                    341:                        *hash_scheme = xstrdup("crypt");
                    342:                }
                    343:                if (*salt == NULL) {
                    344:                        debug("%s: unrecognised crypt scheme for user %s",
                    345:                            __func__, authctxt->pw->pw_name);
                    346:                }
                    347:        }
                    348:        if (*salt == NULL)
                    349:                fake_salt_and_scheme(authctxt, salt, hash_scheme);
                    350:
                    351:        if (hash_buffer(authctxt->pw->pw_passwd,
                    352:            strlen(authctxt->pw->pw_passwd), EVP_sha256(),
                    353:            &secret, &secret_len) != 0)
                    354:                fatal("%s: hash_buffer", __func__);
                    355:        if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL)
                    356:                fatal("%s: BN_bin2bn (secret)", __func__);
                    357: #ifdef JPAKE_DEBUG
                    358:        debug3("%s: salt = %s (len %u)", __func__,
                    359:            *salt, (u_int)strlen(*salt));
                    360:        debug3("%s: scheme = %s", __func__, *hash_scheme);
                    361:        JPAKE_DEBUG_BN((*s, "%s: s = ", __func__));
                    362: #endif
                    363:        bzero(secret, secret_len);
                    364:        xfree(secret);
                    365: }
                    366:
                    367: /*
1.3       djm       368:  * Begin authentication attempt.
1.1       djm       369:  * Note, sets authctxt->postponed while in subprotocol
                    370:  */
                    371: static int
                    372: auth2_jpake_start(Authctxt *authctxt)
                    373: {
                    374:        struct jpake_ctx *pctx = authctxt->jpake_ctx;
                    375:        u_char *x3_proof, *x4_proof;
                    376:        u_int x3_proof_len, x4_proof_len;
                    377:        char *salt, *hash_scheme;
                    378:
                    379:        debug("%s: start", __func__);
                    380:
                    381:        PRIVSEP(jpake_step1(pctx->grp,
                    382:            &pctx->server_id, &pctx->server_id_len,
                    383:            &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
                    384:            &x3_proof, &x3_proof_len,
                    385:            &x4_proof, &x4_proof_len));
                    386:
                    387:        PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s,
                    388:            &hash_scheme, &salt));
                    389:
                    390:        if (!use_privsep)
                    391:                JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
                    392:
                    393:        packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1);
                    394:        packet_put_cstring(hash_scheme);
                    395:        packet_put_cstring(salt);
                    396:        packet_put_string(pctx->server_id, pctx->server_id_len);
                    397:        packet_put_bignum2(pctx->g_x3);
                    398:        packet_put_bignum2(pctx->g_x4);
                    399:        packet_put_string(x3_proof, x3_proof_len);
                    400:        packet_put_string(x4_proof, x4_proof_len);
                    401:        packet_send();
                    402:        packet_write_wait();
                    403:
                    404:        bzero(hash_scheme, strlen(hash_scheme));
                    405:        bzero(salt, strlen(salt));
                    406:        xfree(hash_scheme);
                    407:        xfree(salt);
                    408:        bzero(x3_proof, x3_proof_len);
                    409:        bzero(x4_proof, x4_proof_len);
                    410:        xfree(x3_proof);
                    411:        xfree(x4_proof);
                    412:
                    413:        /* Expect step 1 packet from peer */
                    414:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1,
                    415:            input_userauth_jpake_client_step1);
                    416:
                    417:        authctxt->postponed = 1;
                    418:        return 0;
                    419: }
                    420:
                    421: /* ARGSUSED */
                    422: static void
                    423: input_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt)
                    424: {
                    425:        Authctxt *authctxt = ctxt;
                    426:        struct jpake_ctx *pctx = authctxt->jpake_ctx;
                    427:        u_char *x1_proof, *x2_proof, *x4_s_proof;
                    428:        u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
                    429:
                    430:        /* Disable this message */
                    431:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
                    432:
                    433:        /* Fetch step 1 values */
                    434:        if ((pctx->g_x1 = BN_new()) == NULL ||
                    435:            (pctx->g_x2 = BN_new()) == NULL)
                    436:                fatal("%s: BN_new", __func__);
                    437:        pctx->client_id = packet_get_string(&pctx->client_id_len);
                    438:        packet_get_bignum2(pctx->g_x1);
                    439:        packet_get_bignum2(pctx->g_x2);
                    440:        x1_proof = packet_get_string(&x1_proof_len);
                    441:        x2_proof = packet_get_string(&x2_proof_len);
                    442:        packet_check_eom();
                    443:
                    444:        if (!use_privsep)
                    445:                JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
                    446:
                    447:        PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
                    448:            pctx->g_x1, pctx->g_x2, pctx->x4,
                    449:            pctx->client_id, pctx->client_id_len,
                    450:            pctx->server_id, pctx->server_id_len,
                    451:            x1_proof, x1_proof_len,
                    452:            x2_proof, x2_proof_len,
                    453:            &pctx->b,
                    454:            &x4_s_proof, &x4_s_proof_len));
                    455:
                    456:        bzero(x1_proof, x1_proof_len);
                    457:        bzero(x2_proof, x2_proof_len);
                    458:        xfree(x1_proof);
                    459:        xfree(x2_proof);
                    460:
                    461:        if (!use_privsep)
                    462:                JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
                    463:
                    464:        /* Send values for step 2 */
                    465:        packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2);
                    466:        packet_put_bignum2(pctx->b);
                    467:        packet_put_string(x4_s_proof, x4_s_proof_len);
                    468:        packet_send();
                    469:        packet_write_wait();
                    470:
                    471:        bzero(x4_s_proof, x4_s_proof_len);
                    472:        xfree(x4_s_proof);
                    473:
                    474:        /* Expect step 2 packet from peer */
                    475:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2,
                    476:            input_userauth_jpake_client_step2);
                    477: }
                    478:
                    479: /* ARGSUSED */
                    480: static void
                    481: input_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt)
                    482: {
                    483:        Authctxt *authctxt = ctxt;
                    484:        struct jpake_ctx *pctx = authctxt->jpake_ctx;
                    485:        u_char *x2_s_proof;
                    486:        u_int x2_s_proof_len;
                    487:
                    488:        /* Disable this message */
                    489:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
                    490:
                    491:        if ((pctx->a = BN_new()) == NULL)
                    492:                fatal("%s: BN_new", __func__);
                    493:
                    494:        /* Fetch step 2 values */
                    495:        packet_get_bignum2(pctx->a);
                    496:        x2_s_proof = packet_get_string(&x2_s_proof_len);
                    497:        packet_check_eom();
                    498:
                    499:        if (!use_privsep)
                    500:                JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
                    501:
                    502:        /* Derive shared key and calculate confirmation hash */
                    503:        PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
                    504:            pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
                    505:            pctx->server_id, pctx->server_id_len,
                    506:            pctx->client_id, pctx->client_id_len,
                    507:            session_id2, session_id2_len,
                    508:            x2_s_proof, x2_s_proof_len,
                    509:            &pctx->k,
                    510:            &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len));
                    511:
                    512:        bzero(x2_s_proof, x2_s_proof_len);
                    513:        xfree(x2_s_proof);
                    514:
                    515:        if (!use_privsep)
                    516:                JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
                    517:
                    518:        /* Send key confirmation proof */
                    519:        packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM);
                    520:        packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
                    521:        packet_send();
                    522:        packet_write_wait();
                    523:
                    524:        /* Expect confirmation from peer */
                    525:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM,
                    526:            input_userauth_jpake_client_confirm);
                    527: }
                    528:
                    529: /* ARGSUSED */
                    530: static void
                    531: input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
                    532: {
                    533:        Authctxt *authctxt = ctxt;
                    534:        struct jpake_ctx *pctx = authctxt->jpake_ctx;
                    535:        int authenticated = 0;
                    536:
                    537:        /* Disable this message */
                    538:        dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
                    539:
                    540:        pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len);
                    541:        packet_check_eom();
                    542:
                    543:        if (!use_privsep)
                    544:                JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
                    545:
                    546:        /* Verify expected confirmation hash */
                    547:        if (PRIVSEP(jpake_check_confirm(pctx->k,
                    548:            pctx->client_id, pctx->client_id_len,
                    549:            session_id2, session_id2_len,
                    550:            pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1)
                    551:                authenticated = authctxt->valid ? 1 : 0;
                    552:        else
                    553:                debug("%s: confirmation mismatch", __func__);
                    554:
                    555:        /* done */
                    556:        authctxt->postponed = 0;
                    557:        jpake_free(authctxt->jpake_ctx);
                    558:        authctxt->jpake_ctx = NULL;
1.5     ! djm       559:        userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
1.1       djm       560: }
                    561:
                    562: #endif /* JPAKE */
                    563: