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