summaryrefslogtreecommitdiff
path: root/monitor.c
diff options
context:
space:
mode:
authordjm <djm>2008-11-05 05:20:46 +0000
committerdjm <djm>2008-11-05 05:20:46 +0000
commitccb18169086ece13da97d2dd9438f476fb4f3a31 (patch)
treef014d9bea12b814e3bb606717aa1c3d84289b208 /monitor.c
parent2035911cdc3de9e81bc2746b3b5152a067d42f5f (diff)
downloadopenssh-ccb18169086ece13da97d2dd9438f476fb4f3a31.tar.gz
- djm@cvs.openbsd.org 2008/11/04 08:22:13
[auth.h auth2.c monitor.c monitor.h monitor_wrap.c monitor_wrap.h] [readconf.c readconf.h servconf.c servconf.h ssh2.h ssh_config.5] [sshconnect2.c sshd_config.5 jpake.c jpake.h schnorr.c auth2-jpake.c] [Makefile.in] Add support for an experimental zero-knowledge password authentication method using the J-PAKE protocol described in F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling", 16th Workshop on Security Protocols, Cambridge, April 2008. This method allows password-based authentication without exposing the password to the server. Instead, the client and server exchange cryptographic proofs to demonstrate of knowledge of the password while revealing nothing useful to an attacker or compromised endpoint. This is experimental, work-in-progress code and is presently compiled-time disabled (turn on -DJPAKE in Makefile.inc). "just commit it. It isn't too intrusive." deraadt@
Diffstat (limited to 'monitor.c')
-rw-r--r--monitor.c227
1 files changed, 226 insertions, 1 deletions
diff --git a/monitor.c b/monitor.c
index 73cf6bc9..39deedc8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.99 2008/07/10 18:08:11 markus Exp $ */
+/* $OpenBSD: monitor.c,v 1.100 2008/11/04 08:22:13 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -87,6 +87,7 @@
#include "misc.h"
#include "compat.h"
#include "ssh2.h"
+#include "jpake.h"
#ifdef GSSAPI
static Gssctxt *gsscontext = NULL;
@@ -149,6 +150,11 @@ 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 *);
@@ -234,6 +240,13 @@ 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}
};
@@ -379,6 +392,15 @@ 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)
@@ -1969,3 +1991,206 @@ mm_answer_gss_userok(int sock, Buffer *m)
return (authenticated);
}
#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);
+ xfree(x3_proof);
+ xfree(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));
+ xfree(hash_scheme);
+ xfree(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);
+ xfree(x1_proof);
+ xfree(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);
+ xfree(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);
+ xfree(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 */