summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Makefile.in6
-rw-r--r--auth.h6
-rw-r--r--auth2-jpake.c563
-rw-r--r--auth2.c11
-rw-r--r--jpake.c456
-rw-r--r--jpake.h114
-rw-r--r--monitor.c226
-rw-r--r--monitor.h7
-rw-r--r--monitor_wrap.c165
-rw-r--r--monitor_wrap.h22
-rw-r--r--readconf.c17
-rw-r--r--readconf.h3
-rw-r--r--schnorr.c668
-rw-r--r--schnorr.h60
-rw-r--r--servconf.c21
-rw-r--r--servconf.h4
-rw-r--r--ssh2.h8
-rw-r--r--sshconnect2.c293
19 files changed, 22 insertions, 2633 deletions
diff --git a/ChangeLog b/ChangeLog
index 7a4db10a6..25d9c9aff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,11 @@
20 they are equivalent, but SUSv2 describes the latter as having undefined 20 they are equivalent, but SUSv2 describes the latter as having undefined
21 behaviour; from portable; ok dtucker 21 behaviour; from portable; ok dtucker
22 (Id sync only; change is already in portable) 22 (Id sync only; change is already in portable)
23 - djm@cvs.openbsd.org 2014/01/29 06:18:35
24 [Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c]
25 [monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h]
26 [schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c]
27 remove experimental, never-enabled JPAKE code; ok markus@
23 28
2420140131 2920140131
25 - (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2) 30 - (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 @@
1# $Id: Makefile.in,v 1.355 2014/02/04 00:07:14 djm Exp $ 1# $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $
2 2
3# uncomment if you run a non bourne compatable shell. Ie. csh 3# uncomment if you run a non bourne compatable shell. Ie. csh
4#SHELL = @SH@ 4#SHELL = @SH@
@@ -73,7 +73,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \
73 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ 73 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
74 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ 74 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
75 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ 75 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
76 jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \ 76 ssh-pkcs11.o krl.o smult_curve25519_ref.o \
77 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ 77 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
78 ssh-ed25519.o digest-openssl.o hmac.o \ 78 ssh-ed25519.o digest-openssl.o hmac.o \
79 sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o 79 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 \
88 auth.o auth1.o auth2.o auth-options.o session.o \ 88 auth.o auth1.o auth2.o auth-options.o session.o \
89 auth-chall.o auth2-chall.o groupaccess.o \ 89 auth-chall.o auth2-chall.o groupaccess.o \
90 auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ 90 auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
91 auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \ 91 auth2-none.o auth2-passwd.o auth2-pubkey.o \
92 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ 92 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
93 kexc25519s.o auth-krb5.o \ 93 kexc25519s.o auth-krb5.o \
94 auth2-gss.o gss-serv.o gss-serv-krb5.o \ 94 auth2-gss.o gss-serv.o gss-serv-krb5.o \
diff --git a/auth.h b/auth.h
index 80f089869..124e59743 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.76 2013/07/19 07:37:48 markus Exp $ */ 1/* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -61,7 +61,6 @@ struct Authctxt {
61 char *style; 61 char *style;
62 void *kbdintctxt; 62 void *kbdintctxt;
63 char *info; /* Extra info for next auth_log */ 63 char *info; /* Extra info for next auth_log */
64 void *jpake_ctx;
65#ifdef BSD_AUTH 64#ifdef BSD_AUTH
66 auth_session_t *as; 65 auth_session_t *as;
67#endif 66#endif
@@ -175,9 +174,6 @@ int bsdauth_respond(void *, u_int, char **);
175int skey_query(void *, char **, char **, u_int *, char ***, u_int **); 174int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
176int skey_respond(void *, u_int, char **); 175int skey_respond(void *, u_int, char **);
177 176
178void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
179void auth2_jpake_stop(Authctxt *);
180
181int allowed_user(struct passwd *); 177int allowed_user(struct passwd *);
182struct passwd * getpwnamallow(const char *user); 178struct passwd * getpwnamallow(const char *user);
183 179
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 @@
1/* $OpenBSD: auth2-jpake.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */
2/*
3 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * Server side of zero-knowledge password auth using J-PAKE protocol
20 * as described in:
21 *
22 * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
23 * 16th Workshop on Security Protocols, Cambridge, April 2008
24 *
25 * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
26 */
27
28#ifdef JPAKE
29
30#include <sys/types.h>
31#include <sys/param.h>
32
33#include <pwd.h>
34#include <stdio.h>
35#include <string.h>
36#include <login_cap.h>
37
38#include <openssl/bn.h>
39#include <openssl/evp.h>
40
41#include "xmalloc.h"
42#include "ssh2.h"
43#include "key.h"
44#include "hostfile.h"
45#include "auth.h"
46#include "buffer.h"
47#include "packet.h"
48#include "dispatch.h"
49#include "log.h"
50#include "servconf.h"
51#include "auth-options.h"
52#include "canohost.h"
53#ifdef GSSAPI
54#include "ssh-gss.h"
55#endif
56#include "monitor_wrap.h"
57
58#include "schnorr.h"
59#include "jpake.h"
60
61/*
62 * XXX options->permit_empty_passwd (at the moment, they will be refused
63 * anyway because they will mismatch on fake salt.
64 */
65
66/* Dispatch handlers */
67static void input_userauth_jpake_client_step1(int, u_int32_t, void *);
68static void input_userauth_jpake_client_step2(int, u_int32_t, void *);
69static void input_userauth_jpake_client_confirm(int, u_int32_t, void *);
70
71static int auth2_jpake_start(Authctxt *);
72
73/* import */
74extern ServerOptions options;
75extern u_char *session_id2;
76extern u_int session_id2_len;
77
78/*
79 * Attempt J-PAKE authentication.
80 */
81static int
82userauth_jpake(Authctxt *authctxt)
83{
84 int authenticated = 0;
85
86 packet_check_eom();
87
88 debug("jpake-01@openssh.com requested");
89
90 if (authctxt->user != NULL) {
91 if (authctxt->jpake_ctx == NULL)
92 authctxt->jpake_ctx = jpake_new();
93 if (options.zero_knowledge_password_authentication)
94 authenticated = auth2_jpake_start(authctxt);
95 }
96
97 return authenticated;
98}
99
100Authmethod method_jpake = {
101 "jpake-01@openssh.com",
102 userauth_jpake,
103 &options.zero_knowledge_password_authentication
104};
105
106/* Clear context and callbacks */
107void
108auth2_jpake_stop(Authctxt *authctxt)
109{
110 /* unregister callbacks */
111 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
112 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
113 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
114 if (authctxt->jpake_ctx != NULL) {
115 jpake_free(authctxt->jpake_ctx);
116 authctxt->jpake_ctx = NULL;
117 }
118}
119
120/* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */
121static int
122valid_crypt_salt(int c)
123{
124 if (c >= 'A' && c <= 'Z')
125 return 1;
126 if (c >= 'a' && c <= 'z')
127 return 1;
128 if (c >= '.' && c <= '9')
129 return 1;
130 return 0;
131}
132
133/*
134 * Derive fake salt as H(username || first_private_host_key)
135 * This provides relatively stable fake salts for non-existent
136 * users and avoids the jpake method becoming an account validity
137 * oracle.
138 */
139static void
140derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
141{
142 u_char *digest;
143 u_int digest_len;
144 Buffer b;
145 Key *k;
146
147 buffer_init(&b);
148 buffer_put_cstring(&b, username);
149 if ((k = get_hostkey_by_index(0)) == NULL ||
150 (k->flags & KEY_FLAG_EXT))
151 fatal("%s: no hostkeys", __func__);
152 switch (k->type) {
153 case KEY_RSA1:
154 case KEY_RSA:
155 if (k->rsa->p == NULL || k->rsa->q == NULL)
156 fatal("%s: RSA key missing p and/or q", __func__);
157 buffer_put_bignum2(&b, k->rsa->p);
158 buffer_put_bignum2(&b, k->rsa->q);
159 break;
160 case KEY_DSA:
161 if (k->dsa->priv_key == NULL)
162 fatal("%s: DSA key missing priv_key", __func__);
163 buffer_put_bignum2(&b, k->dsa->priv_key);
164 break;
165 case KEY_ECDSA:
166 if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
167 fatal("%s: ECDSA key missing priv_key", __func__);
168 buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
169 break;
170 default:
171 fatal("%s: unknown key type %d", __func__, k->type);
172 }
173 if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
174 &digest, &digest_len) != 0)
175 fatal("%s: hash_buffer", __func__);
176 buffer_free(&b);
177 if (len > digest_len)
178 fatal("%s: not enough bytes for rawsalt (want %u have %u)",
179 __func__, len, digest_len);
180 memcpy(rawsalt, digest, len);
181 bzero(digest, digest_len);
182 free(digest);
183}
184
185/* ASCII an integer [0, 64) for inclusion in a password/salt */
186static char
187pw_encode64(u_int i64)
188{
189 const u_char e64[] =
190 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
191 return e64[i64 % 64];
192}
193
194/* Generate ASCII salt bytes for user */
195static char *
196makesalt(u_int want, const char *user)
197{
198 u_char rawsalt[32];
199 static char ret[33];
200 u_int i;
201
202 if (want > sizeof(ret) - 1)
203 fatal("%s: want %u", __func__, want);
204
205 derive_rawsalt(user, rawsalt, sizeof(rawsalt));
206 bzero(ret, sizeof(ret));
207 for (i = 0; i < want; i++)
208 ret[i] = pw_encode64(rawsalt[i]);
209 bzero(rawsalt, sizeof(rawsalt));
210
211 return ret;
212}
213
214/*
215 * Select the system's default password hashing scheme and generate
216 * a stable fake salt under it for use by a non-existent account.
217 * Prevents jpake method being used to infer the validity of accounts.
218 */
219static void
220fake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme)
221{
222 char *rounds_s, *style;
223 long long rounds;
224 login_cap_t *lc;
225
226
227 if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL &&
228 (lc = login_getclass(NULL)) == NULL)
229 fatal("%s: login_getclass failed", __func__);
230 style = login_getcapstr(lc, "localcipher", NULL, NULL);
231 if (style == NULL)
232 style = xstrdup("blowfish,6");
233 login_close(lc);
234
235 if ((rounds_s = strchr(style, ',')) != NULL)
236 *rounds_s++ = '\0';
237 rounds = strtonum(rounds_s, 1, 1<<31, NULL);
238
239 if (strcmp(style, "md5") == 0) {
240 xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user));
241 *scheme = xstrdup("md5");
242 } else if (strcmp(style, "old") == 0) {
243 *salt = xstrdup(makesalt(2, authctxt->user));
244 *scheme = xstrdup("crypt");
245 } else if (strcmp(style, "newsalt") == 0) {
246 rounds = MAX(rounds, 7250);
247 rounds = MIN(rounds, (1<<24) - 1);
248 xasprintf(salt, "_%c%c%c%c%s",
249 pw_encode64(rounds), pw_encode64(rounds >> 6),
250 pw_encode64(rounds >> 12), pw_encode64(rounds >> 18),
251 makesalt(4, authctxt->user));
252 *scheme = xstrdup("crypt-extended");
253 } else {
254 /* Default to blowfish */
255 rounds = MAX(rounds, 3);
256 rounds = MIN(rounds, 31);
257 xasprintf(salt, "$2a$%02lld$%s", rounds,
258 makesalt(22, authctxt->user));
259 *scheme = xstrdup("bcrypt");
260 }
261 free(style);
262 debug3("%s: fake %s salt for user %s: %s",
263 __func__, *scheme, authctxt->user, *salt);
264}
265
266/*
267 * Fetch password hashing scheme, password salt and derive shared secret
268 * for user. If user does not exist, a fake but stable and user-unique
269 * salt will be returned.
270 */
271void
272auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
273 char **hash_scheme, char **salt)
274{
275 char *cp;
276 u_char *secret;
277 u_int secret_len, salt_len;
278
279#ifdef JPAKE_DEBUG
280 debug3("%s: valid %d pw %.5s...", __func__,
281 authctxt->valid, authctxt->pw->pw_passwd);
282#endif
283
284 *salt = NULL;
285 *hash_scheme = NULL;
286 if (authctxt->valid) {
287 if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 &&
288 strlen(authctxt->pw->pw_passwd) > 28) {
289 /*
290 * old-variant bcrypt:
291 * "$2$", 2 digit rounds, "$", 22 bytes salt
292 */
293 salt_len = 3 + 2 + 1 + 22 + 1;
294 *salt = xmalloc(salt_len);
295 strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
296 *hash_scheme = xstrdup("bcrypt");
297 } else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 &&
298 strlen(authctxt->pw->pw_passwd) > 29) {
299 /*
300 * current-variant bcrypt:
301 * "$2a$", 2 digit rounds, "$", 22 bytes salt
302 */
303 salt_len = 4 + 2 + 1 + 22 + 1;
304 *salt = xmalloc(salt_len);
305 strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
306 *hash_scheme = xstrdup("bcrypt");
307 } else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 &&
308 strlen(authctxt->pw->pw_passwd) > 5) {
309 /*
310 * md5crypt:
311 * "$1$", salt until "$"
312 */
313 cp = strchr(authctxt->pw->pw_passwd + 3, '$');
314 if (cp != NULL) {
315 salt_len = (cp - authctxt->pw->pw_passwd) + 1;
316 *salt = xmalloc(salt_len);
317 strlcpy(*salt, authctxt->pw->pw_passwd,
318 salt_len);
319 *hash_scheme = xstrdup("md5crypt");
320 }
321 } else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 &&
322 strlen(authctxt->pw->pw_passwd) > 9) {
323 /*
324 * BSDI extended crypt:
325 * "_", 4 digits count, 4 chars salt
326 */
327 salt_len = 1 + 4 + 4 + 1;
328 *salt = xmalloc(salt_len);
329 strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
330 *hash_scheme = xstrdup("crypt-extended");
331 } else if (strlen(authctxt->pw->pw_passwd) == 13 &&
332 valid_crypt_salt(authctxt->pw->pw_passwd[0]) &&
333 valid_crypt_salt(authctxt->pw->pw_passwd[1])) {
334 /*
335 * traditional crypt:
336 * 2 chars salt
337 */
338 salt_len = 2 + 1;
339 *salt = xmalloc(salt_len);
340 strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
341 *hash_scheme = xstrdup("crypt");
342 }
343 if (*salt == NULL) {
344 debug("%s: unrecognised crypt scheme for user %s",
345 __func__, authctxt->pw->pw_name);
346 }
347 }
348 if (*salt == NULL)
349 fake_salt_and_scheme(authctxt, salt, hash_scheme);
350
351 if (hash_buffer(authctxt->pw->pw_passwd,
352 strlen(authctxt->pw->pw_passwd), EVP_sha256(),
353 &secret, &secret_len) != 0)
354 fatal("%s: hash_buffer", __func__);
355 if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL)
356 fatal("%s: BN_bin2bn (secret)", __func__);
357#ifdef JPAKE_DEBUG
358 debug3("%s: salt = %s (len %u)", __func__,
359 *salt, (u_int)strlen(*salt));
360 debug3("%s: scheme = %s", __func__, *hash_scheme);
361 JPAKE_DEBUG_BN((*s, "%s: s = ", __func__));
362#endif
363 bzero(secret, secret_len);
364 free(secret);
365}
366
367/*
368 * Begin authentication attempt.
369 * Note, sets authctxt->postponed while in subprotocol
370 */
371static int
372auth2_jpake_start(Authctxt *authctxt)
373{
374 struct jpake_ctx *pctx = authctxt->jpake_ctx;
375 u_char *x3_proof, *x4_proof;
376 u_int x3_proof_len, x4_proof_len;
377 char *salt, *hash_scheme;
378
379 debug("%s: start", __func__);
380
381 PRIVSEP(jpake_step1(pctx->grp,
382 &pctx->server_id, &pctx->server_id_len,
383 &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
384 &x3_proof, &x3_proof_len,
385 &x4_proof, &x4_proof_len));
386
387 PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s,
388 &hash_scheme, &salt));
389
390 if (!use_privsep)
391 JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
392
393 packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1);
394 packet_put_cstring(hash_scheme);
395 packet_put_cstring(salt);
396 packet_put_string(pctx->server_id, pctx->server_id_len);
397 packet_put_bignum2(pctx->g_x3);
398 packet_put_bignum2(pctx->g_x4);
399 packet_put_string(x3_proof, x3_proof_len);
400 packet_put_string(x4_proof, x4_proof_len);
401 packet_send();
402 packet_write_wait();
403
404 bzero(hash_scheme, strlen(hash_scheme));
405 bzero(salt, strlen(salt));
406 free(hash_scheme);
407 free(salt);
408 bzero(x3_proof, x3_proof_len);
409 bzero(x4_proof, x4_proof_len);
410 free(x3_proof);
411 free(x4_proof);
412
413 /* Expect step 1 packet from peer */
414 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1,
415 input_userauth_jpake_client_step1);
416
417 authctxt->postponed = 1;
418 return 0;
419}
420
421/* ARGSUSED */
422static void
423input_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt)
424{
425 Authctxt *authctxt = ctxt;
426 struct jpake_ctx *pctx = authctxt->jpake_ctx;
427 u_char *x1_proof, *x2_proof, *x4_s_proof;
428 u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
429
430 /* Disable this message */
431 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
432
433 /* Fetch step 1 values */
434 if ((pctx->g_x1 = BN_new()) == NULL ||
435 (pctx->g_x2 = BN_new()) == NULL)
436 fatal("%s: BN_new", __func__);
437 pctx->client_id = packet_get_string(&pctx->client_id_len);
438 packet_get_bignum2(pctx->g_x1);
439 packet_get_bignum2(pctx->g_x2);
440 x1_proof = packet_get_string(&x1_proof_len);
441 x2_proof = packet_get_string(&x2_proof_len);
442 packet_check_eom();
443
444 if (!use_privsep)
445 JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
446
447 PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
448 pctx->g_x1, pctx->g_x2, pctx->x4,
449 pctx->client_id, pctx->client_id_len,
450 pctx->server_id, pctx->server_id_len,
451 x1_proof, x1_proof_len,
452 x2_proof, x2_proof_len,
453 &pctx->b,
454 &x4_s_proof, &x4_s_proof_len));
455
456 bzero(x1_proof, x1_proof_len);
457 bzero(x2_proof, x2_proof_len);
458 free(x1_proof);
459 free(x2_proof);
460
461 if (!use_privsep)
462 JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
463
464 /* Send values for step 2 */
465 packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2);
466 packet_put_bignum2(pctx->b);
467 packet_put_string(x4_s_proof, x4_s_proof_len);
468 packet_send();
469 packet_write_wait();
470
471 bzero(x4_s_proof, x4_s_proof_len);
472 free(x4_s_proof);
473
474 /* Expect step 2 packet from peer */
475 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2,
476 input_userauth_jpake_client_step2);
477}
478
479/* ARGSUSED */
480static void
481input_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt)
482{
483 Authctxt *authctxt = ctxt;
484 struct jpake_ctx *pctx = authctxt->jpake_ctx;
485 u_char *x2_s_proof;
486 u_int x2_s_proof_len;
487
488 /* Disable this message */
489 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
490
491 if ((pctx->a = BN_new()) == NULL)
492 fatal("%s: BN_new", __func__);
493
494 /* Fetch step 2 values */
495 packet_get_bignum2(pctx->a);
496 x2_s_proof = packet_get_string(&x2_s_proof_len);
497 packet_check_eom();
498
499 if (!use_privsep)
500 JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
501
502 /* Derive shared key and calculate confirmation hash */
503 PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
504 pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
505 pctx->server_id, pctx->server_id_len,
506 pctx->client_id, pctx->client_id_len,
507 session_id2, session_id2_len,
508 x2_s_proof, x2_s_proof_len,
509 &pctx->k,
510 &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len));
511
512 bzero(x2_s_proof, x2_s_proof_len);
513 free(x2_s_proof);
514
515 if (!use_privsep)
516 JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
517
518 /* Send key confirmation proof */
519 packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM);
520 packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
521 packet_send();
522 packet_write_wait();
523
524 /* Expect confirmation from peer */
525 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM,
526 input_userauth_jpake_client_confirm);
527}
528
529/* ARGSUSED */
530static void
531input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
532{
533 Authctxt *authctxt = ctxt;
534 struct jpake_ctx *pctx = authctxt->jpake_ctx;
535 int authenticated = 0;
536
537 /* Disable this message */
538 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
539
540 pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len);
541 packet_check_eom();
542
543 if (!use_privsep)
544 JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
545
546 /* Verify expected confirmation hash */
547 if (PRIVSEP(jpake_check_confirm(pctx->k,
548 pctx->client_id, pctx->client_id_len,
549 session_id2, session_id2_len,
550 pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1)
551 authenticated = authctxt->valid ? 1 : 0;
552 else
553 debug("%s: confirmation mismatch", __func__);
554
555 /* done */
556 authctxt->postponed = 0;
557 jpake_free(authctxt->jpake_ctx);
558 authctxt->jpake_ctx = NULL;
559 userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
560}
561
562#endif /* JPAKE */
563
diff --git a/auth2.c b/auth2.c
index f0cab8cc0..a5490c009 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */ 1/* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -71,9 +71,6 @@ extern Authmethod method_hostbased;
71#ifdef GSSAPI 71#ifdef GSSAPI
72extern Authmethod method_gssapi; 72extern Authmethod method_gssapi;
73#endif 73#endif
74#ifdef JPAKE
75extern Authmethod method_jpake;
76#endif
77 74
78Authmethod *authmethods[] = { 75Authmethod *authmethods[] = {
79 &method_none, 76 &method_none,
@@ -81,9 +78,6 @@ Authmethod *authmethods[] = {
81#ifdef GSSAPI 78#ifdef GSSAPI
82 &method_gssapi, 79 &method_gssapi,
83#endif 80#endif
84#ifdef JPAKE
85 &method_jpake,
86#endif
87 &method_passwd, 81 &method_passwd,
88 &method_kbdint, 82 &method_kbdint,
89 &method_hostbased, 83 &method_hostbased,
@@ -270,9 +264,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
270 } 264 }
271 /* reset state */ 265 /* reset state */
272 auth2_challenge_stop(authctxt); 266 auth2_challenge_stop(authctxt);
273#ifdef JPAKE
274 auth2_jpake_stop(authctxt);
275#endif
276 267
277#ifdef GSSAPI 268#ifdef GSSAPI
278 /* XXX move to auth2_gssapi_stop() */ 269 /* 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 @@
1/* $OpenBSD: jpake.c,v 1.8 2013/05/17 00:13:13 djm Exp $ */
2/*
3 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * Shared components of zero-knowledge password auth using J-PAKE protocol
20 * as described in:
21 *
22 * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
23 * 16th Workshop on Security Protocols, Cambridge, April 2008
24 *
25 * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
26 */
27
28#include "includes.h"
29
30#include <sys/types.h>
31
32#include <stdio.h>
33#include <string.h>
34#include <stdarg.h>
35
36#include <openssl/bn.h>
37#include <openssl/evp.h>
38
39#include "xmalloc.h"
40#include "ssh2.h"
41#include "key.h"
42#include "hostfile.h"
43#include "auth.h"
44#include "buffer.h"
45#include "packet.h"
46#include "dispatch.h"
47#include "log.h"
48#include "misc.h"
49
50#include "jpake.h"
51#include "schnorr.h"
52
53#ifdef JPAKE
54
55/* RFC3526 group 5, 1536 bits */
56#define JPAKE_GROUP_G "2"
57#define JPAKE_GROUP_P \
58 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" \
59 "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" \
60 "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
61 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" \
62 "98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \
63 "9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
64
65struct modp_group *
66jpake_default_group(void)
67{
68 return modp_group_from_g_and_safe_p(JPAKE_GROUP_G, JPAKE_GROUP_P);
69}
70
71struct jpake_ctx *
72jpake_new(void)
73{
74 struct jpake_ctx *ret;
75
76 ret = xcalloc(1, sizeof(*ret));
77
78 ret->grp = jpake_default_group();
79
80 ret->s = ret->k = NULL;
81 ret->x1 = ret->x2 = ret->x3 = ret->x4 = NULL;
82 ret->g_x1 = ret->g_x2 = ret->g_x3 = ret->g_x4 = NULL;
83 ret->a = ret->b = NULL;
84
85 ret->client_id = ret->server_id = NULL;
86 ret->h_k_cid_sessid = ret->h_k_sid_sessid = NULL;
87
88 debug3("%s: alloc %p", __func__, ret);
89
90 return ret;
91}
92
93void
94jpake_free(struct jpake_ctx *pctx)
95{
96 debug3("%s: free %p", __func__, pctx);
97
98#define JPAKE_BN_CLEAR_FREE(v) \
99 do { \
100 if ((v) != NULL) { \
101 BN_clear_free(v); \
102 (v) = NULL; \
103 } \
104 } while (0)
105#define JPAKE_BUF_CLEAR_FREE(v, l) \
106 do { \
107 if ((v) != NULL) { \
108 bzero((v), (l)); \
109 free(v); \
110 (v) = NULL; \
111 (l) = 0; \
112 } \
113 } while (0)
114
115 JPAKE_BN_CLEAR_FREE(pctx->s);
116 JPAKE_BN_CLEAR_FREE(pctx->k);
117 JPAKE_BN_CLEAR_FREE(pctx->x1);
118 JPAKE_BN_CLEAR_FREE(pctx->x2);
119 JPAKE_BN_CLEAR_FREE(pctx->x3);
120 JPAKE_BN_CLEAR_FREE(pctx->x4);
121 JPAKE_BN_CLEAR_FREE(pctx->g_x1);
122 JPAKE_BN_CLEAR_FREE(pctx->g_x2);
123 JPAKE_BN_CLEAR_FREE(pctx->g_x3);
124 JPAKE_BN_CLEAR_FREE(pctx->g_x4);
125 JPAKE_BN_CLEAR_FREE(pctx->a);
126 JPAKE_BN_CLEAR_FREE(pctx->b);
127
128 JPAKE_BUF_CLEAR_FREE(pctx->client_id, pctx->client_id_len);
129 JPAKE_BUF_CLEAR_FREE(pctx->server_id, pctx->server_id_len);
130 JPAKE_BUF_CLEAR_FREE(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
131 JPAKE_BUF_CLEAR_FREE(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
132
133#undef JPAKE_BN_CLEAR_FREE
134#undef JPAKE_BUF_CLEAR_FREE
135
136 bzero(pctx, sizeof(*pctx));
137 free(pctx);
138}
139
140/* dump entire jpake_ctx. NB. includes private values! */
141void
142jpake_dump(struct jpake_ctx *pctx, const char *fmt, ...)
143{
144 char *out;
145 va_list args;
146
147 out = NULL;
148 va_start(args, fmt);
149 vasprintf(&out, fmt, args);
150 va_end(args);
151 if (out == NULL)
152 fatal("%s: vasprintf failed", __func__);
153
154 debug3("%s: %s (ctx at %p)", __func__, out, pctx);
155 if (pctx == NULL) {
156 free(out);
157 return;
158 }
159
160#define JPAKE_DUMP_BN(a) do { \
161 if ((a) != NULL) \
162 JPAKE_DEBUG_BN(((a), "%s = ", #a)); \
163 } while (0)
164#define JPAKE_DUMP_BUF(a, b) do { \
165 if ((a) != NULL) \
166 JPAKE_DEBUG_BUF((a, b, "%s", #a)); \
167 } while (0)
168
169 JPAKE_DUMP_BN(pctx->s);
170 JPAKE_DUMP_BN(pctx->k);
171 JPAKE_DUMP_BN(pctx->x1);
172 JPAKE_DUMP_BN(pctx->x2);
173 JPAKE_DUMP_BN(pctx->x3);
174 JPAKE_DUMP_BN(pctx->x4);
175 JPAKE_DUMP_BN(pctx->g_x1);
176 JPAKE_DUMP_BN(pctx->g_x2);
177 JPAKE_DUMP_BN(pctx->g_x3);
178 JPAKE_DUMP_BN(pctx->g_x4);
179 JPAKE_DUMP_BN(pctx->a);
180 JPAKE_DUMP_BN(pctx->b);
181
182 JPAKE_DUMP_BUF(pctx->client_id, pctx->client_id_len);
183 JPAKE_DUMP_BUF(pctx->server_id, pctx->server_id_len);
184 JPAKE_DUMP_BUF(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
185 JPAKE_DUMP_BUF(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
186
187 debug3("%s: %s done", __func__, out);
188 free(out);
189}
190
191/* Shared parts of step 1 exchange calculation */
192void
193jpake_step1(struct modp_group *grp,
194 u_char **id, u_int *id_len,
195 BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
196 u_char **priv1_proof, u_int *priv1_proof_len,
197 u_char **priv2_proof, u_int *priv2_proof_len)
198{
199 BN_CTX *bn_ctx;
200
201 if ((bn_ctx = BN_CTX_new()) == NULL)
202 fatal("%s: BN_CTX_new", __func__);
203
204 /* Random nonce to prevent replay */
205 *id = xmalloc(KZP_ID_LEN);
206 *id_len = KZP_ID_LEN;
207 arc4random_buf(*id, *id_len);
208
209 /*
210 * x1/x3 is a random element of Zq
211 * x2/x4 is a random element of Z*q
212 * We also exclude [1] from x1/x3 candidates and [0, 1] from
213 * x2/x4 candiates to avoid possible degeneracy (i.e. g^0, g^1).
214 */
215 if ((*priv1 = bn_rand_range_gt_one(grp->q)) == NULL ||
216 (*priv2 = bn_rand_range_gt_one(grp->q)) == NULL)
217 fatal("%s: bn_rand_range_gt_one", __func__);
218
219 /*
220 * client: g_x1 = g^x1 mod p / server: g_x3 = g^x3 mod p
221 * client: g_x2 = g^x2 mod p / server: g_x4 = g^x4 mod p
222 */
223 if ((*g_priv1 = BN_new()) == NULL ||
224 (*g_priv2 = BN_new()) == NULL)
225 fatal("%s: BN_new", __func__);
226 if (BN_mod_exp(*g_priv1, grp->g, *priv1, grp->p, bn_ctx) == -1)
227 fatal("%s: BN_mod_exp", __func__);
228 if (BN_mod_exp(*g_priv2, grp->g, *priv2, grp->p, bn_ctx) == -1)
229 fatal("%s: BN_mod_exp", __func__);
230
231 /* Generate proofs for holding x1/x3 and x2/x4 */
232 if (schnorr_sign_buf(grp->p, grp->q, grp->g,
233 *priv1, *g_priv1, *id, *id_len,
234 priv1_proof, priv1_proof_len) != 0)
235 fatal("%s: schnorr_sign", __func__);
236 if (schnorr_sign_buf(grp->p, grp->q, grp->g,
237 *priv2, *g_priv2, *id, *id_len,
238 priv2_proof, priv2_proof_len) != 0)
239 fatal("%s: schnorr_sign", __func__);
240
241 BN_CTX_free(bn_ctx);
242}
243
244/* Shared parts of step 2 exchange calculation */
245void
246jpake_step2(struct modp_group *grp, BIGNUM *s,
247 BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
248 const u_char *theirid, u_int theirid_len,
249 const u_char *myid, u_int myid_len,
250 const u_char *theirpub1_proof, u_int theirpub1_proof_len,
251 const u_char *theirpub2_proof, u_int theirpub2_proof_len,
252 BIGNUM **newpub,
253 u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
254{
255 BN_CTX *bn_ctx;
256 BIGNUM *tmp, *exponent;
257
258 /* Validate peer's step 1 values */
259 if (BN_cmp(theirpub1, BN_value_one()) <= 0)
260 fatal("%s: theirpub1 <= 1", __func__);
261 if (BN_cmp(theirpub1, grp->p) >= 0)
262 fatal("%s: theirpub1 >= p", __func__);
263 if (BN_cmp(theirpub2, BN_value_one()) <= 0)
264 fatal("%s: theirpub2 <= 1", __func__);
265 if (BN_cmp(theirpub2, grp->p) >= 0)
266 fatal("%s: theirpub2 >= p", __func__);
267
268 if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1,
269 theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1)
270 fatal("%s: schnorr_verify theirpub1 failed", __func__);
271 if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub2,
272 theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1)
273 fatal("%s: schnorr_verify theirpub2 failed", __func__);
274
275 if ((bn_ctx = BN_CTX_new()) == NULL)
276 fatal("%s: BN_CTX_new", __func__);
277
278 if ((*newpub = BN_new()) == NULL ||
279 (tmp = BN_new()) == NULL ||
280 (exponent = BN_new()) == NULL)
281 fatal("%s: BN_new", __func__);
282
283 /*
284 * client: exponent = x2 * s mod p
285 * server: exponent = x4 * s mod p
286 */
287 if (BN_mod_mul(exponent, mypriv2, s, grp->q, bn_ctx) != 1)
288 fatal("%s: BN_mod_mul (exponent = mypriv2 * s mod p)",
289 __func__);
290
291 /*
292 * client: tmp = g^(x1 + x3 + x4) mod p
293 * server: tmp = g^(x1 + x2 + x3) mod p
294 */
295 if (BN_mod_mul(tmp, mypub1, theirpub1, grp->p, bn_ctx) != 1)
296 fatal("%s: BN_mod_mul (tmp = mypub1 * theirpub1 mod p)",
297 __func__);
298 if (BN_mod_mul(tmp, tmp, theirpub2, grp->p, bn_ctx) != 1)
299 fatal("%s: BN_mod_mul (tmp = tmp * theirpub2 mod p)", __func__);
300
301 /*
302 * client: a = tmp^exponent = g^((x1+x3+x4) * x2 * s) mod p
303 * server: b = tmp^exponent = g^((x1+x2+x3) * x4 * s) mod p
304 */
305 if (BN_mod_exp(*newpub, tmp, exponent, grp->p, bn_ctx) != 1)
306 fatal("%s: BN_mod_mul (newpub = tmp^exponent mod p)", __func__);
307
308 JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
309 JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__));
310
311 /* Note the generator here is 'tmp', not g */
312 if (schnorr_sign_buf(grp->p, grp->q, tmp, exponent, *newpub,
313 myid, myid_len,
314 newpub_exponent_proof, newpub_exponent_proof_len) != 0)
315 fatal("%s: schnorr_sign newpub", __func__);
316
317 BN_clear_free(tmp); /* XXX stash for later use? */
318 BN_clear_free(exponent); /* XXX stash for later use? (yes, in conf) */
319
320 BN_CTX_free(bn_ctx);
321}
322
323/* Confirmation hash calculation */
324void
325jpake_confirm_hash(const BIGNUM *k,
326 const u_char *endpoint_id, u_int endpoint_id_len,
327 const u_char *sess_id, u_int sess_id_len,
328 u_char **confirm_hash, u_int *confirm_hash_len)
329{
330 Buffer b;
331
332 /*
333 * Calculate confirmation proof:
334 * client: H(k || client_id || session_id)
335 * server: H(k || server_id || session_id)
336 */
337 buffer_init(&b);
338 buffer_put_bignum2(&b, k);
339 buffer_put_string(&b, endpoint_id, endpoint_id_len);
340 buffer_put_string(&b, sess_id, sess_id_len);
341 if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
342 confirm_hash, confirm_hash_len) != 0)
343 fatal("%s: hash_buffer", __func__);
344 buffer_free(&b);
345}
346
347/* Shared parts of key derivation and confirmation calculation */
348void
349jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
350 BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
351 BIGNUM *theirpub1, BIGNUM *theirpub2,
352 const u_char *my_id, u_int my_id_len,
353 const u_char *their_id, u_int their_id_len,
354 const u_char *sess_id, u_int sess_id_len,
355 const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
356 BIGNUM **k,
357 u_char **confirm_hash, u_int *confirm_hash_len)
358{
359 BN_CTX *bn_ctx;
360 BIGNUM *tmp;
361
362 if ((bn_ctx = BN_CTX_new()) == NULL)
363 fatal("%s: BN_CTX_new", __func__);
364 if ((tmp = BN_new()) == NULL ||
365 (*k = BN_new()) == NULL)
366 fatal("%s: BN_new", __func__);
367
368 /* Validate step 2 values */
369 if (BN_cmp(step2_val, BN_value_one()) <= 0)
370 fatal("%s: step2_val <= 1", __func__);
371 if (BN_cmp(step2_val, grp->p) >= 0)
372 fatal("%s: step2_val >= p", __func__);
373
374 /*
375 * theirpriv2_s_proof is calculated with a different generator:
376 * tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1
377 * Calculate it here so we can check the signature.
378 */
379 if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1)
380 fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__);
381 if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1)
382 fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__);
383
384 JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
385
386 if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val,
387 their_id, their_id_len,
388 theirpriv2_s_proof, theirpriv2_s_proof_len) != 1)
389 fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__);
390
391 /*
392 * Derive shared key:
393 * client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s)
394 * server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s)
395 *
396 * Computed as:
397 * client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p
398 * server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p
399 */
400 if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1)
401 fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__);
402 if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1)
403 fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__);
404 if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1)
405 fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__);
406 if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1)
407 fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__);
408 if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1)
409 fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__);
410
411 BN_CTX_free(bn_ctx);
412 BN_clear_free(tmp);
413
414 jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len,
415 confirm_hash, confirm_hash_len);
416}
417
418/*
419 * Calculate and check confirmation hash from peer. Returns 1 on success
420 * 0 on failure/mismatch.
421 */
422int
423jpake_check_confirm(const BIGNUM *k,
424 const u_char *peer_id, u_int peer_id_len,
425 const u_char *sess_id, u_int sess_id_len,
426 const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
427{
428 u_char *expected_confirm_hash;
429 u_int expected_confirm_hash_len;
430 int success = 0;
431
432 /* Calculate and verify expected confirmation hash */
433 jpake_confirm_hash(k, peer_id, peer_id_len, sess_id, sess_id_len,
434 &expected_confirm_hash, &expected_confirm_hash_len);
435
436 JPAKE_DEBUG_BUF((expected_confirm_hash, expected_confirm_hash_len,
437 "%s: expected confirm hash", __func__));
438 JPAKE_DEBUG_BUF((peer_confirm_hash, peer_confirm_hash_len,
439 "%s: received confirm hash", __func__));
440
441 if (peer_confirm_hash_len != expected_confirm_hash_len)
442 error("%s: confirmation length mismatch (my %u them %u)",
443 __func__, expected_confirm_hash_len, peer_confirm_hash_len);
444 else if (timingsafe_bcmp(peer_confirm_hash, expected_confirm_hash,
445 expected_confirm_hash_len) == 0)
446 success = 1;
447 bzero(expected_confirm_hash, expected_confirm_hash_len);
448 free(expected_confirm_hash);
449 debug3("%s: success = %d", __func__, success);
450 return success;
451}
452
453/* XXX main() function with tests */
454
455#endif /* JPAKE */
456
diff --git a/jpake.h b/jpake.h
deleted file mode 100644
index a3f2cf025..000000000
--- a/jpake.h
+++ /dev/null
@@ -1,114 +0,0 @@
1/* $OpenBSD: jpake.h,v 1.2 2009/03/05 07:18:19 djm Exp $ */
2/*
3 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef JPAKE_H
19#define JPAKE_H
20
21#include <sys/types.h>
22
23#include <openssl/bn.h>
24
25/* Set JPAKE_DEBUG in CFLAGS for privacy-violating debugging */
26#ifndef JPAKE_DEBUG
27# define JPAKE_DEBUG_BN(a)
28# define JPAKE_DEBUG_BUF(a)
29# define JPAKE_DEBUG_CTX(a)
30#else
31# define JPAKE_DEBUG_BN(a) debug3_bn a
32# define JPAKE_DEBUG_BUF(a) debug3_buf a
33# define JPAKE_DEBUG_CTX(a) jpake_dump a
34#endif /* JPAKE_DEBUG */
35
36#define KZP_ID_LEN 16 /* Length of client and server IDs */
37
38struct jpake_ctx {
39 /* Parameters */
40 struct modp_group *grp;
41
42 /* Private values shared by client and server */
43 BIGNUM *s; /* Secret (salted, crypted password) */
44 BIGNUM *k; /* Derived key */
45
46 /* Client private values (NULL for server) */
47 BIGNUM *x1; /* random in Zq */
48 BIGNUM *x2; /* random in Z*q */
49
50 /* Server private values (NULL for server) */
51 BIGNUM *x3; /* random in Zq */
52 BIGNUM *x4; /* random in Z*q */
53
54 /* Step 1: C->S */
55 u_char *client_id; /* Anti-replay nonce */
56 u_int client_id_len;
57 BIGNUM *g_x1; /* g^x1 */
58 BIGNUM *g_x2; /* g^x2 */
59
60 /* Step 1: S->C */
61 u_char *server_id; /* Anti-replay nonce */
62 u_int server_id_len;
63 BIGNUM *g_x3; /* g^x3 */
64 BIGNUM *g_x4; /* g^x4 */
65
66 /* Step 2: C->S */
67 BIGNUM *a; /* g^((x1+x3+x4)*x2*s) */
68
69 /* Step 2: S->C */
70 BIGNUM *b; /* g^((x1+x2+x3)*x4*s) */
71
72 /* Confirmation: C->S */
73 u_char *h_k_cid_sessid; /* H(k || client_id || session_id) */
74 u_int h_k_cid_sessid_len;
75
76 /* Confirmation: S->C */
77 u_char *h_k_sid_sessid; /* H(k || server_id || session_id) */
78 u_int h_k_sid_sessid_len;
79};
80
81/* jpake.c */
82struct modp_group *jpake_default_group(void);
83void jpake_dump(struct jpake_ctx *, const char *, ...)
84 __attribute__((__nonnull__ (2)))
85 __attribute__((format(printf, 2, 3)));
86struct jpake_ctx *jpake_new(void);
87void jpake_free(struct jpake_ctx *);
88
89void jpake_step1(struct modp_group *, u_char **, u_int *,
90 BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
91 u_char **, u_int *, u_char **, u_int *);
92
93void jpake_step2(struct modp_group *, BIGNUM *,
94 BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
95 const u_char *, u_int, const u_char *, u_int,
96 const u_char *, u_int, const u_char *, u_int,
97 BIGNUM **, u_char **, u_int *);
98
99void jpake_confirm_hash(const BIGNUM *,
100 const u_char *, u_int,
101 const u_char *, u_int,
102 u_char **, u_int *);
103
104void jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
105 BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
106 const u_char *, u_int, const u_char *, u_int,
107 const u_char *, u_int, const u_char *, u_int,
108 BIGNUM **, u_char **, u_int *);
109
110int jpake_check_confirm(const BIGNUM *, const u_char *, u_int,
111 const u_char *, u_int, const u_char *, u_int);
112
113#endif /* JPAKE_H */
114
diff --git a/monitor.c b/monitor.c
index 03baf1ea9..c923e7c0b 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.128 2013/11/04 11:51:16 markus Exp $ */ 1/* $OpenBSD: monitor.c,v 1.129 2014/01/29 06:18:35 djm Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -95,7 +95,6 @@
95#include "misc.h" 95#include "misc.h"
96#include "compat.h" 96#include "compat.h"
97#include "ssh2.h" 97#include "ssh2.h"
98#include "jpake.h"
99#include "roaming.h" 98#include "roaming.h"
100#include "authfd.h" 99#include "authfd.h"
101 100
@@ -161,11 +160,6 @@ int mm_answer_rsa_challenge(int, Buffer *);
161int mm_answer_rsa_response(int, Buffer *); 160int mm_answer_rsa_response(int, Buffer *);
162int mm_answer_sesskey(int, Buffer *); 161int mm_answer_sesskey(int, Buffer *);
163int mm_answer_sessid(int, Buffer *); 162int mm_answer_sessid(int, Buffer *);
164int mm_answer_jpake_get_pwdata(int, Buffer *);
165int mm_answer_jpake_step1(int, Buffer *);
166int mm_answer_jpake_step2(int, Buffer *);
167int mm_answer_jpake_key_confirm(int, Buffer *);
168int mm_answer_jpake_check_confirm(int, Buffer *);
169 163
170#ifdef USE_PAM 164#ifdef USE_PAM
171int mm_answer_pam_start(int, Buffer *); 165int mm_answer_pam_start(int, Buffer *);
@@ -254,13 +248,6 @@ struct mon_table mon_dispatch_proto20[] = {
254 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 248 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
255 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 249 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
256#endif 250#endif
257#ifdef JPAKE
258 {MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
259 {MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1},
260 {MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2},
261 {MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
262 {MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
263#endif
264 {0, 0, NULL} 251 {0, 0, NULL}
265}; 252};
266 253
@@ -427,15 +414,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
427 if (!authenticated) 414 if (!authenticated)
428 authctxt->failures++; 415 authctxt->failures++;
429 } 416 }
430#ifdef JPAKE
431 /* Cleanup JPAKE context after authentication */
432 if (ent->flags & MON_AUTHDECIDE) {
433 if (authctxt->jpake_ctx != NULL) {
434 jpake_free(authctxt->jpake_ctx);
435 authctxt->jpake_ctx = NULL;
436 }
437 }
438#endif
439 } 417 }
440 418
441 if (!authctxt->valid) 419 if (!authctxt->valid)
@@ -2159,205 +2137,3 @@ mm_answer_gss_userok(int sock, Buffer *m)
2159} 2137}
2160#endif /* GSSAPI */ 2138#endif /* GSSAPI */
2161 2139
2162#ifdef JPAKE
2163int
2164mm_answer_jpake_step1(int sock, Buffer *m)
2165{
2166 struct jpake_ctx *pctx;
2167 u_char *x3_proof, *x4_proof;
2168 u_int x3_proof_len, x4_proof_len;
2169
2170 if (!options.zero_knowledge_password_authentication)
2171 fatal("zero_knowledge_password_authentication disabled");
2172
2173 if (authctxt->jpake_ctx != NULL)
2174 fatal("%s: authctxt->jpake_ctx already set (%p)",
2175 __func__, authctxt->jpake_ctx);
2176 authctxt->jpake_ctx = pctx = jpake_new();
2177
2178 jpake_step1(pctx->grp,
2179 &pctx->server_id, &pctx->server_id_len,
2180 &pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
2181 &x3_proof, &x3_proof_len,
2182 &x4_proof, &x4_proof_len);
2183
2184 JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__));
2185
2186 buffer_clear(m);
2187
2188 buffer_put_string(m, pctx->server_id, pctx->server_id_len);
2189 buffer_put_bignum2(m, pctx->g_x3);
2190 buffer_put_bignum2(m, pctx->g_x4);
2191 buffer_put_string(m, x3_proof, x3_proof_len);
2192 buffer_put_string(m, x4_proof, x4_proof_len);
2193
2194 debug3("%s: sending step1", __func__);
2195 mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m);
2196
2197 bzero(x3_proof, x3_proof_len);
2198 bzero(x4_proof, x4_proof_len);
2199 free(x3_proof);
2200 free(x4_proof);
2201
2202 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1);
2203 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0);
2204
2205 return 0;
2206}
2207
2208int
2209mm_answer_jpake_get_pwdata(int sock, Buffer *m)
2210{
2211 struct jpake_ctx *pctx = authctxt->jpake_ctx;
2212 char *hash_scheme, *salt;
2213
2214 if (pctx == NULL)
2215 fatal("%s: pctx == NULL", __func__);
2216
2217 auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt);
2218
2219 buffer_clear(m);
2220 /* pctx->s is sensitive, not returned to slave */
2221 buffer_put_cstring(m, hash_scheme);
2222 buffer_put_cstring(m, salt);
2223
2224 debug3("%s: sending pwdata", __func__);
2225 mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m);
2226
2227 bzero(hash_scheme, strlen(hash_scheme));
2228 bzero(salt, strlen(salt));
2229 free(hash_scheme);
2230 free(salt);
2231
2232 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1);
2233
2234 return 0;
2235}
2236
2237int
2238mm_answer_jpake_step2(int sock, Buffer *m)
2239{
2240 struct jpake_ctx *pctx = authctxt->jpake_ctx;
2241 u_char *x1_proof, *x2_proof, *x4_s_proof;
2242 u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
2243
2244 if (pctx == NULL)
2245 fatal("%s: pctx == NULL", __func__);
2246
2247 if ((pctx->g_x1 = BN_new()) == NULL ||
2248 (pctx->g_x2 = BN_new()) == NULL)
2249 fatal("%s: BN_new", __func__);
2250 buffer_get_bignum2(m, pctx->g_x1);
2251 buffer_get_bignum2(m, pctx->g_x2);
2252 pctx->client_id = buffer_get_string(m, &pctx->client_id_len);
2253 x1_proof = buffer_get_string(m, &x1_proof_len);
2254 x2_proof = buffer_get_string(m, &x2_proof_len);
2255
2256 jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
2257 pctx->g_x1, pctx->g_x2, pctx->x4,
2258 pctx->client_id, pctx->client_id_len,
2259 pctx->server_id, pctx->server_id_len,
2260 x1_proof, x1_proof_len,
2261 x2_proof, x2_proof_len,
2262 &pctx->b,
2263 &x4_s_proof, &x4_s_proof_len);
2264
2265 JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__));
2266
2267 bzero(x1_proof, x1_proof_len);
2268 bzero(x2_proof, x2_proof_len);
2269 free(x1_proof);
2270 free(x2_proof);
2271
2272 buffer_clear(m);
2273
2274 buffer_put_bignum2(m, pctx->b);
2275 buffer_put_string(m, x4_s_proof, x4_s_proof_len);
2276
2277 debug3("%s: sending step2", __func__);
2278 mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m);
2279
2280 bzero(x4_s_proof, x4_s_proof_len);
2281 free(x4_s_proof);
2282
2283 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1);
2284
2285 return 0;
2286}
2287
2288int
2289mm_answer_jpake_key_confirm(int sock, Buffer *m)
2290{
2291 struct jpake_ctx *pctx = authctxt->jpake_ctx;
2292 u_char *x2_s_proof;
2293 u_int x2_s_proof_len;
2294
2295 if (pctx == NULL)
2296 fatal("%s: pctx == NULL", __func__);
2297
2298 if ((pctx->a = BN_new()) == NULL)
2299 fatal("%s: BN_new", __func__);
2300 buffer_get_bignum2(m, pctx->a);
2301 x2_s_proof = buffer_get_string(m, &x2_s_proof_len);
2302
2303 jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
2304 pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
2305 pctx->server_id, pctx->server_id_len,
2306 pctx->client_id, pctx->client_id_len,
2307 session_id2, session_id2_len,
2308 x2_s_proof, x2_s_proof_len,
2309 &pctx->k,
2310 &pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len);
2311
2312 JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__));
2313
2314 bzero(x2_s_proof, x2_s_proof_len);
2315 buffer_clear(m);
2316
2317 /* pctx->k is sensitive, not sent */
2318 buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
2319
2320 debug3("%s: sending confirmation hash", __func__);
2321 mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m);
2322
2323 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1);
2324
2325 return 0;
2326}
2327
2328int
2329mm_answer_jpake_check_confirm(int sock, Buffer *m)
2330{
2331 int authenticated = 0;
2332 u_char *peer_confirm_hash;
2333 u_int peer_confirm_hash_len;
2334 struct jpake_ctx *pctx = authctxt->jpake_ctx;
2335
2336 if (pctx == NULL)
2337 fatal("%s: pctx == NULL", __func__);
2338
2339 peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len);
2340
2341 authenticated = jpake_check_confirm(pctx->k,
2342 pctx->client_id, pctx->client_id_len,
2343 session_id2, session_id2_len,
2344 peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid;
2345
2346 JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__));
2347
2348 bzero(peer_confirm_hash, peer_confirm_hash_len);
2349 free(peer_confirm_hash);
2350
2351 buffer_clear(m);
2352 buffer_put_int(m, authenticated);
2353
2354 debug3("%s: sending result %d", __func__, authenticated);
2355 mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m);
2356
2357 monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1);
2358
2359 auth_method = "jpake-01@openssh.com";
2360 return authenticated;
2361}
2362
2363#endif /* JPAKE */
diff --git a/monitor.h b/monitor.h
index 2caa46933..5bc41b513 100644
--- a/monitor.h
+++ b/monitor.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.h,v 1.17 2012/12/02 20:34:10 djm Exp $ */ 1/* $OpenBSD: monitor.h,v 1.18 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -56,11 +56,6 @@ enum monitor_reqtype {
56 MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47, 56 MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
57 MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, 57 MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
58 MONITOR_REQ_TERM = 50, 58 MONITOR_REQ_TERM = 50,
59 MONITOR_REQ_JPAKE_STEP1 = 52, MONITOR_ANS_JPAKE_STEP1 = 53,
60 MONITOR_REQ_JPAKE_GET_PWDATA = 54, MONITOR_ANS_JPAKE_GET_PWDATA = 55,
61 MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57,
62 MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59,
63 MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61,
64 59
65 MONITOR_REQ_PAM_START = 100, 60 MONITOR_REQ_PAM_START = 100,
66 MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, 61 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 @@
1/* $OpenBSD: monitor_wrap.c,v 1.77 2013/11/06 16:52:11 markus Exp $ */ 1/* $OpenBSD: monitor_wrap.c,v 1.78 2014/01/29 06:18:35 djm Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -71,8 +71,6 @@
71#include "atomicio.h" 71#include "atomicio.h"
72#include "monitor_fdpass.h" 72#include "monitor_fdpass.h"
73#include "misc.h" 73#include "misc.h"
74#include "schnorr.h"
75#include "jpake.h"
76#include "uuencode.h" 74#include "uuencode.h"
77 75
78#include "channels.h" 76#include "channels.h"
@@ -1292,164 +1290,3 @@ mm_ssh_gssapi_userok(char *user)
1292} 1290}
1293#endif /* GSSAPI */ 1291#endif /* GSSAPI */
1294 1292
1295#ifdef JPAKE
1296void
1297mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
1298 char **hash_scheme, char **salt)
1299{
1300 Buffer m;
1301
1302 debug3("%s entering", __func__);
1303
1304 buffer_init(&m);
1305 mm_request_send(pmonitor->m_recvfd,
1306 MONITOR_REQ_JPAKE_GET_PWDATA, &m);
1307
1308 debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
1309 mm_request_receive_expect(pmonitor->m_recvfd,
1310 MONITOR_ANS_JPAKE_GET_PWDATA, &m);
1311
1312 *hash_scheme = buffer_get_string(&m, NULL);
1313 *salt = buffer_get_string(&m, NULL);
1314
1315 buffer_free(&m);
1316}
1317
1318void
1319mm_jpake_step1(struct modp_group *grp,
1320 u_char **id, u_int *id_len,
1321 BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
1322 u_char **priv1_proof, u_int *priv1_proof_len,
1323 u_char **priv2_proof, u_int *priv2_proof_len)
1324{
1325 Buffer m;
1326
1327 debug3("%s entering", __func__);
1328
1329 buffer_init(&m);
1330 mm_request_send(pmonitor->m_recvfd,
1331 MONITOR_REQ_JPAKE_STEP1, &m);
1332
1333 debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
1334 mm_request_receive_expect(pmonitor->m_recvfd,
1335 MONITOR_ANS_JPAKE_STEP1, &m);
1336
1337 if ((*priv1 = BN_new()) == NULL ||
1338 (*priv2 = BN_new()) == NULL ||
1339 (*g_priv1 = BN_new()) == NULL ||
1340 (*g_priv2 = BN_new()) == NULL)
1341 fatal("%s: BN_new", __func__);
1342
1343 *id = buffer_get_string(&m, id_len);
1344 /* priv1 and priv2 are, well, private */
1345 buffer_get_bignum2(&m, *g_priv1);
1346 buffer_get_bignum2(&m, *g_priv2);
1347 *priv1_proof = buffer_get_string(&m, priv1_proof_len);
1348 *priv2_proof = buffer_get_string(&m, priv2_proof_len);
1349
1350 buffer_free(&m);
1351}
1352
1353void
1354mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
1355 BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
1356 const u_char *theirid, u_int theirid_len,
1357 const u_char *myid, u_int myid_len,
1358 const u_char *theirpub1_proof, u_int theirpub1_proof_len,
1359 const u_char *theirpub2_proof, u_int theirpub2_proof_len,
1360 BIGNUM **newpub,
1361 u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
1362{
1363 Buffer m;
1364
1365 debug3("%s entering", __func__);
1366
1367 buffer_init(&m);
1368 /* monitor already has all bignums except theirpub1, theirpub2 */
1369 buffer_put_bignum2(&m, theirpub1);
1370 buffer_put_bignum2(&m, theirpub2);
1371 /* monitor already knows our id */
1372 buffer_put_string(&m, theirid, theirid_len);
1373 buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
1374 buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
1375
1376 mm_request_send(pmonitor->m_recvfd,
1377 MONITOR_REQ_JPAKE_STEP2, &m);
1378
1379 debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
1380 mm_request_receive_expect(pmonitor->m_recvfd,
1381 MONITOR_ANS_JPAKE_STEP2, &m);
1382
1383 if ((*newpub = BN_new()) == NULL)
1384 fatal("%s: BN_new", __func__);
1385
1386 buffer_get_bignum2(&m, *newpub);
1387 *newpub_exponent_proof = buffer_get_string(&m,
1388 newpub_exponent_proof_len);
1389
1390 buffer_free(&m);
1391}
1392
1393void
1394mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
1395 BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
1396 BIGNUM *theirpub1, BIGNUM *theirpub2,
1397 const u_char *my_id, u_int my_id_len,
1398 const u_char *their_id, u_int their_id_len,
1399 const u_char *sess_id, u_int sess_id_len,
1400 const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
1401 BIGNUM **k,
1402 u_char **confirm_hash, u_int *confirm_hash_len)
1403{
1404 Buffer m;
1405
1406 debug3("%s entering", __func__);
1407
1408 buffer_init(&m);
1409 /* monitor already has all bignums except step2_val */
1410 buffer_put_bignum2(&m, step2_val);
1411 /* monitor already knows all the ids */
1412 buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
1413
1414 mm_request_send(pmonitor->m_recvfd,
1415 MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
1416
1417 debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
1418 mm_request_receive_expect(pmonitor->m_recvfd,
1419 MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
1420
1421 /* 'k' is sensitive and stays in the monitor */
1422 *confirm_hash = buffer_get_string(&m, confirm_hash_len);
1423
1424 buffer_free(&m);
1425}
1426
1427int
1428mm_jpake_check_confirm(const BIGNUM *k,
1429 const u_char *peer_id, u_int peer_id_len,
1430 const u_char *sess_id, u_int sess_id_len,
1431 const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
1432{
1433 Buffer m;
1434 int success = 0;
1435
1436 debug3("%s entering", __func__);
1437
1438 buffer_init(&m);
1439 /* k is dummy in slave, ignored */
1440 /* monitor knows all the ids */
1441 buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
1442 mm_request_send(pmonitor->m_recvfd,
1443 MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
1444
1445 debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
1446 mm_request_receive_expect(pmonitor->m_recvfd,
1447 MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
1448
1449 success = buffer_get_int(&m);
1450 buffer_free(&m);
1451
1452 debug3("%s: success = %d", __func__, success);
1453 return success;
1454}
1455#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 @@
1/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */ 1/* $OpenBSD: monitor_wrap.h,v 1.24 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 4 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -102,26 +102,6 @@ int mm_bsdauth_respond(void *, u_int, char **);
102int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); 102int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
103int mm_skey_respond(void *, u_int, char **); 103int mm_skey_respond(void *, u_int, char **);
104 104
105/* jpake */
106struct modp_group;
107void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **);
108void mm_jpake_step1(struct modp_group *, u_char **, u_int *,
109 BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
110 u_char **, u_int *, u_char **, u_int *);
111void mm_jpake_step2(struct modp_group *, BIGNUM *,
112 BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
113 const u_char *, u_int, const u_char *, u_int,
114 const u_char *, u_int, const u_char *, u_int,
115 BIGNUM **, u_char **, u_int *);
116void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
117 BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
118 const u_char *, u_int, const u_char *, u_int,
119 const u_char *, u_int, const u_char *, u_int,
120 BIGNUM **, u_char **, u_int *);
121int mm_jpake_check_confirm(const BIGNUM *,
122 const u_char *, u_int, const u_char *, u_int, const u_char *, u_int);
123
124
125/* zlib allocation hooks */ 105/* zlib allocation hooks */
126 106
127void *mm_zalloc(struct mm_master *, u_int, u_int); 107void *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 @@
1/* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */ 1/* $OpenBSD: readconf.c,v 1.216 2014/01/29 06:18:35 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -145,7 +145,7 @@ typedef enum {
145 oSendEnv, oControlPath, oControlMaster, oControlPersist, 145 oSendEnv, oControlPath, oControlMaster, oControlPersist,
146 oHashKnownHosts, 146 oHashKnownHosts,
147 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, 147 oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
148 oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication, 148 oVisualHostKey, oUseRoaming,
149 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 149 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
150 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 150 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
151 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 151 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
@@ -252,12 +252,6 @@ static struct {
252 { "permitlocalcommand", oPermitLocalCommand }, 252 { "permitlocalcommand", oPermitLocalCommand },
253 { "visualhostkey", oVisualHostKey }, 253 { "visualhostkey", oVisualHostKey },
254 { "useroaming", oUseRoaming }, 254 { "useroaming", oUseRoaming },
255#ifdef JPAKE
256 { "zeroknowledgepasswordauthentication",
257 oZeroKnowledgePasswordAuthentication },
258#else
259 { "zeroknowledgepasswordauthentication", oUnsupported },
260#endif
261 { "kexalgorithms", oKexAlgorithms }, 255 { "kexalgorithms", oKexAlgorithms },
262 { "ipqos", oIPQoS }, 256 { "ipqos", oIPQoS },
263 { "requesttty", oRequestTTY }, 257 { "requesttty", oRequestTTY },
@@ -804,10 +798,6 @@ parse_time:
804 intptr = &options->password_authentication; 798 intptr = &options->password_authentication;
805 goto parse_flag; 799 goto parse_flag;
806 800
807 case oZeroKnowledgePasswordAuthentication:
808 intptr = &options->zero_knowledge_password_authentication;
809 goto parse_flag;
810
811 case oKbdInteractiveAuthentication: 801 case oKbdInteractiveAuthentication:
812 intptr = &options->kbd_interactive_authentication; 802 intptr = &options->kbd_interactive_authentication;
813 goto parse_flag; 803 goto parse_flag;
@@ -1550,7 +1540,6 @@ initialize_options(Options * options)
1550 options->permit_local_command = -1; 1540 options->permit_local_command = -1;
1551 options->use_roaming = -1; 1541 options->use_roaming = -1;
1552 options->visual_host_key = -1; 1542 options->visual_host_key = -1;
1553 options->zero_knowledge_password_authentication = -1;
1554 options->ip_qos_interactive = -1; 1543 options->ip_qos_interactive = -1;
1555 options->ip_qos_bulk = -1; 1544 options->ip_qos_bulk = -1;
1556 options->request_tty = -1; 1545 options->request_tty = -1;
@@ -1706,8 +1695,6 @@ fill_default_options(Options * options)
1706 options->use_roaming = 1; 1695 options->use_roaming = 1;
1707 if (options->visual_host_key == -1) 1696 if (options->visual_host_key == -1)
1708 options->visual_host_key = 0; 1697 options->visual_host_key = 0;
1709 if (options->zero_knowledge_password_authentication == -1)
1710 options->zero_knowledge_password_authentication = 0;
1711 if (options->ip_qos_interactive == -1) 1698 if (options->ip_qos_interactive == -1)
1712 options->ip_qos_interactive = IPTOS_LOWDELAY; 1699 options->ip_qos_interactive = IPTOS_LOWDELAY;
1713 if (options->ip_qos_bulk == -1) 1700 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 @@
1/* $OpenBSD: readconf.h,v 1.99 2013/10/16 22:49:38 djm Exp $ */ 1/* $OpenBSD: readconf.h,v 1.100 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -59,7 +59,6 @@ typedef struct {
59 * authentication. */ 59 * authentication. */
60 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ 60 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
61 char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */ 61 char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
62 int zero_knowledge_password_authentication; /* Try jpake */
63 int batch_mode; /* Batch mode: do not ask for passwords. */ 62 int batch_mode; /* Batch mode: do not ask for passwords. */
64 int check_host_ip; /* Also keep track of keys for IP address */ 63 int check_host_ip; /* Also keep track of keys for IP address */
65 int strict_host_key_checking; /* Strict host key checking. */ 64 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 @@
1/* $OpenBSD: schnorr.c,v 1.9 2014/01/09 23:20:00 djm Exp $ */
2/*
3 * Copyright (c) 2008 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/*
19 * Implementation of Schnorr signatures / zero-knowledge proofs, based on
20 * description in:
21 *
22 * F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
23 * 16th Workshop on Security Protocols, Cambridge, April 2008
24 *
25 * http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
26 */
27
28#include "includes.h"
29
30#include <sys/types.h>
31
32#include <string.h>
33#include <stdarg.h>
34#include <stdio.h>
35
36#include <openssl/evp.h>
37#include <openssl/bn.h>
38
39#include "xmalloc.h"
40#include "buffer.h"
41#include "log.h"
42
43#include "schnorr.h"
44#include "digest.h"
45
46#include "openbsd-compat/openssl-compat.h"
47
48/* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */
49/* #define SCHNORR_MAIN */ /* Include main() selftest */
50
51#ifndef SCHNORR_DEBUG
52# define SCHNORR_DEBUG_BN(a)
53# define SCHNORR_DEBUG_BUF(a)
54#else
55# define SCHNORR_DEBUG_BN(a) debug3_bn a
56# define SCHNORR_DEBUG_BUF(a) debug3_buf a
57#endif /* SCHNORR_DEBUG */
58
59/*
60 * Calculate hash component of Schnorr signature H(g || g^v || g^x || id)
61 * using the hash function defined by "hash_alg". Returns signature as
62 * bignum or NULL on error.
63 */
64static BIGNUM *
65schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g,
66 int hash_alg, const BIGNUM *g_v, const BIGNUM *g_x,
67 const u_char *id, u_int idlen)
68{
69 u_char *digest;
70 u_int digest_len;
71 BIGNUM *h;
72 Buffer b;
73 int success = -1;
74
75 if ((h = BN_new()) == NULL) {
76 error("%s: BN_new", __func__);
77 return NULL;
78 }
79
80 buffer_init(&b);
81
82 /* h = H(g || p || q || g^v || g^x || id) */
83 buffer_put_bignum2(&b, g);
84 buffer_put_bignum2(&b, p);
85 buffer_put_bignum2(&b, q);
86 buffer_put_bignum2(&b, g_v);
87 buffer_put_bignum2(&b, g_x);
88 buffer_put_string(&b, id, idlen);
89
90 SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
91 "%s: hashblob", __func__));
92 if (hash_buffer(buffer_ptr(&b), buffer_len(&b), hash_alg,
93 &digest, &digest_len) != 0) {
94 error("%s: hash_buffer", __func__);
95 goto out;
96 }
97 if (BN_bin2bn(digest, (int)digest_len, h) == NULL) {
98 error("%s: BN_bin2bn", __func__);
99 goto out;
100 }
101 success = 0;
102 SCHNORR_DEBUG_BN((h, "%s: h = ", __func__));
103 out:
104 buffer_free(&b);
105 bzero(digest, digest_len);
106 free(digest);
107 digest_len = 0;
108 if (success == 0)
109 return h;
110 BN_clear_free(h);
111 return NULL;
112}
113
114/*
115 * Generate Schnorr signature to prove knowledge of private value 'x' used
116 * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
117 * using the hash function "hash_alg".
118 * 'idlen' bytes from 'id' will be included in the signature hash as an anti-
119 * replay salt.
120 *
121 * On success, 0 is returned. The signature values are returned as *e_p
122 * (g^v mod p) and *r_p (v - xh mod q). The caller must free these values.
123 * On failure, -1 is returned.
124 */
125int
126schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
127 int hash_alg, const BIGNUM *x, const BIGNUM *g_x,
128 const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p)
129{
130 int success = -1;
131 BIGNUM *h, *tmp, *v, *g_v, *r;
132 BN_CTX *bn_ctx;
133
134 SCHNORR_DEBUG_BN((x, "%s: x = ", __func__));
135 SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
136
137 /* Avoid degenerate cases: g^0 yields a spoofable signature */
138 if (BN_cmp(g_x, BN_value_one()) <= 0) {
139 error("%s: g_x < 1", __func__);
140 return -1;
141 }
142 if (BN_cmp(g_x, grp_p) >= 0) {
143 error("%s: g_x > g", __func__);
144 return -1;
145 }
146
147 h = g_v = r = tmp = v = NULL;
148 if ((bn_ctx = BN_CTX_new()) == NULL) {
149 error("%s: BN_CTX_new", __func__);
150 goto out;
151 }
152 if ((g_v = BN_new()) == NULL ||
153 (r = BN_new()) == NULL ||
154 (tmp = BN_new()) == NULL) {
155 error("%s: BN_new", __func__);
156 goto out;
157 }
158
159 /*
160 * v must be a random element of Zq, so 1 <= v < q
161 * we also exclude v = 1, since g^1 looks dangerous
162 */
163 if ((v = bn_rand_range_gt_one(grp_p)) == NULL) {
164 error("%s: bn_rand_range2", __func__);
165 goto out;
166 }
167 SCHNORR_DEBUG_BN((v, "%s: v = ", __func__));
168
169 /* g_v = g^v mod p */
170 if (BN_mod_exp(g_v, grp_g, v, grp_p, bn_ctx) == -1) {
171 error("%s: BN_mod_exp (g^v mod p)", __func__);
172 goto out;
173 }
174 SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__));
175
176 /* h = H(g || g^v || g^x || id) */
177 if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x,
178 id, idlen)) == NULL) {
179 error("%s: schnorr_hash failed", __func__);
180 goto out;
181 }
182
183 /* r = v - xh mod q */
184 if (BN_mod_mul(tmp, x, h, grp_q, bn_ctx) == -1) {
185 error("%s: BN_mod_mul (tmp = xv mod q)", __func__);
186 goto out;
187 }
188 if (BN_mod_sub(r, v, tmp, grp_q, bn_ctx) == -1) {
189 error("%s: BN_mod_mul (r = v - tmp)", __func__);
190 goto out;
191 }
192 SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__));
193 SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
194
195 *e_p = g_v;
196 *r_p = r;
197
198 success = 0;
199 out:
200 BN_CTX_free(bn_ctx);
201 if (h != NULL)
202 BN_clear_free(h);
203 if (v != NULL)
204 BN_clear_free(v);
205 BN_clear_free(tmp);
206
207 return success;
208}
209
210/*
211 * Generate Schnorr signature to prove knowledge of private value 'x' used
212 * in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
213 * using a SHA256 hash.
214 * 'idlen' bytes from 'id' will be included in the signature hash as an anti-
215 * replay salt.
216 * On success, 0 is returned and *siglen bytes of signature are returned in
217 * *sig (caller to free). Returns -1 on failure.
218 */
219int
220schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
221 const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
222 u_char **sig, u_int *siglen)
223{
224 Buffer b;
225 BIGNUM *r, *e;
226
227 if (schnorr_sign(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256,
228 x, g_x, id, idlen, &r, &e) != 0)
229 return -1;
230
231 /* Signature is (e, r) */
232 buffer_init(&b);
233 /* XXX sigtype-hash as string? */
234 buffer_put_bignum2(&b, e);
235 buffer_put_bignum2(&b, r);
236 *siglen = buffer_len(&b);
237 *sig = xmalloc(*siglen);
238 memcpy(*sig, buffer_ptr(&b), *siglen);
239 SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
240 "%s: sigblob", __func__));
241 buffer_free(&b);
242
243 BN_clear_free(r);
244 BN_clear_free(e);
245
246 return 0;
247}
248
249/*
250 * Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against
251 * public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and
252 * 'grp_g' using hash "hash_alg".
253 * Signature hash will be salted with 'idlen' bytes from 'id'.
254 * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
255 */
256int
257schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
258 int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen,
259 const BIGNUM *r, const BIGNUM *e)
260{
261 int success = -1;
262 BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL;
263 BIGNUM *expected = NULL;
264 BN_CTX *bn_ctx;
265
266 SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
267
268 /* Avoid degenerate cases: g^0 yields a spoofable signature */
269 if (BN_cmp(g_x, BN_value_one()) <= 0) {
270 error("%s: g_x <= 1", __func__);
271 return -1;
272 }
273 if (BN_cmp(g_x, grp_p) >= 0) {
274 error("%s: g_x >= p", __func__);
275 return -1;
276 }
277
278 h = g_xh = g_r = expected = NULL;
279 if ((bn_ctx = BN_CTX_new()) == NULL) {
280 error("%s: BN_CTX_new", __func__);
281 goto out;
282 }
283 if ((g_xh = BN_new()) == NULL ||
284 (g_r = BN_new()) == NULL ||
285 (gx_q = BN_new()) == NULL ||
286 (expected = BN_new()) == NULL) {
287 error("%s: BN_new", __func__);
288 goto out;
289 }
290
291 SCHNORR_DEBUG_BN((e, "%s: e = ", __func__));
292 SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
293
294 /* gx_q = (g^x)^q must === 1 mod p */
295 if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) {
296 error("%s: BN_mod_exp (g_x^q mod p)", __func__);
297 goto out;
298 }
299 if (BN_cmp(gx_q, BN_value_one()) != 0) {
300 error("%s: Invalid signature (g^x)^q != 1 mod p", __func__);
301 goto out;
302 }
303
304 SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
305 /* h = H(g || g^v || g^x || id) */
306 if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x,
307 id, idlen)) == NULL) {
308 error("%s: schnorr_hash failed", __func__);
309 goto out;
310 }
311
312 /* g_xh = (g^x)^h */
313 if (BN_mod_exp(g_xh, g_x, h, grp_p, bn_ctx) == -1) {
314 error("%s: BN_mod_exp (g_x^h mod p)", __func__);
315 goto out;
316 }
317 SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
318
319 /* g_r = g^r */
320 if (BN_mod_exp(g_r, grp_g, r, grp_p, bn_ctx) == -1) {
321 error("%s: BN_mod_exp (g_x^h mod p)", __func__);
322 goto out;
323 }
324 SCHNORR_DEBUG_BN((g_r, "%s: g_r = ", __func__));
325
326 /* expected = g^r * g_xh */
327 if (BN_mod_mul(expected, g_r, g_xh, grp_p, bn_ctx) == -1) {
328 error("%s: BN_mod_mul (expected = g_r mod p)", __func__);
329 goto out;
330 }
331 SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__));
332
333 /* Check e == expected */
334 success = BN_cmp(expected, e) == 0;
335 out:
336 BN_CTX_free(bn_ctx);
337 if (h != NULL)
338 BN_clear_free(h);
339 if (gx_q != NULL)
340 BN_clear_free(gx_q);
341 if (g_xh != NULL)
342 BN_clear_free(g_xh);
343 if (g_r != NULL)
344 BN_clear_free(g_r);
345 if (expected != NULL)
346 BN_clear_free(expected);
347 return success;
348}
349
350/*
351 * Verify Schnorr signature 'sig' of length 'siglen' against public exponent
352 * g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a
353 * SHA256 hash.
354 * Signature hash will be salted with 'idlen' bytes from 'id'.
355 * Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
356 */
357int
358schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q,
359 const BIGNUM *grp_g,
360 const BIGNUM *g_x, const u_char *id, u_int idlen,
361 const u_char *sig, u_int siglen)
362{
363 Buffer b;
364 int ret = -1;
365 u_int rlen;
366 BIGNUM *r, *e;
367
368 e = r = NULL;
369 if ((e = BN_new()) == NULL ||
370 (r = BN_new()) == NULL) {
371 error("%s: BN_new", __func__);
372 goto out;
373 }
374
375 /* Extract g^v and r from signature blob */
376 buffer_init(&b);
377 buffer_append(&b, sig, siglen);
378 SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
379 "%s: sigblob", __func__));
380 buffer_get_bignum2(&b, e);
381 buffer_get_bignum2(&b, r);
382 rlen = buffer_len(&b);
383 buffer_free(&b);
384 if (rlen != 0) {
385 error("%s: remaining bytes in signature %d", __func__, rlen);
386 goto out;
387 }
388
389 ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256,
390 g_x, id, idlen, r, e);
391 out:
392 BN_clear_free(e);
393 BN_clear_free(r);
394
395 return ret;
396}
397
398/* Helper functions */
399
400/*
401 * Generate uniformly distributed random number in range (1, high).
402 * Return number on success, NULL on failure.
403 */
404BIGNUM *
405bn_rand_range_gt_one(const BIGNUM *high)
406{
407 BIGNUM *r, *tmp;
408 int success = -1;
409
410 if ((tmp = BN_new()) == NULL) {
411 error("%s: BN_new", __func__);
412 return NULL;
413 }
414 if ((r = BN_new()) == NULL) {
415 error("%s: BN_new failed", __func__);
416 goto out;
417 }
418 if (BN_set_word(tmp, 2) != 1) {
419 error("%s: BN_set_word(tmp, 2)", __func__);
420 goto out;
421 }
422 if (BN_sub(tmp, high, tmp) == -1) {
423 error("%s: BN_sub failed (tmp = high - 2)", __func__);
424 goto out;
425 }
426 if (BN_rand_range(r, tmp) == -1) {
427 error("%s: BN_rand_range failed", __func__);
428 goto out;
429 }
430 if (BN_set_word(tmp, 2) != 1) {
431 error("%s: BN_set_word(tmp, 2)", __func__);
432 goto out;
433 }
434 if (BN_add(r, r, tmp) == -1) {
435 error("%s: BN_add failed (r = r + 2)", __func__);
436 goto out;
437 }
438 success = 0;
439 out:
440 BN_clear_free(tmp);
441 if (success == 0)
442 return r;
443 BN_clear_free(r);
444 return NULL;
445}
446
447/* XXX convert all callers of this to use ssh_digest_memory() directly */
448/*
449 * Hash contents of buffer 'b' with hash 'md'. Returns 0 on success,
450 * with digest via 'digestp' (caller to free) and length via 'lenp'.
451 * Returns -1 on failure.
452 */
453int
454hash_buffer(const u_char *buf, u_int len, int hash_alg,
455 u_char **digestp, u_int *lenp)
456{
457 u_char digest[SSH_DIGEST_MAX_LENGTH];
458 u_int digest_len = ssh_digest_bytes(hash_alg);
459
460 if (digest_len == 0) {
461 error("%s: invalid hash", __func__);
462 return -1;
463 }
464 if (ssh_digest_memory(hash_alg, buf, len, digest, digest_len) != 0) {
465 error("%s: digest_memory failed", __func__);
466 return -1;
467 }
468 *digestp = xmalloc(digest_len);
469 *lenp = digest_len;
470 memcpy(*digestp, digest, *lenp);
471 bzero(digest, sizeof(digest));
472 digest_len = 0;
473 return 0;
474}
475
476/* print formatted string followed by bignum */
477void
478debug3_bn(const BIGNUM *n, const char *fmt, ...)
479{
480 char *out, *h;
481 va_list args;
482 int ret;
483
484 out = NULL;
485 va_start(args, fmt);
486 ret = vasprintf(&out, fmt, args);
487 va_end(args);
488 if (ret == -1 || out == NULL)
489 fatal("%s: vasprintf failed", __func__);
490
491 if (n == NULL)
492 debug3("%s(null)", out);
493 else {
494 h = BN_bn2hex(n);
495 debug3("%s0x%s", out, h);
496 free(h);
497 }
498 free(out);
499}
500
501/* print formatted string followed by buffer contents in hex */
502void
503debug3_buf(const u_char *buf, u_int len, const char *fmt, ...)
504{
505 char *out, h[65];
506 u_int i, j;
507 va_list args;
508 int ret;
509
510 out = NULL;
511 va_start(args, fmt);
512 ret = vasprintf(&out, fmt, args);
513 va_end(args);
514 if (ret == -1 || out == NULL)
515 fatal("%s: vasprintf failed", __func__);
516
517 debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : "");
518 free(out);
519 if (buf == NULL)
520 return;
521
522 *h = '\0';
523 for (i = j = 0; i < len; i++) {
524 snprintf(h + j, sizeof(h) - j, "%02x", buf[i]);
525 j += 2;
526 if (j >= sizeof(h) - 1 || i == len - 1) {
527 debug3(" %s", h);
528 *h = '\0';
529 j = 0;
530 }
531 }
532}
533
534/*
535 * Construct a MODP group from hex strings p (which must be a safe
536 * prime) and g, automatically calculating subgroup q as (p / 2)
537 */
538struct modp_group *
539modp_group_from_g_and_safe_p(const char *grp_g, const char *grp_p)
540{
541 struct modp_group *ret;
542
543 ret = xcalloc(1, sizeof(*ret));
544 ret->p = ret->q = ret->g = NULL;
545 if (BN_hex2bn(&ret->p, grp_p) == 0 ||
546 BN_hex2bn(&ret->g, grp_g) == 0)
547 fatal("%s: BN_hex2bn", __func__);
548 /* Subgroup order is p/2 (p is a safe prime) */
549 if ((ret->q = BN_new()) == NULL)
550 fatal("%s: BN_new", __func__);
551 if (BN_rshift1(ret->q, ret->p) != 1)
552 fatal("%s: BN_rshift1", __func__);
553
554 return ret;
555}
556
557void
558modp_group_free(struct modp_group *grp)
559{
560 if (grp->g != NULL)
561 BN_clear_free(grp->g);
562 if (grp->p != NULL)
563 BN_clear_free(grp->p);
564 if (grp->q != NULL)
565 BN_clear_free(grp->q);
566 bzero(grp, sizeof(*grp));
567 free(grp);
568}
569
570/* main() function for self-test */
571
572#ifdef SCHNORR_MAIN
573static void
574schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q,
575 const BIGNUM *grp_g, const BIGNUM *x)
576{
577 BIGNUM *g_x;
578 u_char *sig;
579 u_int siglen;
580 BN_CTX *bn_ctx;
581
582 if ((bn_ctx = BN_CTX_new()) == NULL)
583 fatal("%s: BN_CTX_new", __func__);
584 if ((g_x = BN_new()) == NULL)
585 fatal("%s: BN_new", __func__);
586
587 if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1)
588 fatal("%s: g_x", __func__);
589 if (schnorr_sign_buf(grp_p, grp_q, grp_g, x, g_x, "junk", 4,
590 &sig, &siglen))
591 fatal("%s: schnorr_sign", __func__);
592 if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
593 sig, siglen) != 1)
594 fatal("%s: verify fail", __func__);
595 if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "JUNK", 4,
596 sig, siglen) != 0)
597 fatal("%s: verify should have failed (bad ID)", __func__);
598 sig[4] ^= 1;
599 if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
600 sig, siglen) != 0)
601 fatal("%s: verify should have failed (bit error)", __func__);
602 free(sig);
603 BN_free(g_x);
604 BN_CTX_free(bn_ctx);
605}
606
607static void
608schnorr_selftest(void)
609{
610 BIGNUM *x;
611 struct modp_group *grp;
612 u_int i;
613 char *hh;
614
615 grp = jpake_default_group();
616 if ((x = BN_new()) == NULL)
617 fatal("%s: BN_new", __func__);
618 SCHNORR_DEBUG_BN((grp->p, "%s: grp->p = ", __func__));
619 SCHNORR_DEBUG_BN((grp->q, "%s: grp->q = ", __func__));
620 SCHNORR_DEBUG_BN((grp->g, "%s: grp->g = ", __func__));
621
622 /* [1, 20) */
623 for (i = 1; i < 20; i++) {
624 printf("x = %u\n", i);
625 fflush(stdout);
626 if (BN_set_word(x, i) != 1)
627 fatal("%s: set x word", __func__);
628 schnorr_selftest_one(grp->p, grp->q, grp->g, x);
629 }
630
631 /* 100 x random [0, p) */
632 for (i = 0; i < 100; i++) {
633 if (BN_rand_range(x, grp->p) != 1)
634 fatal("%s: BN_rand_range", __func__);
635 hh = BN_bn2hex(x);
636 printf("x = (random) 0x%s\n", hh);
637 free(hh);
638 fflush(stdout);
639 schnorr_selftest_one(grp->p, grp->q, grp->g, x);
640 }
641
642 /* [q-20, q) */
643 if (BN_set_word(x, 20) != 1)
644 fatal("%s: BN_set_word (x = 20)", __func__);
645 if (BN_sub(x, grp->q, x) != 1)
646 fatal("%s: BN_sub (q - x)", __func__);
647 for (i = 0; i < 19; i++) {
648 hh = BN_bn2hex(x);
649 printf("x = (q - %d) 0x%s\n", 20 - i, hh);
650 free(hh);
651 fflush(stdout);
652 schnorr_selftest_one(grp->p, grp->q, grp->g, x);
653 if (BN_add(x, x, BN_value_one()) != 1)
654 fatal("%s: BN_add (x + 1)", __func__);
655 }
656 BN_free(x);
657}
658
659int
660main(int argc, char **argv)
661{
662 log_init(argv[0], SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_USER, 1);
663
664 schnorr_selftest();
665 return 0;
666}
667#endif
668
diff --git a/schnorr.h b/schnorr.h
deleted file mode 100644
index e2405c102..000000000
--- a/schnorr.h
+++ /dev/null
@@ -1,60 +0,0 @@
1/* $OpenBSD: schnorr.h,v 1.2 2014/01/09 23:20:00 djm Exp $ */
2/*
3 * Copyright (c) 2009 Damien Miller. All rights reserved.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef SCHNORR_H
19#define SCHNORR_H
20
21#include <sys/types.h>
22
23#include <openssl/bn.h>
24
25struct modp_group {
26 BIGNUM *p, *q, *g;
27};
28
29BIGNUM *bn_rand_range_gt_one(const BIGNUM *high);
30int hash_buffer(const u_char *, u_int, int, u_char **, u_int *);
31void debug3_bn(const BIGNUM *, const char *, ...)
32 __attribute__((__nonnull__ (2)))
33 __attribute__((format(printf, 2, 3)));
34void debug3_buf(const u_char *, u_int, const char *, ...)
35 __attribute__((__nonnull__ (3)))
36 __attribute__((format(printf, 3, 4)));
37struct modp_group *modp_group_from_g_and_safe_p(const char *, const char *);
38void modp_group_free(struct modp_group *);
39
40/* Signature and verification functions */
41int
42schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
43 int hash_alg, const BIGNUM *x, const BIGNUM *g_x,
44 const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p);
45int
46schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
47 const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
48 u_char **sig, u_int *siglen);
49int
50schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
51 int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen,
52 const BIGNUM *r, const BIGNUM *e);
53int
54schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q,
55 const BIGNUM *grp_g,
56 const BIGNUM *g_x, const u_char *id, u_int idlen,
57 const u_char *sig, u_int siglen);
58
59#endif /* JPAKE_H */
60
diff --git a/servconf.c b/servconf.c
index 9bcd05bf2..7ba65d51d 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.248 2013/12/06 13:39:49 markus Exp $ */ 2/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -147,7 +147,6 @@ initialize_server_options(ServerOptions *options)
147 options->chroot_directory = NULL; 147 options->chroot_directory = NULL;
148 options->authorized_keys_command = NULL; 148 options->authorized_keys_command = NULL;
149 options->authorized_keys_command_user = NULL; 149 options->authorized_keys_command_user = NULL;
150 options->zero_knowledge_password_authentication = -1;
151 options->revoked_keys_file = NULL; 150 options->revoked_keys_file = NULL;
152 options->trusted_user_ca_keys = NULL; 151 options->trusted_user_ca_keys = NULL;
153 options->authorized_principals_file = NULL; 152 options->authorized_principals_file = NULL;
@@ -295,8 +294,6 @@ fill_default_server_options(ServerOptions *options)
295 } 294 }
296 if (options->permit_tun == -1) 295 if (options->permit_tun == -1)
297 options->permit_tun = SSH_TUNMODE_NO; 296 options->permit_tun = SSH_TUNMODE_NO;
298 if (options->zero_knowledge_password_authentication == -1)
299 options->zero_knowledge_password_authentication = 0;
300 if (options->ip_qos_interactive == -1) 297 if (options->ip_qos_interactive == -1)
301 options->ip_qos_interactive = IPTOS_LOWDELAY; 298 options->ip_qos_interactive = IPTOS_LOWDELAY;
302 if (options->ip_qos_bulk == -1) 299 if (options->ip_qos_bulk == -1)
@@ -346,7 +343,7 @@ typedef enum {
346 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, 343 sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
347 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 344 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
348 sUsePrivilegeSeparation, sAllowAgentForwarding, 345 sUsePrivilegeSeparation, sAllowAgentForwarding,
349 sZeroKnowledgePasswordAuthentication, sHostCertificate, 346 sHostCertificate,
350 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 347 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
351 sKexAlgorithms, sIPQoS, sVersionAddendum, 348 sKexAlgorithms, sIPQoS, sVersionAddendum,
352 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 349 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
@@ -418,11 +415,6 @@ static struct {
418 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 415 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
419 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 416 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
420 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */ 417 { "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
421#ifdef JPAKE
422 { "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
423#else
424 { "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
425#endif
426 { "checkmail", sDeprecated, SSHCFG_GLOBAL }, 418 { "checkmail", sDeprecated, SSHCFG_GLOBAL },
427 { "listenaddress", sListenAddress, SSHCFG_GLOBAL }, 419 { "listenaddress", sListenAddress, SSHCFG_GLOBAL },
428 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL }, 420 { "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
@@ -1102,10 +1094,6 @@ process_server_config_line(ServerOptions *options, char *line,
1102 intptr = &options->password_authentication; 1094 intptr = &options->password_authentication;
1103 goto parse_flag; 1095 goto parse_flag;
1104 1096
1105 case sZeroKnowledgePasswordAuthentication:
1106 intptr = &options->zero_knowledge_password_authentication;
1107 goto parse_flag;
1108
1109 case sKbdInteractiveAuthentication: 1097 case sKbdInteractiveAuthentication:
1110 intptr = &options->kbd_interactive_authentication; 1098 intptr = &options->kbd_interactive_authentication;
1111 goto parse_flag; 1099 goto parse_flag;
@@ -1767,7 +1755,6 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1767 M_CP_INTOPT(hostbased_authentication); 1755 M_CP_INTOPT(hostbased_authentication);
1768 M_CP_INTOPT(hostbased_uses_name_from_packet_only); 1756 M_CP_INTOPT(hostbased_uses_name_from_packet_only);
1769 M_CP_INTOPT(kbd_interactive_authentication); 1757 M_CP_INTOPT(kbd_interactive_authentication);
1770 M_CP_INTOPT(zero_knowledge_password_authentication);
1771 M_CP_INTOPT(permit_root_login); 1758 M_CP_INTOPT(permit_root_login);
1772 M_CP_INTOPT(permit_empty_passwd); 1759 M_CP_INTOPT(permit_empty_passwd);
1773 1760
@@ -2010,10 +1997,6 @@ dump_config(ServerOptions *o)
2010 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 1997 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2011 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 1998 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
2012#endif 1999#endif
2013#ifdef JPAKE
2014 dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
2015 o->zero_knowledge_password_authentication);
2016#endif
2017 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2000 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2018 dump_cfg_fmtint(sKbdInteractiveAuthentication, 2001 dump_cfg_fmtint(sKbdInteractiveAuthentication,
2019 o->kbd_interactive_authentication); 2002 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 @@
1/* $OpenBSD: servconf.h,v 1.111 2013/12/05 01:16:41 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -117,8 +117,6 @@ typedef struct {
117 * authentication. */ 117 * authentication. */
118 int kbd_interactive_authentication; /* If true, permit */ 118 int kbd_interactive_authentication; /* If true, permit */
119 int challenge_response_authentication; 119 int challenge_response_authentication;
120 int zero_knowledge_password_authentication;
121 /* If true, permit jpake auth */
122 int permit_empty_passwd; /* If false, do not permit empty 120 int permit_empty_passwd; /* If false, do not permit empty
123 * passwords. */ 121 * passwords. */
124 int permit_user_env; /* If true, read ~/.ssh/environment */ 122 int permit_user_env; /* If true, read ~/.ssh/environment */
diff --git a/ssh2.h b/ssh2.h
index 51a963cae..59417e612 100644
--- a/ssh2.h
+++ b/ssh2.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh2.h,v 1.14 2010/08/31 11:54:45 djm Exp $ */ 1/* $OpenBSD: ssh2.h,v 1.15 2014/01/29 06:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -115,12 +115,6 @@
115#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60 115#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
116#define SSH2_MSG_USERAUTH_INFO_REQUEST 60 116#define SSH2_MSG_USERAUTH_INFO_REQUEST 60
117#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61 117#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
118#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1 60
119#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1 61
120#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2 62
121#define SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2 63
122#define SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM 64
123#define SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM 65
124 118
125/* connection protocol: generic */ 119/* connection protocol: generic */
126 120
diff --git a/sshconnect2.c b/sshconnect2.c
index 8acffc5c3..8343db10e 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.201 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.202 2014/01/29 06:18:35 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -70,8 +70,6 @@
70#include "pathnames.h" 70#include "pathnames.h"
71#include "uidswap.h" 71#include "uidswap.h"
72#include "hostfile.h" 72#include "hostfile.h"
73#include "schnorr.h"
74#include "jpake.h"
75 73
76#ifdef GSSAPI 74#ifdef GSSAPI
77#include "ssh-gss.h" 75#include "ssh-gss.h"
@@ -289,18 +287,12 @@ void input_userauth_error(int, u_int32_t, void *);
289void input_userauth_info_req(int, u_int32_t, void *); 287void input_userauth_info_req(int, u_int32_t, void *);
290void input_userauth_pk_ok(int, u_int32_t, void *); 288void input_userauth_pk_ok(int, u_int32_t, void *);
291void input_userauth_passwd_changereq(int, u_int32_t, void *); 289void input_userauth_passwd_changereq(int, u_int32_t, void *);
292void input_userauth_jpake_server_step1(int, u_int32_t, void *);
293void input_userauth_jpake_server_step2(int, u_int32_t, void *);
294void input_userauth_jpake_server_confirm(int, u_int32_t, void *);
295 290
296int userauth_none(Authctxt *); 291int userauth_none(Authctxt *);
297int userauth_pubkey(Authctxt *); 292int userauth_pubkey(Authctxt *);
298int userauth_passwd(Authctxt *); 293int userauth_passwd(Authctxt *);
299int userauth_kbdint(Authctxt *); 294int userauth_kbdint(Authctxt *);
300int userauth_hostbased(Authctxt *); 295int userauth_hostbased(Authctxt *);
301int userauth_jpake(Authctxt *);
302
303void userauth_jpake_cleanup(Authctxt *);
304 296
305#ifdef GSSAPI 297#ifdef GSSAPI
306int userauth_gssapi(Authctxt *authctxt); 298int userauth_gssapi(Authctxt *authctxt);
@@ -340,13 +332,6 @@ Authmethod authmethods[] = {
340 NULL, 332 NULL,
341 &options.pubkey_authentication, 333 &options.pubkey_authentication,
342 NULL}, 334 NULL},
343#ifdef JPAKE
344 {"jpake-01@openssh.com",
345 userauth_jpake,
346 userauth_jpake_cleanup,
347 &options.zero_knowledge_password_authentication,
348 &options.batch_mode},
349#endif
350 {"keyboard-interactive", 335 {"keyboard-interactive",
351 userauth_kbdint, 336 userauth_kbdint,
352 NULL, 337 NULL,
@@ -965,209 +950,6 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt)
965 &input_userauth_passwd_changereq); 950 &input_userauth_passwd_changereq);
966} 951}
967 952
968#ifdef JPAKE
969static char *
970pw_encrypt(const char *password, const char *crypt_scheme, const char *salt)
971{
972 /* OpenBSD crypt(3) handles all of these */
973 if (strcmp(crypt_scheme, "crypt") == 0 ||
974 strcmp(crypt_scheme, "bcrypt") == 0 ||
975 strcmp(crypt_scheme, "md5crypt") == 0 ||
976 strcmp(crypt_scheme, "crypt-extended") == 0)
977 return xstrdup(crypt(password, salt));
978 error("%s: unsupported password encryption scheme \"%.100s\"",
979 __func__, crypt_scheme);
980 return NULL;
981}
982
983static BIGNUM *
984jpake_password_to_secret(Authctxt *authctxt, const char *crypt_scheme,
985 const char *salt)
986{
987 char prompt[256], *password, *crypted;
988 u_char *secret;
989 u_int secret_len;
990 BIGNUM *ret;
991
992 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password (JPAKE): ",
993 authctxt->server_user, authctxt->host);
994 password = read_passphrase(prompt, 0);
995
996 if ((crypted = pw_encrypt(password, crypt_scheme, salt)) == NULL) {
997 logit("Disabling %s authentication", authctxt->method->name);
998 authctxt->method->enabled = NULL;
999 /* Continue with an empty password to fail gracefully */
1000 crypted = xstrdup("");
1001 }
1002
1003#ifdef JPAKE_DEBUG
1004 debug3("%s: salt = %s", __func__, salt);
1005 debug3("%s: scheme = %s", __func__, crypt_scheme);
1006 debug3("%s: crypted = %s", __func__, crypted);
1007#endif
1008
1009 if (hash_buffer(crypted, strlen(crypted), SSH_DIGEST_SHA1,
1010 &secret, &secret_len) != 0)
1011 fatal("%s: hash_buffer", __func__);
1012
1013 bzero(password, strlen(password));
1014 bzero(crypted, strlen(crypted));
1015 free(password);
1016 free(crypted);
1017
1018 if ((ret = BN_bin2bn(secret, secret_len, NULL)) == NULL)
1019 fatal("%s: BN_bin2bn (secret)", __func__);
1020 bzero(secret, secret_len);
1021 free(secret);
1022
1023 return ret;
1024}
1025
1026/* ARGSUSED */
1027void
1028input_userauth_jpake_server_step1(int type, u_int32_t seq, void *ctxt)
1029{
1030 Authctxt *authctxt = ctxt;
1031 struct jpake_ctx *pctx = authctxt->methoddata;
1032 u_char *x3_proof, *x4_proof, *x2_s_proof;
1033 u_int x3_proof_len, x4_proof_len, x2_s_proof_len;
1034 char *crypt_scheme, *salt;
1035
1036 /* Disable this message */
1037 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1, NULL);
1038
1039 if ((pctx->g_x3 = BN_new()) == NULL ||
1040 (pctx->g_x4 = BN_new()) == NULL)
1041 fatal("%s: BN_new", __func__);
1042
1043 /* Fetch step 1 values */
1044 crypt_scheme = packet_get_string(NULL);
1045 salt = packet_get_string(NULL);
1046 pctx->server_id = packet_get_string(&pctx->server_id_len);
1047 packet_get_bignum2(pctx->g_x3);
1048 packet_get_bignum2(pctx->g_x4);
1049 x3_proof = packet_get_string(&x3_proof_len);
1050 x4_proof = packet_get_string(&x4_proof_len);
1051 packet_check_eom();
1052
1053 JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
1054
1055 /* Obtain password and derive secret */
1056 pctx->s = jpake_password_to_secret(authctxt, crypt_scheme, salt);
1057 bzero(crypt_scheme, strlen(crypt_scheme));
1058 bzero(salt, strlen(salt));
1059 free(crypt_scheme);
1060 free(salt);
1061 JPAKE_DEBUG_BN((pctx->s, "%s: s = ", __func__));
1062
1063 /* Calculate step 2 values */
1064 jpake_step2(pctx->grp, pctx->s, pctx->g_x1,
1065 pctx->g_x3, pctx->g_x4, pctx->x2,
1066 pctx->server_id, pctx->server_id_len,
1067 pctx->client_id, pctx->client_id_len,
1068 x3_proof, x3_proof_len,
1069 x4_proof, x4_proof_len,
1070 &pctx->a,
1071 &x2_s_proof, &x2_s_proof_len);
1072
1073 bzero(x3_proof, x3_proof_len);
1074 bzero(x4_proof, x4_proof_len);
1075 free(x3_proof);
1076 free(x4_proof);
1077
1078 JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
1079
1080 /* Send values for step 2 */
1081 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2);
1082 packet_put_bignum2(pctx->a);
1083 packet_put_string(x2_s_proof, x2_s_proof_len);
1084 packet_send();
1085
1086 bzero(x2_s_proof, x2_s_proof_len);
1087 free(x2_s_proof);
1088
1089 /* Expect step 2 packet from peer */
1090 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2,
1091 input_userauth_jpake_server_step2);
1092}
1093
1094/* ARGSUSED */
1095void
1096input_userauth_jpake_server_step2(int type, u_int32_t seq, void *ctxt)
1097{
1098 Authctxt *authctxt = ctxt;
1099 struct jpake_ctx *pctx = authctxt->methoddata;
1100 u_char *x4_s_proof;
1101 u_int x4_s_proof_len;
1102
1103 /* Disable this message */
1104 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2, NULL);
1105
1106 if ((pctx->b = BN_new()) == NULL)
1107 fatal("%s: BN_new", __func__);
1108
1109 /* Fetch step 2 values */
1110 packet_get_bignum2(pctx->b);
1111 x4_s_proof = packet_get_string(&x4_s_proof_len);
1112 packet_check_eom();
1113
1114 JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
1115
1116 /* Derive shared key and calculate confirmation hash */
1117 jpake_key_confirm(pctx->grp, pctx->s, pctx->b,
1118 pctx->x2, pctx->g_x1, pctx->g_x2, pctx->g_x3, pctx->g_x4,
1119 pctx->client_id, pctx->client_id_len,
1120 pctx->server_id, pctx->server_id_len,
1121 session_id2, session_id2_len,
1122 x4_s_proof, x4_s_proof_len,
1123 &pctx->k,
1124 &pctx->h_k_cid_sessid, &pctx->h_k_cid_sessid_len);
1125
1126 bzero(x4_s_proof, x4_s_proof_len);
1127 free(x4_s_proof);
1128
1129 JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
1130
1131 /* Send key confirmation proof */
1132 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM);
1133 packet_put_string(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
1134 packet_send();
1135
1136 /* Expect confirmation from peer */
1137 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM,
1138 input_userauth_jpake_server_confirm);
1139}
1140
1141/* ARGSUSED */
1142void
1143input_userauth_jpake_server_confirm(int type, u_int32_t seq, void *ctxt)
1144{
1145 Authctxt *authctxt = ctxt;
1146 struct jpake_ctx *pctx = authctxt->methoddata;
1147
1148 /* Disable this message */
1149 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM, NULL);
1150
1151 pctx->h_k_sid_sessid = packet_get_string(&pctx->h_k_sid_sessid_len);
1152 packet_check_eom();
1153
1154 JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
1155
1156 /* Verify expected confirmation hash */
1157 if (jpake_check_confirm(pctx->k,
1158 pctx->server_id, pctx->server_id_len,
1159 session_id2, session_id2_len,
1160 pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len) == 1)
1161 debug("%s: %s success", __func__, authctxt->method->name);
1162 else {
1163 debug("%s: confirmation mismatch", __func__);
1164 /* XXX stash this so if auth succeeds then we can warn/kill */
1165 }
1166
1167 userauth_jpake_cleanup(authctxt);
1168}
1169#endif /* JPAKE */
1170
1171static int 953static int
1172identity_sign(Identity *id, u_char **sigp, u_int *lenp, 954identity_sign(Identity *id, u_char **sigp, u_int *lenp,
1173 u_char *data, u_int datalen) 955 u_char *data, u_int datalen)
@@ -1783,79 +1565,6 @@ userauth_hostbased(Authctxt *authctxt)
1783 return 1; 1565 return 1;
1784} 1566}
1785 1567
1786#ifdef JPAKE
1787int
1788userauth_jpake(Authctxt *authctxt)
1789{
1790 struct jpake_ctx *pctx;
1791 u_char *x1_proof, *x2_proof;
1792 u_int x1_proof_len, x2_proof_len;
1793 static int attempt = 0; /* XXX share with userauth_password's? */
1794
1795 if (attempt++ >= options.number_of_password_prompts)
1796 return 0;
1797 if (attempt != 1)
1798 error("Permission denied, please try again.");
1799
1800 if (authctxt->methoddata != NULL)
1801 fatal("%s: authctxt->methoddata already set (%p)",
1802 __func__, authctxt->methoddata);
1803
1804 authctxt->methoddata = pctx = jpake_new();
1805
1806 /*
1807 * Send request immediately, to get the protocol going while
1808 * we do the initial computations.
1809 */
1810 packet_start(SSH2_MSG_USERAUTH_REQUEST);
1811 packet_put_cstring(authctxt->server_user);
1812 packet_put_cstring(authctxt->service);
1813 packet_put_cstring(authctxt->method->name);
1814 packet_send();
1815 packet_write_wait();
1816
1817 jpake_step1(pctx->grp,
1818 &pctx->client_id, &pctx->client_id_len,
1819 &pctx->x1, &pctx->x2, &pctx->g_x1, &pctx->g_x2,
1820 &x1_proof, &x1_proof_len,
1821 &x2_proof, &x2_proof_len);
1822
1823 JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
1824
1825 packet_start(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1);
1826 packet_put_string(pctx->client_id, pctx->client_id_len);
1827 packet_put_bignum2(pctx->g_x1);
1828 packet_put_bignum2(pctx->g_x2);
1829 packet_put_string(x1_proof, x1_proof_len);
1830 packet_put_string(x2_proof, x2_proof_len);
1831 packet_send();
1832
1833 bzero(x1_proof, x1_proof_len);
1834 bzero(x2_proof, x2_proof_len);
1835 free(x1_proof);
1836 free(x2_proof);
1837
1838 /* Expect step 1 packet from peer */
1839 dispatch_set(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1,
1840 input_userauth_jpake_server_step1);
1841 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS,
1842 &input_userauth_success_unexpected);
1843
1844 return 1;
1845}
1846
1847void
1848userauth_jpake_cleanup(Authctxt *authctxt)
1849{
1850 debug3("%s: clean up", __func__);
1851 if (authctxt->methoddata != NULL) {
1852 jpake_free(authctxt->methoddata);
1853 authctxt->methoddata = NULL;
1854 }
1855 dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
1856}
1857#endif /* JPAKE */
1858
1859/* find auth method */ 1568/* find auth method */
1860 1569
1861/* 1570/*