11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: auth2-jpake.c,v 1.4 2010/08/31 11:54:45 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2008 Damien Miller.  All rights reserved.
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Server side of zero-knowledge password auth using J-PAKE protocol
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * as described in:
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 16th Workshop on Security Protocols, Cambridge, April 2008
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/param.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <login_cap.h>
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/bn.h>
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/evp.h>
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh2.h"
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h"
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "hostfile.h"
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth.h"
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h"
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "packet.h"
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "dispatch.h"
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "servconf.h"
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "auth-options.h"
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "canohost.h"
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef GSSAPI
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-gss.h"
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "monitor_wrap.h"
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "schnorr.h"
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "jpake.h"
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * XXX options->permit_empty_passwd (at the moment, they will be refused
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * anyway because they will mismatch on fake salt.
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Dispatch handlers */
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void input_userauth_jpake_client_step1(int, u_int32_t, void *);
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void input_userauth_jpake_client_step2(int, u_int32_t, void *);
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void input_userauth_jpake_client_confirm(int, u_int32_t, void *);
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int auth2_jpake_start(Authctxt *);
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* import */
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern ServerOptions options;
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern u_char *session_id2;
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodextern u_int session_id2_len;
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Attempt J-PAKE authentication.
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooduserauth_jpake(Authctxt *authctxt)
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int authenticated = 0;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("jpake-01@openssh.com requested");
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->user != NULL) {
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (authctxt->jpake_ctx == NULL)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			authctxt->jpake_ctx = jpake_new();
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (options.zero_knowledge_password_authentication)
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			authenticated = auth2_jpake_start(authctxt);
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return authenticated;
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodAuthmethod method_jpake = {
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	"jpake-01@openssh.com",
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	userauth_jpake,
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	&options.zero_knowledge_password_authentication
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Clear context and callbacks */
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth2_jpake_stop(Authctxt *authctxt)
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* unregister callbacks */
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->jpake_ctx != NULL) {
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		jpake_free(authctxt->jpake_ctx);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authctxt->jpake_ctx = NULL;
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvalid_crypt_salt(int c)
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c >= 'A' && c <= 'Z')
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c >= 'a' && c <= 'z')
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (c >= '.' && c <= '9')
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 1;
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Derive fake salt as H(username || first_private_host_key)
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * This provides relatively stable fake salts for non-existent
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * users and avoids the jpake method becoming an account validity
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * oracle.
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodderive_rawsalt(const char *username, u_char *rawsalt, u_int len)
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *digest;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int digest_len;
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Buffer b;
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Key *k;
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_init(&b);
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_put_cstring(&b, username);
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((k = get_hostkey_by_index(0)) == NULL ||
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (k->flags & KEY_FLAG_EXT))
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: no hostkeys", __func__);
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (k->type) {
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA1:
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_RSA:
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->rsa->p == NULL || k->rsa->q == NULL)
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: RSA key missing p and/or q", __func__);
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, k->rsa->p);
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, k->rsa->q);
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_DSA:
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (k->dsa->priv_key == NULL)
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: DSA key missing priv_key", __func__);
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, k->dsa->priv_key);
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case KEY_ECDSA:
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			fatal("%s: ECDSA key missing priv_key", __func__);
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: unknown key type %d", __func__, k->type);
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &digest, &digest_len) != 0)
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: hash_buffer", __func__);
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	buffer_free(&b);
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (len > digest_len)
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: not enough bytes for rawsalt (want %u have %u)",
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    __func__, len, digest_len);
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memcpy(rawsalt, digest, len);
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(digest, digest_len);
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(digest);
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ASCII an integer [0, 64) for inclusion in a password/salt */
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpw_encode64(u_int i64)
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	const u_char e64[] =
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return e64[i64 % 64];
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Generate ASCII salt bytes for user */
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic char *
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmakesalt(u_int want, const char *user)
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char rawsalt[32];
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	static char ret[33];
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int i;
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (want > sizeof(ret) - 1)
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: want %u", __func__, want);
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	derive_rawsalt(user, rawsalt, sizeof(rawsalt));
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(ret, sizeof(ret));
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	for (i = 0; i < want; i++)
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ret[i] = pw_encode64(rawsalt[i]);
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(rawsalt, sizeof(rawsalt));
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Select the system's default password hashing scheme and generate
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * a stable fake salt under it for use by a non-existent account.
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Prevents jpake method being used to infer the validity of accounts.
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodfake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme)
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *rounds_s, *style;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long long rounds;
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	login_cap_t *lc;
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL &&
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (lc = login_getclass(NULL)) == NULL)
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: login_getclass failed", __func__);
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	style = login_getcapstr(lc, "localcipher", NULL, NULL);
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (style == NULL)
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		style = xstrdup("blowfish,6");
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	login_close(lc);
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((rounds_s = strchr(style, ',')) != NULL)
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*rounds_s++ = '\0';
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	rounds = strtonum(rounds_s, 1, 1<<31, NULL);
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (strcmp(style, "md5") == 0) {
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user));
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*scheme = xstrdup("md5");
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(style, "old") == 0) {
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*salt = xstrdup(makesalt(2, authctxt->user));
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*scheme = xstrdup("crypt");
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else if (strcmp(style, "newsalt") == 0) {
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rounds = MAX(rounds, 7250);
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rounds = MIN(rounds, (1<<24) - 1);
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xasprintf(salt, "_%c%c%c%c%s",
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pw_encode64(rounds), pw_encode64(rounds >> 6),
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    pw_encode64(rounds >> 12), pw_encode64(rounds >> 18),
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    makesalt(4, authctxt->user));
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*scheme = xstrdup("crypt-extended");
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Default to blowfish */
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rounds = MAX(rounds, 3);
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		rounds = MIN(rounds, 31);
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xasprintf(salt, "$2a$%02lld$%s", rounds,
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    makesalt(22, authctxt->user));
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*scheme = xstrdup("bcrypt");
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(style);
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: fake %s salt for user %s: %s",
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    __func__, *scheme, authctxt->user, *salt);
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Fetch password hashing scheme, password salt and derive shared secret
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * for user. If user does not exist, a fake but stable and user-unique
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * salt will be returned.
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood    char **hash_scheme, char **salt)
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *cp;
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *secret;
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int secret_len, salt_len;
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE_DEBUG
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: valid %d pw %.5s...", __func__,
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    authctxt->valid, authctxt->pw->pw_passwd);
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*salt = NULL;
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*hash_scheme = NULL;
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (authctxt->valid) {
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 &&
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strlen(authctxt->pw->pw_passwd) > 28) {
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * old-variant bcrypt:
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 *     "$2$", 2 digit rounds, "$", 22 bytes salt
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			salt_len = 3 + 2 + 1 + 22 + 1;
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*salt = xmalloc(salt_len);
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*hash_scheme = xstrdup("bcrypt");
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 &&
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strlen(authctxt->pw->pw_passwd) > 29) {
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * current-variant bcrypt:
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 *     "$2a$", 2 digit rounds, "$", 22 bytes salt
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			salt_len = 4 + 2 + 1 + 22 + 1;
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*salt = xmalloc(salt_len);
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*hash_scheme = xstrdup("bcrypt");
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 &&
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strlen(authctxt->pw->pw_passwd) > 5) {
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * md5crypt:
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 *     "$1$", salt until "$"
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cp = strchr(authctxt->pw->pw_passwd + 3, '$');
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (cp != NULL) {
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				salt_len = (cp - authctxt->pw->pw_passwd) + 1;
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*salt = xmalloc(salt_len);
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				strlcpy(*salt, authctxt->pw->pw_passwd,
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    salt_len);
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				*hash_scheme = xstrdup("md5crypt");
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 &&
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strlen(authctxt->pw->pw_passwd) > 9) {
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * BSDI extended crypt:
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 *     "_", 4 digits count, 4 chars salt
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			salt_len = 1 + 4 + 4 + 1;
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*salt = xmalloc(salt_len);
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*hash_scheme = xstrdup("crypt-extended");
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (strlen(authctxt->pw->pw_passwd) == 13  &&
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    valid_crypt_salt(authctxt->pw->pw_passwd[0]) &&
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    valid_crypt_salt(authctxt->pw->pw_passwd[1])) {
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/*
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 * traditional crypt:
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 *     2 chars salt
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			 */
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			salt_len = 2 + 1;
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*salt = xmalloc(salt_len);
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			*hash_scheme = xstrdup("crypt");
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*salt == NULL) {
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			debug("%s: unrecognised crypt scheme for user %s",
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, authctxt->pw->pw_name);
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (*salt == NULL)
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fake_salt_and_scheme(authctxt, salt, hash_scheme);
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (hash_buffer(authctxt->pw->pw_passwd,
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    strlen(authctxt->pw->pw_passwd), EVP_sha256(),
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &secret, &secret_len) != 0)
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: hash_buffer", __func__);
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL)
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_bin2bn (secret)", __func__);
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef JPAKE_DEBUG
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: salt = %s (len %u)", __func__,
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    *salt, (u_int)strlen(*salt));
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug3("%s: scheme = %s", __func__, *hash_scheme);
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	JPAKE_DEBUG_BN((*s, "%s: s = ", __func__));
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(secret, secret_len);
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(secret);
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Begin authentication attempt.
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Note, sets authctxt->postponed while in subprotocol
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodauth2_jpake_start(Authctxt *authctxt)
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->jpake_ctx;
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x3_proof, *x4_proof;
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x3_proof_len, x4_proof_len;
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *salt, *hash_scheme;
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("%s: start", __func__);
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	PRIVSEP(jpake_step1(pctx->grp,
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->server_id, &pctx->server_id_len,
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x3_proof, &x3_proof_len,
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x4_proof, &x4_proof_len));
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s,
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &hash_scheme, &salt));
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1);
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(hash_scheme);
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_cstring(salt);
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(pctx->server_id, pctx->server_id_len);
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->g_x3);
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->g_x4);
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x3_proof, x3_proof_len);
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x4_proof, x4_proof_len);
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(hash_scheme, strlen(hash_scheme));
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(salt, strlen(salt));
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(hash_scheme);
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(salt);
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x3_proof, x3_proof_len);
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x4_proof, x4_proof_len);
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x3_proof);
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x4_proof);
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect step 1 packet from peer */
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1,
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_client_step1);
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->postponed = 1;
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt)
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->jpake_ctx;
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x1_proof, *x2_proof, *x4_s_proof;
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fetch step 1 values */
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pctx->g_x1 = BN_new()) == NULL ||
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    (pctx->g_x2 = BN_new()) == NULL)
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new", __func__);
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pctx->client_id = packet_get_string(&pctx->client_id_len);
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->g_x1);
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->g_x2);
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x1_proof = packet_get_string(&x1_proof_len);
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x2_proof = packet_get_string(&x2_proof_len);
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->g_x1, pctx->g_x2, pctx->x4,
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->client_id, pctx->client_id_len,
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->server_id, pctx->server_id_len,
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x1_proof, x1_proof_len,
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x2_proof, x2_proof_len,
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->b,
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &x4_s_proof, &x4_s_proof_len));
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x1_proof, x1_proof_len);
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x2_proof, x2_proof_len);
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x1_proof);
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x2_proof);
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send values for step 2 */
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2);
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_bignum2(pctx->b);
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(x4_s_proof, x4_s_proof_len);
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x4_s_proof, x4_s_proof_len);
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x4_s_proof);
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect step 2 packet from peer */
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2,
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_client_step2);
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt)
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->jpake_ctx;
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_char *x2_s_proof;
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int x2_s_proof_len;
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((pctx->a = BN_new()) == NULL)
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("%s: BN_new", __func__);
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Fetch step 2 values */
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_get_bignum2(pctx->a);
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	x2_s_proof = packet_get_string(&x2_s_proof_len);
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
5011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Derive shared key and calculate confirmation hash */
5031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
5041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
5051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->server_id, pctx->server_id_len,
5061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->client_id, pctx->client_id_len,
5071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    session_id2, session_id2_len,
5081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    x2_s_proof, x2_s_proof_len,
5091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->k,
5101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len));
5111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	bzero(x2_s_proof, x2_s_proof_len);
5131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(x2_s_proof);
5141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
5161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
5171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Send key confirmation proof */
5191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM);
5201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
5211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_send();
5221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_write_wait();
5231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Expect confirmation from peer */
5251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM,
5261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    input_userauth_jpake_client_confirm);
5271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* ARGSUSED */
5301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void
5311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodinput_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
5321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
5331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	Authctxt *authctxt = ctxt;
5341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct jpake_ctx *pctx = authctxt->jpake_ctx;
5351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int authenticated = 0;
5361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Disable this message */
5381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
5391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len);
5411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	packet_check_eom();
5421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!use_privsep)
5441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
5451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Verify expected confirmation hash */
5471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (PRIVSEP(jpake_check_confirm(pctx->k,
5481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->client_id, pctx->client_id_len,
5491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    session_id2, session_id2_len,
5501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1)
5511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		authenticated = authctxt->valid ? 1 : 0;
5521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
5531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug("%s: confirmation mismatch", __func__);
5541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* done */
5561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->postponed = 0;
5571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	jpake_free(authctxt->jpake_ctx);
5581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	authctxt->jpake_ctx = NULL;
5591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	userauth_finish(authctxt, authenticated, method_jpake.name);
5601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
5611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
5621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* JPAKE */
5631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
564