diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | auth.h | 6 | ||||
-rw-r--r-- | auth2-jpake.c | 563 | ||||
-rw-r--r-- | auth2.c | 11 | ||||
-rw-r--r-- | jpake.c | 456 | ||||
-rw-r--r-- | jpake.h | 114 | ||||
-rw-r--r-- | monitor.c | 226 | ||||
-rw-r--r-- | monitor.h | 7 | ||||
-rw-r--r-- | monitor_wrap.c | 165 | ||||
-rw-r--r-- | monitor_wrap.h | 22 | ||||
-rw-r--r-- | readconf.c | 17 | ||||
-rw-r--r-- | readconf.h | 3 | ||||
-rw-r--r-- | schnorr.c | 668 | ||||
-rw-r--r-- | schnorr.h | 60 | ||||
-rw-r--r-- | servconf.c | 21 | ||||
-rw-r--r-- | servconf.h | 4 | ||||
-rw-r--r-- | ssh2.h | 8 | ||||
-rw-r--r-- | sshconnect2.c | 293 |
19 files changed, 22 insertions, 2633 deletions
@@ -20,6 +20,11 @@ | |||
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 | ||
24 | 20140131 | 29 | 20140131 |
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 \ |
@@ -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 **); | |||
175 | int skey_query(void *, char **, char **, u_int *, char ***, u_int **); | 174 | int skey_query(void *, char **, char **, u_int *, char ***, u_int **); |
176 | int skey_respond(void *, u_int, char **); | 175 | int skey_respond(void *, u_int, char **); |
177 | 176 | ||
178 | void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **); | ||
179 | void auth2_jpake_stop(Authctxt *); | ||
180 | |||
181 | int allowed_user(struct passwd *); | 177 | int allowed_user(struct passwd *); |
182 | struct passwd * getpwnamallow(const char *user); | 178 | struct 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 */ | ||
67 | static void input_userauth_jpake_client_step1(int, u_int32_t, void *); | ||
68 | static void input_userauth_jpake_client_step2(int, u_int32_t, void *); | ||
69 | static void input_userauth_jpake_client_confirm(int, u_int32_t, void *); | ||
70 | |||
71 | static int auth2_jpake_start(Authctxt *); | ||
72 | |||
73 | /* import */ | ||
74 | extern ServerOptions options; | ||
75 | extern u_char *session_id2; | ||
76 | extern u_int session_id2_len; | ||
77 | |||
78 | /* | ||
79 | * Attempt J-PAKE authentication. | ||
80 | */ | ||
81 | static int | ||
82 | userauth_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 | |||
100 | Authmethod method_jpake = { | ||
101 | "jpake-01@openssh.com", | ||
102 | userauth_jpake, | ||
103 | &options.zero_knowledge_password_authentication | ||
104 | }; | ||
105 | |||
106 | /* Clear context and callbacks */ | ||
107 | void | ||
108 | auth2_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 */ | ||
121 | static int | ||
122 | valid_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 | */ | ||
139 | static void | ||
140 | derive_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 */ | ||
186 | static char | ||
187 | pw_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 */ | ||
195 | static char * | ||
196 | makesalt(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 | */ | ||
219 | static void | ||
220 | fake_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 | */ | ||
271 | void | ||
272 | auth2_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 | */ | ||
371 | static int | ||
372 | auth2_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 */ | ||
422 | static void | ||
423 | input_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 */ | ||
480 | static void | ||
481 | input_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 */ | ||
530 | static void | ||
531 | input_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 | |||
@@ -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 |
72 | extern Authmethod method_gssapi; | 72 | extern Authmethod method_gssapi; |
73 | #endif | 73 | #endif |
74 | #ifdef JPAKE | ||
75 | extern Authmethod method_jpake; | ||
76 | #endif | ||
77 | 74 | ||
78 | Authmethod *authmethods[] = { | 75 | Authmethod *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 | |||
65 | struct modp_group * | ||
66 | jpake_default_group(void) | ||
67 | { | ||
68 | return modp_group_from_g_and_safe_p(JPAKE_GROUP_G, JPAKE_GROUP_P); | ||
69 | } | ||
70 | |||
71 | struct jpake_ctx * | ||
72 | jpake_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 | |||
93 | void | ||
94 | jpake_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! */ | ||
141 | void | ||
142 | jpake_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 */ | ||
192 | void | ||
193 | jpake_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 */ | ||
245 | void | ||
246 | jpake_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 */ | ||
324 | void | ||
325 | jpake_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 */ | ||
348 | void | ||
349 | jpake_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 | */ | ||
422 | int | ||
423 | jpake_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 | |||
38 | struct 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 */ | ||
82 | struct modp_group *jpake_default_group(void); | ||
83 | void jpake_dump(struct jpake_ctx *, const char *, ...) | ||
84 | __attribute__((__nonnull__ (2))) | ||
85 | __attribute__((format(printf, 2, 3))); | ||
86 | struct jpake_ctx *jpake_new(void); | ||
87 | void jpake_free(struct jpake_ctx *); | ||
88 | |||
89 | void jpake_step1(struct modp_group *, u_char **, u_int *, | ||
90 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, | ||
91 | u_char **, u_int *, u_char **, u_int *); | ||
92 | |||
93 | void 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 | |||
99 | void jpake_confirm_hash(const BIGNUM *, | ||
100 | const u_char *, u_int, | ||
101 | const u_char *, u_int, | ||
102 | u_char **, u_int *); | ||
103 | |||
104 | void 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 | |||
110 | int 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 | |||
@@ -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 *); | |||
161 | int mm_answer_rsa_response(int, Buffer *); | 160 | int mm_answer_rsa_response(int, Buffer *); |
162 | int mm_answer_sesskey(int, Buffer *); | 161 | int mm_answer_sesskey(int, Buffer *); |
163 | int mm_answer_sessid(int, Buffer *); | 162 | int mm_answer_sessid(int, Buffer *); |
164 | int mm_answer_jpake_get_pwdata(int, Buffer *); | ||
165 | int mm_answer_jpake_step1(int, Buffer *); | ||
166 | int mm_answer_jpake_step2(int, Buffer *); | ||
167 | int mm_answer_jpake_key_confirm(int, Buffer *); | ||
168 | int mm_answer_jpake_check_confirm(int, Buffer *); | ||
169 | 163 | ||
170 | #ifdef USE_PAM | 164 | #ifdef USE_PAM |
171 | int mm_answer_pam_start(int, Buffer *); | 165 | int 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 | ||
2163 | int | ||
2164 | mm_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 | |||
2208 | int | ||
2209 | mm_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 | |||
2237 | int | ||
2238 | mm_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 | |||
2288 | int | ||
2289 | mm_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 | |||
2328 | int | ||
2329 | mm_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 */ | ||
@@ -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 | ||
1296 | void | ||
1297 | mm_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 | |||
1318 | void | ||
1319 | mm_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 | |||
1353 | void | ||
1354 | mm_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 | |||
1393 | void | ||
1394 | mm_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 | |||
1427 | int | ||
1428 | mm_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 **); | |||
102 | int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); | 102 | int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **); |
103 | int mm_skey_respond(void *, u_int, char **); | 103 | int mm_skey_respond(void *, u_int, char **); |
104 | 104 | ||
105 | /* jpake */ | ||
106 | struct modp_group; | ||
107 | void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **); | ||
108 | void mm_jpake_step1(struct modp_group *, u_char **, u_int *, | ||
109 | BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **, | ||
110 | u_char **, u_int *, u_char **, u_int *); | ||
111 | void 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 *); | ||
116 | void 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 *); | ||
121 | int 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 | ||
127 | void *mm_zalloc(struct mm_master *, u_int, u_int); | 107 | void *mm_zalloc(struct mm_master *, u_int, u_int); |
diff --git a/readconf.c b/readconf.c index 7b42f68d9..f80d1ccbc 100644 --- a/readconf.c +++ b/readconf.c | |||
@@ -1,4 +1,4 @@ | |||
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 | */ | ||
64 | static BIGNUM * | ||
65 | schnorr_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 | */ | ||
125 | int | ||
126 | schnorr_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 | */ | ||
219 | int | ||
220 | schnorr_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 | */ | ||
256 | int | ||
257 | schnorr_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 | */ | ||
357 | int | ||
358 | schnorr_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 | */ | ||
404 | BIGNUM * | ||
405 | bn_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 | */ | ||
453 | int | ||
454 | hash_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 */ | ||
477 | void | ||
478 | debug3_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 */ | ||
502 | void | ||
503 | debug3_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 | */ | ||
538 | struct modp_group * | ||
539 | modp_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 | |||
557 | void | ||
558 | modp_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 | ||
573 | static void | ||
574 | schnorr_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 | |||
607 | static void | ||
608 | schnorr_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 | |||
659 | int | ||
660 | main(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 | |||
25 | struct modp_group { | ||
26 | BIGNUM *p, *q, *g; | ||
27 | }; | ||
28 | |||
29 | BIGNUM *bn_rand_range_gt_one(const BIGNUM *high); | ||
30 | int hash_buffer(const u_char *, u_int, int, u_char **, u_int *); | ||
31 | void debug3_bn(const BIGNUM *, const char *, ...) | ||
32 | __attribute__((__nonnull__ (2))) | ||
33 | __attribute__((format(printf, 2, 3))); | ||
34 | void debug3_buf(const u_char *, u_int, const char *, ...) | ||
35 | __attribute__((__nonnull__ (3))) | ||
36 | __attribute__((format(printf, 3, 4))); | ||
37 | struct modp_group *modp_group_from_g_and_safe_p(const char *, const char *); | ||
38 | void modp_group_free(struct modp_group *); | ||
39 | |||
40 | /* Signature and verification functions */ | ||
41 | int | ||
42 | schnorr_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); | ||
45 | int | ||
46 | schnorr_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); | ||
49 | int | ||
50 | schnorr_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); | ||
53 | int | ||
54 | schnorr_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 */ |
@@ -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 *); | |||
289 | void input_userauth_info_req(int, u_int32_t, void *); | 287 | void input_userauth_info_req(int, u_int32_t, void *); |
290 | void input_userauth_pk_ok(int, u_int32_t, void *); | 288 | void input_userauth_pk_ok(int, u_int32_t, void *); |
291 | void input_userauth_passwd_changereq(int, u_int32_t, void *); | 289 | void input_userauth_passwd_changereq(int, u_int32_t, void *); |
292 | void input_userauth_jpake_server_step1(int, u_int32_t, void *); | ||
293 | void input_userauth_jpake_server_step2(int, u_int32_t, void *); | ||
294 | void input_userauth_jpake_server_confirm(int, u_int32_t, void *); | ||
295 | 290 | ||
296 | int userauth_none(Authctxt *); | 291 | int userauth_none(Authctxt *); |
297 | int userauth_pubkey(Authctxt *); | 292 | int userauth_pubkey(Authctxt *); |
298 | int userauth_passwd(Authctxt *); | 293 | int userauth_passwd(Authctxt *); |
299 | int userauth_kbdint(Authctxt *); | 294 | int userauth_kbdint(Authctxt *); |
300 | int userauth_hostbased(Authctxt *); | 295 | int userauth_hostbased(Authctxt *); |
301 | int userauth_jpake(Authctxt *); | ||
302 | |||
303 | void userauth_jpake_cleanup(Authctxt *); | ||
304 | 296 | ||
305 | #ifdef GSSAPI | 297 | #ifdef GSSAPI |
306 | int userauth_gssapi(Authctxt *authctxt); | 298 | int 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 | ||
969 | static char * | ||
970 | pw_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 | |||
983 | static BIGNUM * | ||
984 | jpake_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 */ | ||
1027 | void | ||
1028 | input_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 */ | ||
1095 | void | ||
1096 | input_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 */ | ||
1142 | void | ||
1143 | input_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 | |||
1171 | static int | 953 | static int |
1172 | identity_sign(Identity *id, u_char **sigp, u_int *lenp, | 954 | identity_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 | ||
1787 | int | ||
1788 | userauth_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 | |||
1847 | void | ||
1848 | userauth_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 | /* |