diff options
author | Damien Miller <djm@mindrot.org> | 2014-02-04 01:12:56 +0100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-02-04 01:12:56 +0100 |
commit | 7cc194f70d4a5ec9a82d19422eaf18db4a6624c6 (patch) | |
tree | 8bf6b25f93b3ee74dc184349a45125738e89df5b | |
parent | - djm@cvs.openbsd.org 2014/01/29 00:19:26 (diff) | |
download | openssh-7cc194f70d4a5ec9a82d19422eaf18db4a6624c6.tar.xz openssh-7cc194f70d4a5ec9a82d19422eaf18db4a6624c6.zip |
- djm@cvs.openbsd.org 2014/01/29 06:18:35
[Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c]
[monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h]
[schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c]
remove experimental, never-enabled JPAKE code; ok markus@
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | auth.h | 6 | ||||
-rw-r--r-- | auth2-jpake.c | 563 | ||||
-rw-r--r-- | auth2.c | 11 | ||||
-rw-r--r-- | jpake.c | 456 | ||||
-rw-r--r-- | jpake.h | 114 | ||||
-rw-r--r-- | monitor.c | 226 | ||||
-rw-r--r-- | monitor.h | 7 | ||||
-rw-r--r-- | monitor_wrap.c | 165 | ||||
-rw-r--r-- | monitor_wrap.h | 22 | ||||
-rw-r--r-- | readconf.c | 17 | ||||
-rw-r--r-- | readconf.h | 3 | ||||
-rw-r--r-- | schnorr.c | 668 | ||||
-rw-r--r-- | schnorr.h | 60 | ||||
-rw-r--r-- | servconf.c | 21 | ||||
-rw-r--r-- | servconf.h | 4 | ||||
-rw-r--r-- | ssh2.h | 8 | ||||
-rw-r--r-- | sshconnect2.c | 293 |
19 files changed, 22 insertions, 2633 deletions
@@ -20,6 +20,11 @@ they are equivalent, but SUSv2 describes the latter as having undefined behaviour; from portable; ok dtucker (Id sync only; change is already in portable) + - djm@cvs.openbsd.org 2014/01/29 06:18:35 + [Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c] + [monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h] + [schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c] + remove experimental, never-enabled JPAKE code; ok markus@ 20140131 - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2) diff --git a/Makefile.in b/Makefile.in index 9443c92b0..28a8ec41b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -# $Id: Makefile.in,v 1.355 2014/02/04 00:07:14 djm Exp $ +# $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $ # uncomment if you run a non bourne compatable shell. Ie. csh #SHELL = @SH@ @@ -73,7 +73,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ + ssh-pkcs11.o krl.o smult_curve25519_ref.o \ kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ ssh-ed25519.o digest-openssl.o hmac.o \ sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o @@ -88,7 +88,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ auth.o auth1.o auth2.o auth-options.o session.o \ auth-chall.o auth2-chall.o groupaccess.o \ auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o \ monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ kexc25519s.o auth-krb5.o \ auth2-gss.o gss-serv.o gss-serv-krb5.o \ @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.76 2013/07/19 07:37:48 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -61,7 +61,6 @@ struct Authctxt { char *style; void *kbdintctxt; char *info; /* Extra info for next auth_log */ - void *jpake_ctx; #ifdef BSD_AUTH auth_session_t *as; #endif @@ -175,9 +174,6 @@ int bsdauth_respond(void *, u_int, char **); int skey_query(void *, char **, char **, u_int *, char ***, u_int **); int skey_respond(void *, u_int, char **); -void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **); -void auth2_jpake_stop(Authctxt *); - int allowed_user(struct passwd *); struct passwd * getpwnamallow(const char *user); diff --git a/auth2-jpake.c b/auth2-jpake.c deleted file mode 100644 index 78a6b8817..000000000 --- a/auth2-jpake.c +++ /dev/null @@ -1,563 +0,0 @@ -/* $OpenBSD: auth2-jpake.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ -/* - * Copyright (c) 2008 Damien Miller. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Server side of zero-knowledge password auth using J-PAKE protocol - * as described in: - * - * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling", - * 16th Workshop on Security Protocols, Cambridge, April 2008 - * - * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf - */ - -#ifdef JPAKE - -#include <sys/types.h> -#include <sys/param.h> - -#include <pwd.h> -#include <stdio.h> -#include <string.h> -#include <login_cap.h> - -#include <openssl/bn.h> -#include <openssl/evp.h> - -#include "xmalloc.h" -#include "ssh2.h" -#include "key.h" -#include "hostfile.h" -#include "auth.h" -#include "buffer.h" -#include "packet.h" -#include "dispatch.h" -#include "log.h" -#include "servconf.h" -#include "auth-options.h" -#include "canohost.h" -#ifdef GSSAPI -#include "ssh-gss.h" -#endif -#include "monitor_wrap.h" - -#include "schnorr.h" -#include "jpake.h" - -/* - * XXX options->permit_empty_passwd (at the moment, they will be refused - * anyway because they will mismatch on fake salt. - */ - -/* Dispatch handlers */ -static void input_userauth_jpake_client_step1(int, u_int32_t, void *); -static void input_userauth_jpake_client_step2(int, u_int32_t, void *); -static void input_userauth_jpake_client_confirm(int, u_int32_t, void *); - -static int auth2_jpake_start(Authctxt *); - -/* import */ -extern ServerOptions options; -extern u_char *session_id2; -extern u_int session_id2_len; - -/* - * Attempt J-PAKE authentication. - */ -static int -userauth_jpake(Authctxt *authctxt) -{ - int authenticated = 0; - - packet_check_eom(); - - debug("jpake-01@openssh.com requested"); - - if (authctxt->user != NULL) { - if (authctxt->jpake_ctx == NULL) - authctxt->jpake_ctx = jpake_new(); - if (options.zero_knowledge_password_authentication) - authenticated = auth2_jpake_start(authctxt); - } - - return authenticated; -} - -Authmethod method_jpake = { - "jpake-01@openssh.com", - userauth_jpake, - &options.zero_knowledge_password_authentication -}; - -/* Clear context and callbacks */ -void -auth2_jpake_stop(Authctxt *authctxt) -{ - /* unregister callbacks */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL); - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL); - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL); - if (authctxt->jpake_ctx != NULL) { - jpake_free(authctxt->jpake_ctx); - authctxt->jpake_ctx = NULL; - } -} - -/* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */ -static int -valid_crypt_salt(int c) -{ - if (c >= 'A' && c <= 'Z') - return 1; - if (c >= 'a' && c <= 'z') - return 1; - if (c >= '.' && c <= '9') - return 1; - return 0; -} - -/* - * Derive fake salt as H(username || first_private_host_key) - * This provides relatively stable fake salts for non-existent - * users and avoids the jpake method becoming an account validity - * oracle. - */ -static void -derive_rawsalt(const char *username, u_char *rawsalt, u_int len) -{ - u_char *digest; - u_int digest_len; - Buffer b; - Key *k; - - buffer_init(&b); - buffer_put_cstring(&b, username); - if ((k = get_hostkey_by_index(0)) == NULL || - (k->flags & KEY_FLAG_EXT)) - fatal("%s: no hostkeys", __func__); - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if (k->rsa->p == NULL || k->rsa->q == NULL) - fatal("%s: RSA key missing p and/or q", __func__); - buffer_put_bignum2(&b, k->rsa->p); - buffer_put_bignum2(&b, k->rsa->q); - break; - case KEY_DSA: - if (k->dsa->priv_key == NULL) - fatal("%s: DSA key missing priv_key", __func__); - buffer_put_bignum2(&b, k->dsa->priv_key); - break; - case KEY_ECDSA: - if (EC_KEY_get0_private_key(k->ecdsa) == NULL) - fatal("%s: ECDSA key missing priv_key", __func__); - buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa)); - break; - default: - fatal("%s: unknown key type %d", __func__, k->type); - } - if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(), - &digest, &digest_len) != 0) - fatal("%s: hash_buffer", __func__); - buffer_free(&b); - if (len > digest_len) - fatal("%s: not enough bytes for rawsalt (want %u have %u)", - __func__, len, digest_len); - memcpy(rawsalt, digest, len); - bzero(digest, digest_len); - free(digest); -} - -/* ASCII an integer [0, 64) for inclusion in a password/salt */ -static char -pw_encode64(u_int i64) -{ - const u_char e64[] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - return e64[i64 % 64]; -} - -/* Generate ASCII salt bytes for user */ -static char * -makesalt(u_int want, const char *user) -{ - u_char rawsalt[32]; - static char ret[33]; - u_int i; - - if (want > sizeof(ret) - 1) - fatal("%s: want %u", __func__, want); - - derive_rawsalt(user, rawsalt, sizeof(rawsalt)); - bzero(ret, sizeof(ret)); - for (i = 0; i < want; i++) - ret[i] = pw_encode64(rawsalt[i]); - bzero(rawsalt, sizeof(rawsalt)); - - return ret; -} - -/* - * Select the system's default password hashing scheme and generate - * a stable fake salt under it for use by a non-existent account. - * Prevents jpake method being used to infer the validity of accounts. - */ -static void -fake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme) -{ - char *rounds_s, *style; - long long rounds; - login_cap_t *lc; - - - if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL && - (lc = login_getclass(NULL)) == NULL) - fatal("%s: login_getclass failed", __func__); - style = login_getcapstr(lc, "localcipher", NULL, NULL); - if (style == NULL) - style = xstrdup("blowfish,6"); - login_close(lc); - - if ((rounds_s = strchr(style, ',')) != NULL) - *rounds_s++ = '\0'; - rounds = strtonum(rounds_s, 1, 1<<31, NULL); - - if (strcmp(style, "md5") == 0) { - xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user)); - *scheme = xstrdup("md5"); - } else if (strcmp(style, "old") == 0) { - *salt = xstrdup(makesalt(2, authctxt->user)); - *scheme = xstrdup("crypt"); - } else if (strcmp(style, "newsalt") == 0) { - rounds = MAX(rounds, 7250); - rounds = MIN(rounds, (1<<24) - 1); - xasprintf(salt, "_%c%c%c%c%s", - pw_encode64(rounds), pw_encode64(rounds >> 6), - pw_encode64(rounds >> 12), pw_encode64(rounds >> 18), - makesalt(4, authctxt->user)); - *scheme = xstrdup("crypt-extended"); - } else { - /* Default to blowfish */ - rounds = MAX(rounds, 3); - rounds = MIN(rounds, 31); - xasprintf(salt, "$2a$%02lld$%s", rounds, - makesalt(22, authctxt->user)); - *scheme = xstrdup("bcrypt"); - } - free(style); - debug3("%s: fake %s salt for user %s: %s", - __func__, *scheme, authctxt->user, *salt); -} - -/* - * Fetch password hashing scheme, password salt and derive shared secret - * for user. If user does not exist, a fake but stable and user-unique - * salt will be returned. - */ -void -auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s, - char **hash_scheme, char **salt) -{ - char *cp; - u_char *secret; - u_int secret_len, salt_len; - -#ifdef JPAKE_DEBUG - debug3("%s: valid %d pw %.5s...", __func__, - authctxt->valid, authctxt->pw->pw_passwd); -#endif - - *salt = NULL; - *hash_scheme = NULL; - if (authctxt->valid) { - if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 && - strlen(authctxt->pw->pw_passwd) > 28) { - /* - * old-variant bcrypt: - * "$2$", 2 digit rounds, "$", 22 bytes salt - */ - salt_len = 3 + 2 + 1 + 22 + 1; - *salt = xmalloc(salt_len); - strlcpy(*salt, authctxt->pw->pw_passwd, salt_len); - *hash_scheme = xstrdup("bcrypt"); - } else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 && - strlen(authctxt->pw->pw_passwd) > 29) { - /* - * current-variant bcrypt: - * "$2a$", 2 digit rounds, "$", 22 bytes salt - */ - salt_len = 4 + 2 + 1 + 22 + 1; - *salt = xmalloc(salt_len); - strlcpy(*salt, authctxt->pw->pw_passwd, salt_len); - *hash_scheme = xstrdup("bcrypt"); - } else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 && - strlen(authctxt->pw->pw_passwd) > 5) { - /* - * md5crypt: - * "$1$", salt until "$" - */ - cp = strchr(authctxt->pw->pw_passwd + 3, '$'); - if (cp != NULL) { - salt_len = (cp - authctxt->pw->pw_passwd) + 1; - *salt = xmalloc(salt_len); - strlcpy(*salt, authctxt->pw->pw_passwd, - salt_len); - *hash_scheme = xstrdup("md5crypt"); - } - } else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 && - strlen(authctxt->pw->pw_passwd) > 9) { - /* - * BSDI extended crypt: - * "_", 4 digits count, 4 chars salt - */ - salt_len = 1 + 4 + 4 + 1; - *salt = xmalloc(salt_len); - strlcpy(*salt, authctxt->pw->pw_passwd, salt_len); - *hash_scheme = xstrdup("crypt-extended"); - } else if (strlen(authctxt->pw->pw_passwd) == 13 && - valid_crypt_salt(authctxt->pw->pw_passwd[0]) && - valid_crypt_salt(authctxt->pw->pw_passwd[1])) { - /* - * traditional crypt: - * 2 chars salt - */ - salt_len = 2 + 1; - *salt = xmalloc(salt_len); - strlcpy(*salt, authctxt->pw->pw_passwd, salt_len); - *hash_scheme = xstrdup("crypt"); - } - if (*salt == NULL) { - debug("%s: unrecognised crypt scheme for user %s", - __func__, authctxt->pw->pw_name); - } - } - if (*salt == NULL) - fake_salt_and_scheme(authctxt, salt, hash_scheme); - - if (hash_buffer(authctxt->pw->pw_passwd, - strlen(authctxt->pw->pw_passwd), EVP_sha256(), - &secret, &secret_len) != 0) - fatal("%s: hash_buffer", __func__); - if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL) - fatal("%s: BN_bin2bn (secret)", __func__); -#ifdef JPAKE_DEBUG - debug3("%s: salt = %s (len %u)", __func__, - *salt, (u_int)strlen(*salt)); - debug3("%s: scheme = %s", __func__, *hash_scheme); - JPAKE_DEBUG_BN((*s, "%s: s = ", __func__)); -#endif - bzero(secret, secret_len); - free(secret); -} - -/* - * Begin authentication attempt. - * Note, sets authctxt->postponed while in subprotocol - */ -static int -auth2_jpake_start(Authctxt *authctxt) -{ - struct jpake_ctx *pctx = authctxt->jpake_ctx; - u_char *x3_proof, *x4_proof; - u_int x3_proof_len, x4_proof_len; - char *salt, *hash_scheme; - - debug("%s: start", __func__); - - PRIVSEP(jpake_step1(pctx->grp, - &pctx->server_id, &pctx->server_id_len, - &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4, - &x3_proof, &x3_proof_len, - &x4_proof, &x4_proof_len)); - - PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s, - &hash_scheme, &salt)); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__)); - - packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1); - packet_put_cstring(hash_scheme); - packet_put_cstring(salt); - packet_put_string(pctx->server_id, pctx->server_id_len); - packet_put_bignum2(pctx->g_x3); - packet_put_bignum2(pctx->g_x4); - packet_put_string(x3_proof, x3_proof_len); - packet_put_string(x4_proof, x4_proof_len); - packet_send(); - packet_write_wait(); - - bzero(hash_scheme, strlen(hash_scheme)); - bzero(salt, strlen(salt)); - free(hash_scheme); - free(salt); - bzero(x3_proof, x3_proof_len); - bzero(x4_proof, x4_proof_len); - free(x3_proof); - free(x4_proof); - - /* Expect step 1 packet from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, - input_userauth_jpake_client_step1); - - authctxt->postponed = 1; - return 0; -} - -/* ARGSUSED */ -static void -input_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->jpake_ctx; - u_char *x1_proof, *x2_proof, *x4_s_proof; - u_int x1_proof_len, x2_proof_len, x4_s_proof_len; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL); - - /* Fetch step 1 values */ - if ((pctx->g_x1 = BN_new()) == NULL || - (pctx->g_x2 = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - pctx->client_id = packet_get_string(&pctx->client_id_len); - packet_get_bignum2(pctx->g_x1); - packet_get_bignum2(pctx->g_x2); - x1_proof = packet_get_string(&x1_proof_len); - x2_proof = packet_get_string(&x2_proof_len); - packet_check_eom(); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__)); - - PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3, - pctx->g_x1, pctx->g_x2, pctx->x4, - pctx->client_id, pctx->client_id_len, - pctx->server_id, pctx->server_id_len, - x1_proof, x1_proof_len, - x2_proof, x2_proof_len, - &pctx->b, - &x4_s_proof, &x4_s_proof_len)); - - bzero(x1_proof, x1_proof_len); - bzero(x2_proof, x2_proof_len); - free(x1_proof); - free(x2_proof); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__)); - - /* Send values for step 2 */ - packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2); - packet_put_bignum2(pctx->b); - packet_put_string(x4_s_proof, x4_s_proof_len); - packet_send(); - packet_write_wait(); - - bzero(x4_s_proof, x4_s_proof_len); - free(x4_s_proof); - - /* Expect step 2 packet from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, - input_userauth_jpake_client_step2); -} - -/* ARGSUSED */ -static void -input_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->jpake_ctx; - u_char *x2_s_proof; - u_int x2_s_proof_len; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL); - - if ((pctx->a = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - /* Fetch step 2 values */ - packet_get_bignum2(pctx->a); - x2_s_proof = packet_get_string(&x2_s_proof_len); - packet_check_eom(); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__)); - - /* Derive shared key and calculate confirmation hash */ - PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a, - pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, - pctx->server_id, pctx->server_id_len, - pctx->client_id, pctx->client_id_len, - session_id2, session_id2_len, - x2_s_proof, x2_s_proof_len, - &pctx->k, - &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len)); - - bzero(x2_s_proof, x2_s_proof_len); - free(x2_s_proof); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__)); - - /* Send key confirmation proof */ - packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM); - packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); - packet_send(); - packet_write_wait(); - - /* Expect confirmation from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, - input_userauth_jpake_client_confirm); -} - -/* ARGSUSED */ -static void -input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->jpake_ctx; - int authenticated = 0; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL); - - pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len); - packet_check_eom(); - - if (!use_privsep) - JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__)); - - /* Verify expected confirmation hash */ - if (PRIVSEP(jpake_check_confirm(pctx->k, - pctx->client_id, pctx->client_id_len, - session_id2, session_id2_len, - pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1) - authenticated = authctxt->valid ? 1 : 0; - else - debug("%s: confirmation mismatch", __func__); - - /* done */ - authctxt->postponed = 0; - jpake_free(authctxt->jpake_ctx); - authctxt->jpake_ctx = NULL; - userauth_finish(authctxt, authenticated, method_jpake.name, NULL); -} - -#endif /* JPAKE */ - @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -71,9 +71,6 @@ extern Authmethod method_hostbased; #ifdef GSSAPI extern Authmethod method_gssapi; #endif -#ifdef JPAKE -extern Authmethod method_jpake; -#endif Authmethod *authmethods[] = { &method_none, @@ -81,9 +78,6 @@ Authmethod *authmethods[] = { #ifdef GSSAPI &method_gssapi, #endif -#ifdef JPAKE - &method_jpake, -#endif &method_passwd, &method_kbdint, &method_hostbased, @@ -270,9 +264,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) } /* reset state */ auth2_challenge_stop(authctxt); -#ifdef JPAKE - auth2_jpake_stop(authctxt); -#endif #ifdef GSSAPI /* XXX move to auth2_gssapi_stop() */ diff --git a/jpake.c b/jpake.c deleted file mode 100644 index 3dd87916a..000000000 --- a/jpake.c +++ /dev/null @@ -1,456 +0,0 @@ -/* $OpenBSD: jpake.c,v 1.8 2013/05/17 00:13:13 djm Exp $ */ -/* - * Copyright (c) 2008 Damien Miller. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Shared components of zero-knowledge password auth using J-PAKE protocol - * as described in: - * - * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling", - * 16th Workshop on Security Protocols, Cambridge, April 2008 - * - * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf - */ - -#include "includes.h" - -#include <sys/types.h> - -#include <stdio.h> -#include <string.h> -#include <stdarg.h> - -#include <openssl/bn.h> -#include <openssl/evp.h> - -#include "xmalloc.h" -#include "ssh2.h" -#include "key.h" -#include "hostfile.h" -#include "auth.h" -#include "buffer.h" -#include "packet.h" -#include "dispatch.h" -#include "log.h" -#include "misc.h" - -#include "jpake.h" -#include "schnorr.h" - -#ifdef JPAKE - -/* RFC3526 group 5, 1536 bits */ -#define JPAKE_GROUP_G "2" -#define JPAKE_GROUP_P \ - "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" \ - "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" \ - "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \ - "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" \ - "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \ - "9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF" - -struct modp_group * -jpake_default_group(void) -{ - return modp_group_from_g_and_safe_p(JPAKE_GROUP_G, JPAKE_GROUP_P); -} - -struct jpake_ctx * -jpake_new(void) -{ - struct jpake_ctx *ret; - - ret = xcalloc(1, sizeof(*ret)); - - ret->grp = jpake_default_group(); - - ret->s = ret->k = NULL; - ret->x1 = ret->x2 = ret->x3 = ret->x4 = NULL; - ret->g_x1 = ret->g_x2 = ret->g_x3 = ret->g_x4 = NULL; - ret->a = ret->b = NULL; - - ret->client_id = ret->server_id = NULL; - ret->h_k_cid_sessid = ret->h_k_sid_sessid = NULL; - - debug3("%s: alloc %p", __func__, ret); - - return ret; -} - -void -jpake_free(struct jpake_ctx *pctx) -{ - debug3("%s: free %p", __func__, pctx); - -#define JPAKE_BN_CLEAR_FREE(v) \ - do { \ - if ((v) != NULL) { \ - BN_clear_free(v); \ - (v) = NULL; \ - } \ - } while (0) -#define JPAKE_BUF_CLEAR_FREE(v, l) \ - do { \ - if ((v) != NULL) { \ - bzero((v), (l)); \ - free(v); \ - (v) = NULL; \ - (l) = 0; \ - } \ - } while (0) - - JPAKE_BN_CLEAR_FREE(pctx->s); - JPAKE_BN_CLEAR_FREE(pctx->k); - JPAKE_BN_CLEAR_FREE(pctx->x1); - JPAKE_BN_CLEAR_FREE(pctx->x2); - JPAKE_BN_CLEAR_FREE(pctx->x3); - JPAKE_BN_CLEAR_FREE(pctx->x4); - JPAKE_BN_CLEAR_FREE(pctx->g_x1); - JPAKE_BN_CLEAR_FREE(pctx->g_x2); - JPAKE_BN_CLEAR_FREE(pctx->g_x3); - JPAKE_BN_CLEAR_FREE(pctx->g_x4); - JPAKE_BN_CLEAR_FREE(pctx->a); - JPAKE_BN_CLEAR_FREE(pctx->b); - - JPAKE_BUF_CLEAR_FREE(pctx->client_id, pctx->client_id_len); - JPAKE_BUF_CLEAR_FREE(pctx->server_id, pctx->server_id_len); - JPAKE_BUF_CLEAR_FREE(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len); - JPAKE_BUF_CLEAR_FREE(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); - -#undef JPAKE_BN_CLEAR_FREE -#undef JPAKE_BUF_CLEAR_FREE - - bzero(pctx, sizeof(*pctx)); - free(pctx); -} - -/* dump entire jpake_ctx. NB. includes private values! */ -void -jpake_dump(struct jpake_ctx *pctx, const char *fmt, ...) -{ - char *out; - va_list args; - - out = NULL; - va_start(args, fmt); - vasprintf(&out, fmt, args); - va_end(args); - if (out == NULL) - fatal("%s: vasprintf failed", __func__); - - debug3("%s: %s (ctx at %p)", __func__, out, pctx); - if (pctx == NULL) { - free(out); - return; - } - -#define JPAKE_DUMP_BN(a) do { \ - if ((a) != NULL) \ - JPAKE_DEBUG_BN(((a), "%s = ", #a)); \ - } while (0) -#define JPAKE_DUMP_BUF(a, b) do { \ - if ((a) != NULL) \ - JPAKE_DEBUG_BUF((a, b, "%s", #a)); \ - } while (0) - - JPAKE_DUMP_BN(pctx->s); - JPAKE_DUMP_BN(pctx->k); - JPAKE_DUMP_BN(pctx->x1); - JPAKE_DUMP_BN(pctx->x2); - JPAKE_DUMP_BN(pctx->x3); - JPAKE_DUMP_BN(pctx->x4); - JPAKE_DUMP_BN(pctx->g_x1); - JPAKE_DUMP_BN(pctx->g_x2); - JPAKE_DUMP_BN(pctx->g_x3); - JPAKE_DUMP_BN(pctx->g_x4); - JPAKE_DUMP_BN(pctx->a); - JPAKE_DUMP_BN(pctx->b); - - JPAKE_DUMP_BUF(pctx->client_id, pctx->client_id_len); - JPAKE_DUMP_BUF(pctx->server_id, pctx->server_id_len); - JPAKE_DUMP_BUF(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len); - JPAKE_DUMP_BUF(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); - - debug3("%s: %s done", __func__, out); - free(out); -} - -/* Shared parts of step 1 exchange calculation */ -void -jpake_step1(struct modp_group *grp, - u_char **id, u_int *id_len, - BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, - u_char **priv1_proof, u_int *priv1_proof_len, - u_char **priv2_proof, u_int *priv2_proof_len) -{ - BN_CTX *bn_ctx; - - if ((bn_ctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new", __func__); - - /* Random nonce to prevent replay */ - *id = xmalloc(KZP_ID_LEN); - *id_len = KZP_ID_LEN; - arc4random_buf(*id, *id_len); - - /* - * x1/x3 is a random element of Zq - * x2/x4 is a random element of Z*q - * We also exclude [1] from x1/x3 candidates and [0, 1] from - * x2/x4 candiates to avoid possible degeneracy (i.e. g^0, g^1). - */ - if ((*priv1 = bn_rand_range_gt_one(grp->q)) == NULL || - (*priv2 = bn_rand_range_gt_one(grp->q)) == NULL) - fatal("%s: bn_rand_range_gt_one", __func__); - - /* - * client: g_x1 = g^x1 mod p / server: g_x3 = g^x3 mod p - * client: g_x2 = g^x2 mod p / server: g_x4 = g^x4 mod p - */ - if ((*g_priv1 = BN_new()) == NULL || - (*g_priv2 = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - if (BN_mod_exp(*g_priv1, grp->g, *priv1, grp->p, bn_ctx) == -1) - fatal("%s: BN_mod_exp", __func__); - if (BN_mod_exp(*g_priv2, grp->g, *priv2, grp->p, bn_ctx) == -1) - fatal("%s: BN_mod_exp", __func__); - - /* Generate proofs for holding x1/x3 and x2/x4 */ - if (schnorr_sign_buf(grp->p, grp->q, grp->g, - *priv1, *g_priv1, *id, *id_len, - priv1_proof, priv1_proof_len) != 0) - fatal("%s: schnorr_sign", __func__); - if (schnorr_sign_buf(grp->p, grp->q, grp->g, - *priv2, *g_priv2, *id, *id_len, - priv2_proof, priv2_proof_len) != 0) - fatal("%s: schnorr_sign", __func__); - - BN_CTX_free(bn_ctx); -} - -/* Shared parts of step 2 exchange calculation */ -void -jpake_step2(struct modp_group *grp, BIGNUM *s, - BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, - const u_char *theirid, u_int theirid_len, - const u_char *myid, u_int myid_len, - const u_char *theirpub1_proof, u_int theirpub1_proof_len, - const u_char *theirpub2_proof, u_int theirpub2_proof_len, - BIGNUM **newpub, - u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len) -{ - BN_CTX *bn_ctx; - BIGNUM *tmp, *exponent; - - /* Validate peer's step 1 values */ - if (BN_cmp(theirpub1, BN_value_one()) <= 0) - fatal("%s: theirpub1 <= 1", __func__); - if (BN_cmp(theirpub1, grp->p) >= 0) - fatal("%s: theirpub1 >= p", __func__); - if (BN_cmp(theirpub2, BN_value_one()) <= 0) - fatal("%s: theirpub2 <= 1", __func__); - if (BN_cmp(theirpub2, grp->p) >= 0) - fatal("%s: theirpub2 >= p", __func__); - - if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1, - theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1) - fatal("%s: schnorr_verify theirpub1 failed", __func__); - if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub2, - theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1) - fatal("%s: schnorr_verify theirpub2 failed", __func__); - - if ((bn_ctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new", __func__); - - if ((*newpub = BN_new()) == NULL || - (tmp = BN_new()) == NULL || - (exponent = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - /* - * client: exponent = x2 * s mod p - * server: exponent = x4 * s mod p - */ - if (BN_mod_mul(exponent, mypriv2, s, grp->q, bn_ctx) != 1) - fatal("%s: BN_mod_mul (exponent = mypriv2 * s mod p)", - __func__); - - /* - * client: tmp = g^(x1 + x3 + x4) mod p - * server: tmp = g^(x1 + x2 + x3) mod p - */ - if (BN_mod_mul(tmp, mypub1, theirpub1, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (tmp = mypub1 * theirpub1 mod p)", - __func__); - if (BN_mod_mul(tmp, tmp, theirpub2, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (tmp = tmp * theirpub2 mod p)", __func__); - - /* - * client: a = tmp^exponent = g^((x1+x3+x4) * x2 * s) mod p - * server: b = tmp^exponent = g^((x1+x2+x3) * x4 * s) mod p - */ - if (BN_mod_exp(*newpub, tmp, exponent, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (newpub = tmp^exponent mod p)", __func__); - - JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__)); - JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__)); - - /* Note the generator here is 'tmp', not g */ - if (schnorr_sign_buf(grp->p, grp->q, tmp, exponent, *newpub, - myid, myid_len, - newpub_exponent_proof, newpub_exponent_proof_len) != 0) - fatal("%s: schnorr_sign newpub", __func__); - - BN_clear_free(tmp); /* XXX stash for later use? */ - BN_clear_free(exponent); /* XXX stash for later use? (yes, in conf) */ - - BN_CTX_free(bn_ctx); -} - -/* Confirmation hash calculation */ -void -jpake_confirm_hash(const BIGNUM *k, - const u_char *endpoint_id, u_int endpoint_id_len, - const u_char *sess_id, u_int sess_id_len, - u_char **confirm_hash, u_int *confirm_hash_len) -{ - Buffer b; - - /* - * Calculate confirmation proof: - * client: H(k || client_id || session_id) - * server: H(k || server_id || session_id) - */ - buffer_init(&b); - buffer_put_bignum2(&b, k); - buffer_put_string(&b, endpoint_id, endpoint_id_len); - buffer_put_string(&b, sess_id, sess_id_len); - if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(), - confirm_hash, confirm_hash_len) != 0) - fatal("%s: hash_buffer", __func__); - buffer_free(&b); -} - -/* Shared parts of key derivation and confirmation calculation */ -void -jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val, - BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, - BIGNUM *theirpub1, BIGNUM *theirpub2, - const u_char *my_id, u_int my_id_len, - const u_char *their_id, u_int their_id_len, - const u_char *sess_id, u_int sess_id_len, - const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len, - BIGNUM **k, - u_char **confirm_hash, u_int *confirm_hash_len) -{ - BN_CTX *bn_ctx; - BIGNUM *tmp; - - if ((bn_ctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new", __func__); - if ((tmp = BN_new()) == NULL || - (*k = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - /* Validate step 2 values */ - if (BN_cmp(step2_val, BN_value_one()) <= 0) - fatal("%s: step2_val <= 1", __func__); - if (BN_cmp(step2_val, grp->p) >= 0) - fatal("%s: step2_val >= p", __func__); - - /* - * theirpriv2_s_proof is calculated with a different generator: - * tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1 - * Calculate it here so we can check the signature. - */ - if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__); - if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__); - - JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__)); - - if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val, - their_id, their_id_len, - theirpriv2_s_proof, theirpriv2_s_proof_len) != 1) - fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__); - - /* - * Derive shared key: - * client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s) - * server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s) - * - * Computed as: - * client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p - * server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p - */ - if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1) - fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__); - if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1) - fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__); - if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__); - if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__); - if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1) - fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__); - - BN_CTX_free(bn_ctx); - BN_clear_free(tmp); - - jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len, - confirm_hash, confirm_hash_len); -} - -/* - * Calculate and check confirmation hash from peer. Returns 1 on success - * 0 on failure/mismatch. - */ -int -jpake_check_confirm(const BIGNUM *k, - const u_char *peer_id, u_int peer_id_len, - const u_char *sess_id, u_int sess_id_len, - const u_char *peer_confirm_hash, u_int peer_confirm_hash_len) -{ - u_char *expected_confirm_hash; - u_int expected_confirm_hash_len; - int success = 0; - - /* Calculate and verify expected confirmation hash */ - jpake_confirm_hash(k, peer_id, peer_id_len, sess_id, sess_id_len, - &expected_confirm_hash, &expected_confirm_hash_len); - - JPAKE_DEBUG_BUF((expected_confirm_hash, expected_confirm_hash_len, - "%s: expected confirm hash", __func__)); - JPAKE_DEBUG_BUF((peer_confirm_hash, peer_confirm_hash_len, - "%s: received confirm hash", __func__)); - - if (peer_confirm_hash_len != expected_confirm_hash_len) - error("%s: confirmation length mismatch (my %u them %u)", - __func__, expected_confirm_hash_len, peer_confirm_hash_len); - else if (timingsafe_bcmp(peer_confirm_hash, expected_confirm_hash, - expected_confirm_hash_len) == 0) - success = 1; - bzero(expected_confirm_hash, expected_confirm_hash_len); - free(expected_confirm_hash); - debug3("%s: success = %d", __func__, success); - return success; -} - -/* XXX main() function with tests */ - -#endif /* JPAKE */ - diff --git a/jpake.h b/jpake.h deleted file mode 100644 index a3f2cf025..000000000 --- a/jpake.h +++ /dev/null @@ -1,114 +0,0 @@ -/* $OpenBSD: jpake.h,v 1.2 2009/03/05 07:18:19 djm Exp $ */ -/* - * Copyright (c) 2008 Damien Miller. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef JPAKE_H -#define JPAKE_H - -#include <sys/types.h> - -#include <openssl/bn.h> - -/* Set JPAKE_DEBUG in CFLAGS for privacy-violating debugging */ -#ifndef JPAKE_DEBUG -# define JPAKE_DEBUG_BN(a) -# define JPAKE_DEBUG_BUF(a) -# define JPAKE_DEBUG_CTX(a) -#else -# define JPAKE_DEBUG_BN(a) debug3_bn a -# define JPAKE_DEBUG_BUF(a) debug3_buf a -# define JPAKE_DEBUG_CTX(a) jpake_dump a -#endif /* JPAKE_DEBUG */ - -#define KZP_ID_LEN 16 /* Length of client and server IDs */ - -struct jpake_ctx { - /* Parameters */ - struct modp_group *grp; - - /* Private values shared by client and server */ - BIGNUM *s; /* Secret (salted, crypted password) */ - BIGNUM *k; /* Derived key */ - - /* Client private values (NULL for server) */ - BIGNUM *x1; /* random in Zq */ - BIGNUM *x2; /* random in Z*q */ - - /* Server private values (NULL for server) */ - BIGNUM *x3; /* random in Zq */ - BIGNUM *x4; /* random in Z*q */ - - /* Step 1: C->S */ - u_char *client_id; /* Anti-replay nonce */ - u_int client_id_len; - BIGNUM *g_x1; /* g^x1 */ - BIGNUM *g_x2; /* g^x2 */ - - /* Step 1: S->C */ - u_char *server_id; /* Anti-replay nonce */ - u_int server_id_len; - BIGNUM *g_x3; /* g^x3 */ - BIGNUM *g_x4; /* g^x4 */ - - /* Step 2: C->S */ - BIGNUM *a; /* g^((x1+x3+x4)*x2*s) */ - - /* Step 2: S->C */ - BIGNUM *b; /* g^((x1+x2+x3)*x4*s) */ - - /* Confirmation: C->S */ - u_char *h_k_cid_sessid; /* H(k || client_id || session_id) */ - u_int h_k_cid_sessid_len; - - /* Confirmation: S->C */ - u_char *h_k_sid_sessid; /* H(k || server_id || session_id) */ - u_int h_k_sid_sessid_len; -}; - -/* jpake.c */ -struct modp_group *jpake_default_group(void); -void jpake_dump(struct jpake_ctx *, const char *, ...) - __attribute__((__nonnull__ (2))) - __attribute__((format(printf, 2, 3))); -struct jpake_ctx *jpake_new(void); -void jpake_free(struct jpake_ctx *); - -void jpake_step1(struct modp_group *, u_char **, u_int *, - BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, - u_char **, u_int *, u_char **, u_int *); - -void jpake_step2(struct modp_group *, BIGNUM *, - BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, - const u_char *, u_int, const u_char *, u_int, - const u_char *, u_int, const u_char *, u_int, - BIGNUM **, u_char **, u_int *); - -void jpake_confirm_hash(const BIGNUM *, - const u_char *, u_int, - const u_char *, u_int, - u_char **, u_int *); - -void jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *, - BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, - const u_char *, u_int, const u_char *, u_int, - const u_char *, u_int, const u_char *, u_int, - BIGNUM **, u_char **, u_int *); - -int jpake_check_confirm(const BIGNUM *, const u_char *, u_int, - const u_char *, u_int, const u_char *, u_int); - -#endif /* JPAKE_H */ - @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.128 2013/11/04 11:51:16 markus Exp $ */ +/* $OpenBSD: monitor.c,v 1.129 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -95,7 +95,6 @@ #include "misc.h" #include "compat.h" #include "ssh2.h" -#include "jpake.h" #include "roaming.h" #include "authfd.h" @@ -161,11 +160,6 @@ int mm_answer_rsa_challenge(int, Buffer *); int mm_answer_rsa_response(int, Buffer *); int mm_answer_sesskey(int, Buffer *); int mm_answer_sessid(int, Buffer *); -int mm_answer_jpake_get_pwdata(int, Buffer *); -int mm_answer_jpake_step1(int, Buffer *); -int mm_answer_jpake_step2(int, Buffer *); -int mm_answer_jpake_key_confirm(int, Buffer *); -int mm_answer_jpake_check_confirm(int, Buffer *); #ifdef USE_PAM int mm_answer_pam_start(int, Buffer *); @@ -254,13 +248,6 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, #endif -#ifdef JPAKE - {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata}, - {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1}, - {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2}, - {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm}, - {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm}, -#endif {0, 0, NULL} }; @@ -427,15 +414,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) if (!authenticated) authctxt->failures++; } -#ifdef JPAKE - /* Cleanup JPAKE context after authentication */ - if (ent->flags & MON_AUTHDECIDE) { - if (authctxt->jpake_ctx != NULL) { - jpake_free(authctxt->jpake_ctx); - authctxt->jpake_ctx = NULL; - } - } -#endif } if (!authctxt->valid) @@ -2159,205 +2137,3 @@ mm_answer_gss_userok(int sock, Buffer *m) } #endif /* GSSAPI */ -#ifdef JPAKE -int -mm_answer_jpake_step1(int sock, Buffer *m) -{ - struct jpake_ctx *pctx; - u_char *x3_proof, *x4_proof; - u_int x3_proof_len, x4_proof_len; - - if (!options.zero_knowledge_password_authentication) - fatal("zero_knowledge_password_authentication disabled"); - - if (authctxt->jpake_ctx != NULL) - fatal("%s: authctxt->jpake_ctx already set (%p)", - __func__, authctxt->jpake_ctx); - authctxt->jpake_ctx = pctx = jpake_new(); - - jpake_step1(pctx->grp, - &pctx->server_id, &pctx->server_id_len, - &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4, - &x3_proof, &x3_proof_len, - &x4_proof, &x4_proof_len); - - JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__)); - - buffer_clear(m); - - buffer_put_string(m, pctx->server_id, pctx->server_id_len); - buffer_put_bignum2(m, pctx->g_x3); - buffer_put_bignum2(m, pctx->g_x4); - buffer_put_string(m, x3_proof, x3_proof_len); - buffer_put_string(m, x4_proof, x4_proof_len); - - debug3("%s: sending step1", __func__); - mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m); - - bzero(x3_proof, x3_proof_len); - bzero(x4_proof, x4_proof_len); - free(x3_proof); - free(x4_proof); - - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1); - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0); - - return 0; -} - -int -mm_answer_jpake_get_pwdata(int sock, Buffer *m) -{ - struct jpake_ctx *pctx = authctxt->jpake_ctx; - char *hash_scheme, *salt; - - if (pctx == NULL) - fatal("%s: pctx == NULL", __func__); - - auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt); - - buffer_clear(m); - /* pctx->s is sensitive, not returned to slave */ - buffer_put_cstring(m, hash_scheme); - buffer_put_cstring(m, salt); - - debug3("%s: sending pwdata", __func__); - mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m); - - bzero(hash_scheme, strlen(hash_scheme)); - bzero(salt, strlen(salt)); - free(hash_scheme); - free(salt); - - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1); - - return 0; -} - -int -mm_answer_jpake_step2(int sock, Buffer *m) -{ - struct jpake_ctx *pctx = authctxt->jpake_ctx; - u_char *x1_proof, *x2_proof, *x4_s_proof; - u_int x1_proof_len, x2_proof_len, x4_s_proof_len; - - if (pctx == NULL) - fatal("%s: pctx == NULL", __func__); - - if ((pctx->g_x1 = BN_new()) == NULL || - (pctx->g_x2 = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - buffer_get_bignum2(m, pctx->g_x1); - buffer_get_bignum2(m, pctx->g_x2); - pctx->client_id = buffer_get_string(m, &pctx->client_id_len); - x1_proof = buffer_get_string(m, &x1_proof_len); - x2_proof = buffer_get_string(m, &x2_proof_len); - - jpake_step2(pctx->grp, pctx->s, pctx->g_x3, - pctx->g_x1, pctx->g_x2, pctx->x4, - pctx->client_id, pctx->client_id_len, - pctx->server_id, pctx->server_id_len, - x1_proof, x1_proof_len, - x2_proof, x2_proof_len, - &pctx->b, - &x4_s_proof, &x4_s_proof_len); - - JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__)); - - bzero(x1_proof, x1_proof_len); - bzero(x2_proof, x2_proof_len); - free(x1_proof); - free(x2_proof); - - buffer_clear(m); - - buffer_put_bignum2(m, pctx->b); - buffer_put_string(m, x4_s_proof, x4_s_proof_len); - - debug3("%s: sending step2", __func__); - mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m); - - bzero(x4_s_proof, x4_s_proof_len); - free(x4_s_proof); - - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1); - - return 0; -} - -int -mm_answer_jpake_key_confirm(int sock, Buffer *m) -{ - struct jpake_ctx *pctx = authctxt->jpake_ctx; - u_char *x2_s_proof; - u_int x2_s_proof_len; - - if (pctx == NULL) - fatal("%s: pctx == NULL", __func__); - - if ((pctx->a = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - buffer_get_bignum2(m, pctx->a); - x2_s_proof = buffer_get_string(m, &x2_s_proof_len); - - jpake_key_confirm(pctx->grp, pctx->s, pctx->a, - pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2, - pctx->server_id, pctx->server_id_len, - pctx->client_id, pctx->client_id_len, - session_id2, session_id2_len, - x2_s_proof, x2_s_proof_len, - &pctx->k, - &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len); - - JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__)); - - bzero(x2_s_proof, x2_s_proof_len); - buffer_clear(m); - - /* pctx->k is sensitive, not sent */ - buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len); - - debug3("%s: sending confirmation hash", __func__); - mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1); - - return 0; -} - -int -mm_answer_jpake_check_confirm(int sock, Buffer *m) -{ - int authenticated = 0; - u_char *peer_confirm_hash; - u_int peer_confirm_hash_len; - struct jpake_ctx *pctx = authctxt->jpake_ctx; - - if (pctx == NULL) - fatal("%s: pctx == NULL", __func__); - - peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len); - - authenticated = jpake_check_confirm(pctx->k, - pctx->client_id, pctx->client_id_len, - session_id2, session_id2_len, - peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid; - - JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__)); - - bzero(peer_confirm_hash, peer_confirm_hash_len); - free(peer_confirm_hash); - - buffer_clear(m); - buffer_put_int(m, authenticated); - - debug3("%s: sending result %d", __func__, authenticated); - mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m); - - monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1); - - auth_method = "jpake-01@openssh.com"; - return authenticated; -} - -#endif /* JPAKE */ @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.h,v 1.17 2012/12/02 20:34:10 djm Exp $ */ +/* $OpenBSD: monitor.h,v 1.18 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> @@ -56,11 +56,6 @@ enum monitor_reqtype { MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, MONITOR_REQ_TERM = 50, - MONITOR_REQ_JPAKE_STEP1 = 52, MONITOR_ANS_JPAKE_STEP1 = 53, - MONITOR_REQ_JPAKE_GET_PWDATA = 54, MONITOR_ANS_JPAKE_GET_PWDATA = 55, - MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57, - MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59, - MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61, MONITOR_REQ_PAM_START = 100, MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, diff --git a/monitor_wrap.c b/monitor_wrap.c index 4ce469605..64c262363 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.c,v 1.77 2013/11/06 16:52:11 markus Exp $ */ +/* $OpenBSD: monitor_wrap.c,v 1.78 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Markus Friedl <markus@openbsd.org> @@ -71,8 +71,6 @@ #include "atomicio.h" #include "monitor_fdpass.h" #include "misc.h" -#include "schnorr.h" -#include "jpake.h" #include "uuencode.h" #include "channels.h" @@ -1292,164 +1290,3 @@ mm_ssh_gssapi_userok(char *user) } #endif /* GSSAPI */ -#ifdef JPAKE -void -mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s, - char **hash_scheme, char **salt) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, - MONITOR_REQ_JPAKE_GET_PWDATA, &m); - - debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_JPAKE_GET_PWDATA, &m); - - *hash_scheme = buffer_get_string(&m, NULL); - *salt = buffer_get_string(&m, NULL); - - buffer_free(&m); -} - -void -mm_jpake_step1(struct modp_group *grp, - u_char **id, u_int *id_len, - BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2, - u_char **priv1_proof, u_int *priv1_proof_len, - u_char **priv2_proof, u_int *priv2_proof_len) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - mm_request_send(pmonitor->m_recvfd, - MONITOR_REQ_JPAKE_STEP1, &m); - - debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_JPAKE_STEP1, &m); - - if ((*priv1 = BN_new()) == NULL || - (*priv2 = BN_new()) == NULL || - (*g_priv1 = BN_new()) == NULL || - (*g_priv2 = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - *id = buffer_get_string(&m, id_len); - /* priv1 and priv2 are, well, private */ - buffer_get_bignum2(&m, *g_priv1); - buffer_get_bignum2(&m, *g_priv2); - *priv1_proof = buffer_get_string(&m, priv1_proof_len); - *priv2_proof = buffer_get_string(&m, priv2_proof_len); - - buffer_free(&m); -} - -void -mm_jpake_step2(struct modp_group *grp, BIGNUM *s, - BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2, - const u_char *theirid, u_int theirid_len, - const u_char *myid, u_int myid_len, - const u_char *theirpub1_proof, u_int theirpub1_proof_len, - const u_char *theirpub2_proof, u_int theirpub2_proof_len, - BIGNUM **newpub, - u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - /* monitor already has all bignums except theirpub1, theirpub2 */ - buffer_put_bignum2(&m, theirpub1); - buffer_put_bignum2(&m, theirpub2); - /* monitor already knows our id */ - buffer_put_string(&m, theirid, theirid_len); - buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len); - buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len); - - mm_request_send(pmonitor->m_recvfd, - MONITOR_REQ_JPAKE_STEP2, &m); - - debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_JPAKE_STEP2, &m); - - if ((*newpub = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - buffer_get_bignum2(&m, *newpub); - *newpub_exponent_proof = buffer_get_string(&m, - newpub_exponent_proof_len); - - buffer_free(&m); -} - -void -mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val, - BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2, - BIGNUM *theirpub1, BIGNUM *theirpub2, - const u_char *my_id, u_int my_id_len, - const u_char *their_id, u_int their_id_len, - const u_char *sess_id, u_int sess_id_len, - const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len, - BIGNUM **k, - u_char **confirm_hash, u_int *confirm_hash_len) -{ - Buffer m; - - debug3("%s entering", __func__); - - buffer_init(&m); - /* monitor already has all bignums except step2_val */ - buffer_put_bignum2(&m, step2_val); - /* monitor already knows all the ids */ - buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len); - - mm_request_send(pmonitor->m_recvfd, - MONITOR_REQ_JPAKE_KEY_CONFIRM, &m); - - debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_JPAKE_KEY_CONFIRM, &m); - - /* 'k' is sensitive and stays in the monitor */ - *confirm_hash = buffer_get_string(&m, confirm_hash_len); - - buffer_free(&m); -} - -int -mm_jpake_check_confirm(const BIGNUM *k, - const u_char *peer_id, u_int peer_id_len, - const u_char *sess_id, u_int sess_id_len, - const u_char *peer_confirm_hash, u_int peer_confirm_hash_len) -{ - Buffer m; - int success = 0; - - debug3("%s entering", __func__); - - buffer_init(&m); - /* k is dummy in slave, ignored */ - /* monitor knows all the ids */ - buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len); - mm_request_send(pmonitor->m_recvfd, - MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m); - - debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__); - mm_request_receive_expect(pmonitor->m_recvfd, - MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m); - - success = buffer_get_int(&m); - buffer_free(&m); - - debug3("%s: success = %d", __func__, success); - return success; -} -#endif /* JPAKE */ diff --git a/monitor_wrap.h b/monitor_wrap.h index 0c7f2e384..18c25010d 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */ +/* $OpenBSD: monitor_wrap.h,v 1.24 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> @@ -102,26 +102,6 @@ int mm_bsdauth_respond(void *, u_int, char **); int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); int mm_skey_respond(void *, u_int, char **); -/* jpake */ -struct modp_group; -void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **); -void mm_jpake_step1(struct modp_group *, u_char **, u_int *, - BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, - u_char **, u_int *, u_char **, u_int *); -void mm_jpake_step2(struct modp_group *, BIGNUM *, - BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, - const u_char *, u_int, const u_char *, u_int, - const u_char *, u_int, const u_char *, u_int, - BIGNUM **, u_char **, u_int *); -void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *, - BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, - const u_char *, u_int, const u_char *, u_int, - const u_char *, u_int, const u_char *, u_int, - BIGNUM **, u_char **, u_int *); -int mm_jpake_check_confirm(const BIGNUM *, - const u_char *, u_int, const u_char *, u_int, const u_char *, u_int); - - /* zlib allocation hooks */ void *mm_zalloc(struct mm_master *, u_int, u_int); diff --git a/readconf.c b/readconf.c index 7b42f68d9..f80d1ccbc 100644 --- a/readconf.c +++ b/readconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: readconf.c,v 1.216 2014/01/29 06:18:35 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -145,7 +145,7 @@ typedef enum { oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, - oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, + oVisualHostKey, oUseRoaming, oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, @@ -252,12 +252,6 @@ static struct { { "permitlocalcommand", oPermitLocalCommand }, { "visualhostkey", oVisualHostKey }, { "useroaming", oUseRoaming }, -#ifdef JPAKE - { "zeroknowledgepasswordauthentication", - oZeroKnowledgePasswordAuthentication }, -#else - { "zeroknowledgepasswordauthentication", oUnsupported }, -#endif { "kexalgorithms", oKexAlgorithms }, { "ipqos", oIPQoS }, { "requesttty", oRequestTTY }, @@ -804,10 +798,6 @@ parse_time: intptr = &options->password_authentication; goto parse_flag; - case oZeroKnowledgePasswordAuthentication: - intptr = &options->zero_knowledge_password_authentication; - goto parse_flag; - case oKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; @@ -1550,7 +1540,6 @@ initialize_options(Options * options) options->permit_local_command = -1; options->use_roaming = -1; options->visual_host_key = -1; - options->zero_knowledge_password_authentication = -1; options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->request_tty = -1; @@ -1706,8 +1695,6 @@ fill_default_options(Options * options) options->use_roaming = 1; if (options->visual_host_key == -1) options->visual_host_key = 0; - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_LOWDELAY; if (options->ip_qos_bulk == -1) diff --git a/readconf.h b/readconf.h index 2d7ea9fc4..9723da078 100644 --- a/readconf.h +++ b/readconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: readconf.h,v 1.99 2013/10/16 22:49:38 djm Exp $ */ +/* $OpenBSD: readconf.h,v 1.100 2014/01/29 06:18:35 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -59,7 +59,6 @@ typedef struct { * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ - int zero_knowledge_password_authentication; /* Try jpake */ int batch_mode; /* Batch mode: do not ask for passwords. */ int check_host_ip; /* Also keep track of keys for IP address */ int strict_host_key_checking; /* Strict host key checking. */ diff --git a/schnorr.c b/schnorr.c deleted file mode 100644 index aa3a57770..000000000 --- a/schnorr.c +++ /dev/null @@ -1,668 +0,0 @@ -/* $OpenBSD: schnorr.c,v 1.9 2014/01/09 23:20:00 djm Exp $ */ -/* - * Copyright (c) 2008 Damien Miller. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Implementation of Schnorr signatures / zero-knowledge proofs, based on - * description in: - * - * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling", - * 16th Workshop on Security Protocols, Cambridge, April 2008 - * - * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf - */ - -#include "includes.h" - -#include <sys/types.h> - -#include <string.h> -#include <stdarg.h> -#include <stdio.h> - -#include <openssl/evp.h> -#include <openssl/bn.h> - -#include "xmalloc.h" -#include "buffer.h" -#include "log.h" - -#include "schnorr.h" -#include "digest.h" - -#include "openbsd-compat/openssl-compat.h" - -/* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */ -/* #define SCHNORR_MAIN */ /* Include main() selftest */ - -#ifndef SCHNORR_DEBUG -# define SCHNORR_DEBUG_BN(a) -# define SCHNORR_DEBUG_BUF(a) -#else -# define SCHNORR_DEBUG_BN(a) debug3_bn a -# define SCHNORR_DEBUG_BUF(a) debug3_buf a -#endif /* SCHNORR_DEBUG */ - -/* - * Calculate hash component of Schnorr signature H(g || g^v || g^x || id) - * using the hash function defined by "hash_alg". Returns signature as - * bignum or NULL on error. - */ -static BIGNUM * -schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g, - int hash_alg, const BIGNUM *g_v, const BIGNUM *g_x, - const u_char *id, u_int idlen) -{ - u_char *digest; - u_int digest_len; - BIGNUM *h; - Buffer b; - int success = -1; - - if ((h = BN_new()) == NULL) { - error("%s: BN_new", __func__); - return NULL; - } - - buffer_init(&b); - - /* h = H(g || p || q || g^v || g^x || id) */ - buffer_put_bignum2(&b, g); - buffer_put_bignum2(&b, p); - buffer_put_bignum2(&b, q); - buffer_put_bignum2(&b, g_v); - buffer_put_bignum2(&b, g_x); - buffer_put_string(&b, id, idlen); - - SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), - "%s: hashblob", __func__)); - if (hash_buffer(buffer_ptr(&b), buffer_len(&b), hash_alg, - &digest, &digest_len) != 0) { - error("%s: hash_buffer", __func__); - goto out; - } - if (BN_bin2bn(digest, (int)digest_len, h) == NULL) { - error("%s: BN_bin2bn", __func__); - goto out; - } - success = 0; - SCHNORR_DEBUG_BN((h, "%s: h = ", __func__)); - out: - buffer_free(&b); - bzero(digest, digest_len); - free(digest); - digest_len = 0; - if (success == 0) - return h; - BN_clear_free(h); - return NULL; -} - -/* - * Generate Schnorr signature to prove knowledge of private value 'x' used - * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' - * using the hash function "hash_alg". - * 'idlen' bytes from 'id' will be included in the signature hash as an anti- - * replay salt. - * - * On success, 0 is returned. The signature values are returned as *e_p - * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values. - * On failure, -1 is returned. - */ -int -schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - int hash_alg, const BIGNUM *x, const BIGNUM *g_x, - const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p) -{ - int success = -1; - BIGNUM *h, *tmp, *v, *g_v, *r; - BN_CTX *bn_ctx; - - SCHNORR_DEBUG_BN((x, "%s: x = ", __func__)); - SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); - - /* Avoid degenerate cases: g^0 yields a spoofable signature */ - if (BN_cmp(g_x, BN_value_one()) <= 0) { - error("%s: g_x < 1", __func__); - return -1; - } - if (BN_cmp(g_x, grp_p) >= 0) { - error("%s: g_x > g", __func__); - return -1; - } - - h = g_v = r = tmp = v = NULL; - if ((bn_ctx = BN_CTX_new()) == NULL) { - error("%s: BN_CTX_new", __func__); - goto out; - } - if ((g_v = BN_new()) == NULL || - (r = BN_new()) == NULL || - (tmp = BN_new()) == NULL) { - error("%s: BN_new", __func__); - goto out; - } - - /* - * v must be a random element of Zq, so 1 <= v < q - * we also exclude v = 1, since g^1 looks dangerous - */ - if ((v = bn_rand_range_gt_one(grp_p)) == NULL) { - error("%s: bn_rand_range2", __func__); - goto out; - } - SCHNORR_DEBUG_BN((v, "%s: v = ", __func__)); - - /* g_v = g^v mod p */ - if (BN_mod_exp(g_v, grp_g, v, grp_p, bn_ctx) == -1) { - error("%s: BN_mod_exp (g^v mod p)", __func__); - goto out; - } - SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__)); - - /* h = H(g || g^v || g^x || id) */ - if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x, - id, idlen)) == NULL) { - error("%s: schnorr_hash failed", __func__); - goto out; - } - - /* r = v - xh mod q */ - if (BN_mod_mul(tmp, x, h, grp_q, bn_ctx) == -1) { - error("%s: BN_mod_mul (tmp = xv mod q)", __func__); - goto out; - } - if (BN_mod_sub(r, v, tmp, grp_q, bn_ctx) == -1) { - error("%s: BN_mod_mul (r = v - tmp)", __func__); - goto out; - } - SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__)); - SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); - - *e_p = g_v; - *r_p = r; - - success = 0; - out: - BN_CTX_free(bn_ctx); - if (h != NULL) - BN_clear_free(h); - if (v != NULL) - BN_clear_free(v); - BN_clear_free(tmp); - - return success; -} - -/* - * Generate Schnorr signature to prove knowledge of private value 'x' used - * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g' - * using a SHA256 hash. - * 'idlen' bytes from 'id' will be included in the signature hash as an anti- - * replay salt. - * On success, 0 is returned and *siglen bytes of signature are returned in - * *sig (caller to free). Returns -1 on failure. - */ -int -schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, - u_char **sig, u_int *siglen) -{ - Buffer b; - BIGNUM *r, *e; - - if (schnorr_sign(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, - x, g_x, id, idlen, &r, &e) != 0) - return -1; - - /* Signature is (e, r) */ - buffer_init(&b); - /* XXX sigtype-hash as string? */ - buffer_put_bignum2(&b, e); - buffer_put_bignum2(&b, r); - *siglen = buffer_len(&b); - *sig = xmalloc(*siglen); - memcpy(*sig, buffer_ptr(&b), *siglen); - SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), - "%s: sigblob", __func__)); - buffer_free(&b); - - BN_clear_free(r); - BN_clear_free(e); - - return 0; -} - -/* - * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against - * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and - * 'grp_g' using hash "hash_alg". - * Signature hash will be salted with 'idlen' bytes from 'id'. - * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. - */ -int -schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, - const BIGNUM *r, const BIGNUM *e) -{ - int success = -1; - BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL; - BIGNUM *expected = NULL; - BN_CTX *bn_ctx; - - SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__)); - - /* Avoid degenerate cases: g^0 yields a spoofable signature */ - if (BN_cmp(g_x, BN_value_one()) <= 0) { - error("%s: g_x <= 1", __func__); - return -1; - } - if (BN_cmp(g_x, grp_p) >= 0) { - error("%s: g_x >= p", __func__); - return -1; - } - - h = g_xh = g_r = expected = NULL; - if ((bn_ctx = BN_CTX_new()) == NULL) { - error("%s: BN_CTX_new", __func__); - goto out; - } - if ((g_xh = BN_new()) == NULL || - (g_r = BN_new()) == NULL || - (gx_q = BN_new()) == NULL || - (expected = BN_new()) == NULL) { - error("%s: BN_new", __func__); - goto out; - } - - SCHNORR_DEBUG_BN((e, "%s: e = ", __func__)); - SCHNORR_DEBUG_BN((r, "%s: r = ", __func__)); - - /* gx_q = (g^x)^q must === 1 mod p */ - if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) { - error("%s: BN_mod_exp (g_x^q mod p)", __func__); - goto out; - } - if (BN_cmp(gx_q, BN_value_one()) != 0) { - error("%s: Invalid signature (g^x)^q != 1 mod p", __func__); - goto out; - } - - SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); - /* h = H(g || g^v || g^x || id) */ - if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x, - id, idlen)) == NULL) { - error("%s: schnorr_hash failed", __func__); - goto out; - } - - /* g_xh = (g^x)^h */ - if (BN_mod_exp(g_xh, g_x, h, grp_p, bn_ctx) == -1) { - error("%s: BN_mod_exp (g_x^h mod p)", __func__); - goto out; - } - SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__)); - - /* g_r = g^r */ - if (BN_mod_exp(g_r, grp_g, r, grp_p, bn_ctx) == -1) { - error("%s: BN_mod_exp (g_x^h mod p)", __func__); - goto out; - } - SCHNORR_DEBUG_BN((g_r, "%s: g_r = ", __func__)); - - /* expected = g^r * g_xh */ - if (BN_mod_mul(expected, g_r, g_xh, grp_p, bn_ctx) == -1) { - error("%s: BN_mod_mul (expected = g_r mod p)", __func__); - goto out; - } - SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__)); - - /* Check e == expected */ - success = BN_cmp(expected, e) == 0; - out: - BN_CTX_free(bn_ctx); - if (h != NULL) - BN_clear_free(h); - if (gx_q != NULL) - BN_clear_free(gx_q); - if (g_xh != NULL) - BN_clear_free(g_xh); - if (g_r != NULL) - BN_clear_free(g_r); - if (expected != NULL) - BN_clear_free(expected); - return success; -} - -/* - * Verify Schnorr signature 'sig' of length 'siglen' against public exponent - * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a - * SHA256 hash. - * Signature hash will be salted with 'idlen' bytes from 'id'. - * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature. - */ -int -schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, - const BIGNUM *grp_g, - const BIGNUM *g_x, const u_char *id, u_int idlen, - const u_char *sig, u_int siglen) -{ - Buffer b; - int ret = -1; - u_int rlen; - BIGNUM *r, *e; - - e = r = NULL; - if ((e = BN_new()) == NULL || - (r = BN_new()) == NULL) { - error("%s: BN_new", __func__); - goto out; - } - - /* Extract g^v and r from signature blob */ - buffer_init(&b); - buffer_append(&b, sig, siglen); - SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b), - "%s: sigblob", __func__)); - buffer_get_bignum2(&b, e); - buffer_get_bignum2(&b, r); - rlen = buffer_len(&b); - buffer_free(&b); - if (rlen != 0) { - error("%s: remaining bytes in signature %d", __func__, rlen); - goto out; - } - - ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256, - g_x, id, idlen, r, e); - out: - BN_clear_free(e); - BN_clear_free(r); - - return ret; -} - -/* Helper functions */ - -/* - * Generate uniformly distributed random number in range (1, high). - * Return number on success, NULL on failure. - */ -BIGNUM * -bn_rand_range_gt_one(const BIGNUM *high) -{ - BIGNUM *r, *tmp; - int success = -1; - - if ((tmp = BN_new()) == NULL) { - error("%s: BN_new", __func__); - return NULL; - } - if ((r = BN_new()) == NULL) { - error("%s: BN_new failed", __func__); - goto out; - } - if (BN_set_word(tmp, 2) != 1) { - error("%s: BN_set_word(tmp, 2)", __func__); - goto out; - } - if (BN_sub(tmp, high, tmp) == -1) { - error("%s: BN_sub failed (tmp = high - 2)", __func__); - goto out; - } - if (BN_rand_range(r, tmp) == -1) { - error("%s: BN_rand_range failed", __func__); - goto out; - } - if (BN_set_word(tmp, 2) != 1) { - error("%s: BN_set_word(tmp, 2)", __func__); - goto out; - } - if (BN_add(r, r, tmp) == -1) { - error("%s: BN_add failed (r = r + 2)", __func__); - goto out; - } - success = 0; - out: - BN_clear_free(tmp); - if (success == 0) - return r; - BN_clear_free(r); - return NULL; -} - -/* XXX convert all callers of this to use ssh_digest_memory() directly */ -/* - * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success, - * with digest via 'digestp' (caller to free) and length via 'lenp'. - * Returns -1 on failure. - */ -int -hash_buffer(const u_char *buf, u_int len, int hash_alg, - u_char **digestp, u_int *lenp) -{ - u_char digest[SSH_DIGEST_MAX_LENGTH]; - u_int digest_len = ssh_digest_bytes(hash_alg); - - if (digest_len == 0) { - error("%s: invalid hash", __func__); - return -1; - } - if (ssh_digest_memory(hash_alg, buf, len, digest, digest_len) != 0) { - error("%s: digest_memory failed", __func__); - return -1; - } - *digestp = xmalloc(digest_len); - *lenp = digest_len; - memcpy(*digestp, digest, *lenp); - bzero(digest, sizeof(digest)); - digest_len = 0; - return 0; -} - -/* print formatted string followed by bignum */ -void -debug3_bn(const BIGNUM *n, const char *fmt, ...) -{ - char *out, *h; - va_list args; - int ret; - - out = NULL; - va_start(args, fmt); - ret = vasprintf(&out, fmt, args); - va_end(args); - if (ret == -1 || out == NULL) - fatal("%s: vasprintf failed", __func__); - - if (n == NULL) - debug3("%s(null)", out); - else { - h = BN_bn2hex(n); - debug3("%s0x%s", out, h); - free(h); - } - free(out); -} - -/* print formatted string followed by buffer contents in hex */ -void -debug3_buf(const u_char *buf, u_int len, const char *fmt, ...) -{ - char *out, h[65]; - u_int i, j; - va_list args; - int ret; - - out = NULL; - va_start(args, fmt); - ret = vasprintf(&out, fmt, args); - va_end(args); - if (ret == -1 || out == NULL) - fatal("%s: vasprintf failed", __func__); - - debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : ""); - free(out); - if (buf == NULL) - return; - - *h = '\0'; - for (i = j = 0; i < len; i++) { - snprintf(h + j, sizeof(h) - j, "%02x", buf[i]); - j += 2; - if (j >= sizeof(h) - 1 || i == len - 1) { - debug3(" %s", h); - *h = '\0'; - j = 0; - } - } -} - -/* - * Construct a MODP group from hex strings p (which must be a safe - * prime) and g, automatically calculating subgroup q as (p / 2) - */ -struct modp_group * -modp_group_from_g_and_safe_p(const char *grp_g, const char *grp_p) -{ - struct modp_group *ret; - - ret = xcalloc(1, sizeof(*ret)); - ret->p = ret->q = ret->g = NULL; - if (BN_hex2bn(&ret->p, grp_p) == 0 || - BN_hex2bn(&ret->g, grp_g) == 0) - fatal("%s: BN_hex2bn", __func__); - /* Subgroup order is p/2 (p is a safe prime) */ - if ((ret->q = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - if (BN_rshift1(ret->q, ret->p) != 1) - fatal("%s: BN_rshift1", __func__); - - return ret; -} - -void -modp_group_free(struct modp_group *grp) -{ - if (grp->g != NULL) - BN_clear_free(grp->g); - if (grp->p != NULL) - BN_clear_free(grp->p); - if (grp->q != NULL) - BN_clear_free(grp->q); - bzero(grp, sizeof(*grp)); - free(grp); -} - -/* main() function for self-test */ - -#ifdef SCHNORR_MAIN -static void -schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q, - const BIGNUM *grp_g, const BIGNUM *x) -{ - BIGNUM *g_x; - u_char *sig; - u_int siglen; - BN_CTX *bn_ctx; - - if ((bn_ctx = BN_CTX_new()) == NULL) - fatal("%s: BN_CTX_new", __func__); - if ((g_x = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1) - fatal("%s: g_x", __func__); - if (schnorr_sign_buf(grp_p, grp_q, grp_g, x, g_x, "junk", 4, - &sig, &siglen)) - fatal("%s: schnorr_sign", __func__); - if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4, - sig, siglen) != 1) - fatal("%s: verify fail", __func__); - if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "JUNK", 4, - sig, siglen) != 0) - fatal("%s: verify should have failed (bad ID)", __func__); - sig[4] ^= 1; - if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4, - sig, siglen) != 0) - fatal("%s: verify should have failed (bit error)", __func__); - free(sig); - BN_free(g_x); - BN_CTX_free(bn_ctx); -} - -static void -schnorr_selftest(void) -{ - BIGNUM *x; - struct modp_group *grp; - u_int i; - char *hh; - - grp = jpake_default_group(); - if ((x = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - SCHNORR_DEBUG_BN((grp->p, "%s: grp->p = ", __func__)); - SCHNORR_DEBUG_BN((grp->q, "%s: grp->q = ", __func__)); - SCHNORR_DEBUG_BN((grp->g, "%s: grp->g = ", __func__)); - - /* [1, 20) */ - for (i = 1; i < 20; i++) { - printf("x = %u\n", i); - fflush(stdout); - if (BN_set_word(x, i) != 1) - fatal("%s: set x word", __func__); - schnorr_selftest_one(grp->p, grp->q, grp->g, x); - } - - /* 100 x random [0, p) */ - for (i = 0; i < 100; i++) { - if (BN_rand_range(x, grp->p) != 1) - fatal("%s: BN_rand_range", __func__); - hh = BN_bn2hex(x); - printf("x = (random) 0x%s\n", hh); - free(hh); - fflush(stdout); - schnorr_selftest_one(grp->p, grp->q, grp->g, x); - } - - /* [q-20, q) */ - if (BN_set_word(x, 20) != 1) - fatal("%s: BN_set_word (x = 20)", __func__); - if (BN_sub(x, grp->q, x) != 1) - fatal("%s: BN_sub (q - x)", __func__); - for (i = 0; i < 19; i++) { - hh = BN_bn2hex(x); - printf("x = (q - %d) 0x%s\n", 20 - i, hh); - free(hh); - fflush(stdout); - schnorr_selftest_one(grp->p, grp->q, grp->g, x); - if (BN_add(x, x, BN_value_one()) != 1) - fatal("%s: BN_add (x + 1)", __func__); - } - BN_free(x); -} - -int -main(int argc, char **argv) -{ - log_init(argv[0], SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_USER, 1); - - schnorr_selftest(); - return 0; -} -#endif - diff --git a/schnorr.h b/schnorr.h deleted file mode 100644 index e2405c102..000000000 --- a/schnorr.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD: schnorr.h,v 1.2 2014/01/09 23:20:00 djm Exp $ */ -/* - * Copyright (c) 2009 Damien Miller. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef SCHNORR_H -#define SCHNORR_H - -#include <sys/types.h> - -#include <openssl/bn.h> - -struct modp_group { - BIGNUM *p, *q, *g; -}; - -BIGNUM *bn_rand_range_gt_one(const BIGNUM *high); -int hash_buffer(const u_char *, u_int, int, u_char **, u_int *); -void debug3_bn(const BIGNUM *, const char *, ...) - __attribute__((__nonnull__ (2))) - __attribute__((format(printf, 2, 3))); -void debug3_buf(const u_char *, u_int, const char *, ...) - __attribute__((__nonnull__ (3))) - __attribute__((format(printf, 3, 4))); -struct modp_group *modp_group_from_g_and_safe_p(const char *, const char *); -void modp_group_free(struct modp_group *); - -/* Signature and verification functions */ -int -schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - int hash_alg, const BIGNUM *x, const BIGNUM *g_x, - const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p); -int -schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen, - u_char **sig, u_int *siglen); -int -schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g, - int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen, - const BIGNUM *r, const BIGNUM *e); -int -schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, - const BIGNUM *grp_g, - const BIGNUM *g_x, const u_char *id, u_int idlen, - const u_char *sig, u_int siglen); - -#endif /* JPAKE_H */ - diff --git a/servconf.c b/servconf.c index 9bcd05bf2..7ba65d51d 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.248 2013/12/06 13:39:49 markus Exp $ */ +/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * All rights reserved @@ -147,7 +147,6 @@ initialize_server_options(ServerOptions *options) options->chroot_directory = NULL; options->authorized_keys_command = NULL; options->authorized_keys_command_user = NULL; - options->zero_knowledge_password_authentication = -1; options->revoked_keys_file = NULL; options->trusted_user_ca_keys = NULL; options->authorized_principals_file = NULL; @@ -295,8 +294,6 @@ fill_default_server_options(ServerOptions *options) } if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; - if (options->zero_knowledge_password_authentication == -1) - options->zero_knowledge_password_authentication = 0; if (options->ip_qos_interactive == -1) options->ip_qos_interactive = IPTOS_LOWDELAY; if (options->ip_qos_bulk == -1) @@ -346,7 +343,7 @@ typedef enum { sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - sZeroKnowledgePasswordAuthentication, sHostCertificate, + sHostCertificate, sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sKexAlgorithms, sIPQoS, sVersionAddendum, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, @@ -418,11 +415,6 @@ static struct { { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ -#ifdef JPAKE - { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL }, -#else - { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL }, -#endif { "checkmail", sDeprecated, SSHCFG_GLOBAL }, { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, @@ -1102,10 +1094,6 @@ process_server_config_line(ServerOptions *options, char *line, intptr = &options->password_authentication; goto parse_flag; - case sZeroKnowledgePasswordAuthentication: - intptr = &options->zero_knowledge_password_authentication; - goto parse_flag; - case sKbdInteractiveAuthentication: intptr = &options->kbd_interactive_authentication; goto parse_flag; @@ -1767,7 +1755,6 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(hostbased_authentication); M_CP_INTOPT(hostbased_uses_name_from_packet_only); M_CP_INTOPT(kbd_interactive_authentication); - M_CP_INTOPT(zero_knowledge_password_authentication); M_CP_INTOPT(permit_root_login); M_CP_INTOPT(permit_empty_passwd); @@ -2010,10 +1997,6 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); #endif -#ifdef JPAKE - dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication, - o->zero_knowledge_password_authentication); -#endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, o->kbd_interactive_authentication); diff --git a/servconf.h b/servconf.h index 8812c5aab..752d1c5ae 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.111 2013/12/05 01:16:41 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */ /* * Author: Tatu Ylonen <ylo@cs.hut.fi> @@ -117,8 +117,6 @@ typedef struct { * authentication. */ int kbd_interactive_authentication; /* If true, permit */ int challenge_response_authentication; - int zero_knowledge_password_authentication; - /* If true, permit jpake auth */ int permit_empty_passwd; /* If false, do not permit empty * passwords. */ int permit_user_env; /* If true, read ~/.ssh/environment */ @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh2.h,v 1.14 2010/08/31 11:54:45 djm Exp $ */ +/* $OpenBSD: ssh2.h,v 1.15 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -115,12 +115,6 @@ #define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 #define SSH2_MSG_USERAUTH_INFO_REQUEST 60 #define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 -#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1 60 -#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1 61 -#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2 62 -#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2 63 -#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM 64 -#define SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM 65 /* connection protocol: generic */ diff --git a/sshconnect2.c b/sshconnect2.c index 8acffc5c3..8343db10e 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshconnect2.c,v 1.201 2014/01/09 23:20:00 djm Exp $ */ +/* $OpenBSD: sshconnect2.c,v 1.202 2014/01/29 06:18:35 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved. @@ -70,8 +70,6 @@ #include "pathnames.h" #include "uidswap.h" #include "hostfile.h" -#include "schnorr.h" -#include "jpake.h" #ifdef GSSAPI #include "ssh-gss.h" @@ -289,18 +287,12 @@ void input_userauth_error(int, u_int32_t, void *); void input_userauth_info_req(int, u_int32_t, void *); void input_userauth_pk_ok(int, u_int32_t, void *); void input_userauth_passwd_changereq(int, u_int32_t, void *); -void input_userauth_jpake_server_step1(int, u_int32_t, void *); -void input_userauth_jpake_server_step2(int, u_int32_t, void *); -void input_userauth_jpake_server_confirm(int, u_int32_t, void *); int userauth_none(Authctxt *); int userauth_pubkey(Authctxt *); int userauth_passwd(Authctxt *); int userauth_kbdint(Authctxt *); int userauth_hostbased(Authctxt *); -int userauth_jpake(Authctxt *); - -void userauth_jpake_cleanup(Authctxt *); #ifdef GSSAPI int userauth_gssapi(Authctxt *authctxt); @@ -340,13 +332,6 @@ Authmethod authmethods[] = { NULL, &options.pubkey_authentication, NULL}, -#ifdef JPAKE - {"jpake-01@openssh.com", - userauth_jpake, - userauth_jpake_cleanup, - &options.zero_knowledge_password_authentication, - &options.batch_mode}, -#endif {"keyboard-interactive", userauth_kbdint, NULL, @@ -965,209 +950,6 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) &input_userauth_passwd_changereq); } -#ifdef JPAKE -static char * -pw_encrypt(const char *password, const char *crypt_scheme, const char *salt) -{ - /* OpenBSD crypt(3) handles all of these */ - if (strcmp(crypt_scheme, "crypt") == 0 || - strcmp(crypt_scheme, "bcrypt") == 0 || - strcmp(crypt_scheme, "md5crypt") == 0 || - strcmp(crypt_scheme, "crypt-extended") == 0) - return xstrdup(crypt(password, salt)); - error("%s: unsupported password encryption scheme \"%.100s\"", - __func__, crypt_scheme); - return NULL; -} - -static BIGNUM * -jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme, - const char *salt) -{ - char prompt[256], *password, *crypted; - u_char *secret; - u_int secret_len; - BIGNUM *ret; - - snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ", - authctxt->server_user, authctxt->host); - password = read_passphrase(prompt, 0); - - if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) { - logit("Disabling %s authentication", authctxt->method->name); - authctxt->method->enabled = NULL; - /* Continue with an empty password to fail gracefully */ - crypted = xstrdup(""); - } - -#ifdef JPAKE_DEBUG - debug3("%s: salt = %s", __func__, salt); - debug3("%s: scheme = %s", __func__, crypt_scheme); - debug3("%s: crypted = %s", __func__, crypted); -#endif - - if (hash_buffer(crypted, strlen(crypted), SSH_DIGEST_SHA1, - &secret, &secret_len) != 0) - fatal("%s: hash_buffer", __func__); - - bzero(password, strlen(password)); - bzero(crypted, strlen(crypted)); - free(password); - free(crypted); - - if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL) - fatal("%s: BN_bin2bn (secret)", __func__); - bzero(secret, secret_len); - free(secret); - - return ret; -} - -/* ARGSUSED */ -void -input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->methoddata; - u_char *x3_proof, *x4_proof, *x2_s_proof; - u_int x3_proof_len, x4_proof_len, x2_s_proof_len; - char *crypt_scheme, *salt; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL); - - if ((pctx->g_x3 = BN_new()) == NULL || - (pctx->g_x4 = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - /* Fetch step 1 values */ - crypt_scheme = packet_get_string(NULL); - salt = packet_get_string(NULL); - pctx->server_id = packet_get_string(&pctx->server_id_len); - packet_get_bignum2(pctx->g_x3); - packet_get_bignum2(pctx->g_x4); - x3_proof = packet_get_string(&x3_proof_len); - x4_proof = packet_get_string(&x4_proof_len); - packet_check_eom(); - - JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__)); - - /* Obtain password and derive secret */ - pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt); - bzero(crypt_scheme, strlen(crypt_scheme)); - bzero(salt, strlen(salt)); - free(crypt_scheme); - free(salt); - JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__)); - - /* Calculate step 2 values */ - jpake_step2(pctx->grp, pctx->s, pctx->g_x1, - pctx->g_x3, pctx->g_x4, pctx->x2, - pctx->server_id, pctx->server_id_len, - pctx->client_id, pctx->client_id_len, - x3_proof, x3_proof_len, - x4_proof, x4_proof_len, - &pctx->a, - &x2_s_proof, &x2_s_proof_len); - - bzero(x3_proof, x3_proof_len); - bzero(x4_proof, x4_proof_len); - free(x3_proof); - free(x4_proof); - - JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__)); - - /* Send values for step 2 */ - packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2); - packet_put_bignum2(pctx->a); - packet_put_string(x2_s_proof, x2_s_proof_len); - packet_send(); - - bzero(x2_s_proof, x2_s_proof_len); - free(x2_s_proof); - - /* Expect step 2 packet from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, - input_userauth_jpake_server_step2); -} - -/* ARGSUSED */ -void -input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->methoddata; - u_char *x4_s_proof; - u_int x4_s_proof_len; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL); - - if ((pctx->b = BN_new()) == NULL) - fatal("%s: BN_new", __func__); - - /* Fetch step 2 values */ - packet_get_bignum2(pctx->b); - x4_s_proof = packet_get_string(&x4_s_proof_len); - packet_check_eom(); - - JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__)); - - /* Derive shared key and calculate confirmation hash */ - jpake_key_confirm(pctx->grp, pctx->s, pctx->b, - pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4, - pctx->client_id, pctx->client_id_len, - pctx->server_id, pctx->server_id_len, - session_id2, session_id2_len, - x4_s_proof, x4_s_proof_len, - &pctx->k, - &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len); - - bzero(x4_s_proof, x4_s_proof_len); - free(x4_s_proof); - - JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__)); - - /* Send key confirmation proof */ - packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM); - packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len); - packet_send(); - - /* Expect confirmation from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, - input_userauth_jpake_server_confirm); -} - -/* ARGSUSED */ -void -input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt) -{ - Authctxt *authctxt = ctxt; - struct jpake_ctx *pctx = authctxt->methoddata; - - /* Disable this message */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL); - - pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len); - packet_check_eom(); - - JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__)); - - /* Verify expected confirmation hash */ - if (jpake_check_confirm(pctx->k, - pctx->server_id, pctx->server_id_len, - session_id2, session_id2_len, - pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1) - debug("%s: %s success", __func__, authctxt->method->name); - else { - debug("%s: confirmation mismatch", __func__); - /* XXX stash this so if auth succeeds then we can warn/kill */ - } - - userauth_jpake_cleanup(authctxt); -} -#endif /* JPAKE */ - static int identity_sign(Identity *id, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) @@ -1783,79 +1565,6 @@ userauth_hostbased(Authctxt *authctxt) return 1; } -#ifdef JPAKE -int -userauth_jpake(Authctxt *authctxt) -{ - struct jpake_ctx *pctx; - u_char *x1_proof, *x2_proof; - u_int x1_proof_len, x2_proof_len; - static int attempt = 0; /* XXX share with userauth_password's? */ - - if (attempt++ >= options.number_of_password_prompts) - return 0; - if (attempt != 1) - error("Permission denied, please try again."); - - if (authctxt->methoddata != NULL) - fatal("%s: authctxt->methoddata already set (%p)", - __func__, authctxt->methoddata); - - authctxt->methoddata = pctx = jpake_new(); - - /* - * Send request immediately, to get the protocol going while - * we do the initial computations. - */ - packet_start(SSH2_MSG_USERAUTH_REQUEST); - packet_put_cstring(authctxt->server_user); - packet_put_cstring(authctxt->service); - packet_put_cstring(authctxt->method->name); - packet_send(); - packet_write_wait(); - - jpake_step1(pctx->grp, - &pctx->client_id, &pctx->client_id_len, - &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2, - &x1_proof, &x1_proof_len, - &x2_proof, &x2_proof_len); - - JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__)); - - packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1); - packet_put_string(pctx->client_id, pctx->client_id_len); - packet_put_bignum2(pctx->g_x1); - packet_put_bignum2(pctx->g_x2); - packet_put_string(x1_proof, x1_proof_len); - packet_put_string(x2_proof, x2_proof_len); - packet_send(); - - bzero(x1_proof, x1_proof_len); - bzero(x2_proof, x2_proof_len); - free(x1_proof); - free(x2_proof); - - /* Expect step 1 packet from peer */ - dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, - input_userauth_jpake_server_step1); - dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, - &input_userauth_success_unexpected); - - return 1; -} - -void -userauth_jpake_cleanup(Authctxt *authctxt) -{ - debug3("%s: clean up", __func__); - if (authctxt->methoddata != NULL) { - jpake_free(authctxt->methoddata); - authctxt->methoddata = NULL; - } - dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); -} -#endif /* JPAKE */ - /* find auth method */ /* |