Vendor import of OpenSSH 6.6p1.

This commit is contained in:
Dag-Erling Smørgrav 2014-03-22 15:23:38 +00:00
parent 02d4c2ac3d
commit 0c79dacc8a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor-crypto/openssh/dist/; revision=263635
svn path=/vendor-crypto/openssh/6.6p1/; revision=263636; tag=vendor/openssh/6.6p1
120 changed files with 1512 additions and 3126 deletions

222
ChangeLog
View File

@ -1,3 +1,224 @@
20140313
- (djm) Release OpenSSH 6.6
20140304
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2014/03/03 22:22:30
[session.c]
ignore enviornment variables with embedded '=' or '\0' characters;
spotted by Jann Horn; ok deraadt@
20140301
- (djm) [regress/Makefile] Disable dhgex regress test; it breaks when
no moduli file exists at the expected location.
20140228
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2014/02/27 00:41:49
[bufbn.c]
fix unsigned overflow that could lead to reading a short ssh protocol
1 bignum value; found by Ben Hawkes; ok deraadt@
- djm@cvs.openbsd.org 2014/02/27 08:25:09
[bufbn.c]
off by one in range check
- djm@cvs.openbsd.org 2014/02/27 22:47:07
[sshd_config.5]
bz#2184 clarify behaviour of a keyword that appears in multiple
matching Match blocks; ok dtucker@
- djm@cvs.openbsd.org 2014/02/27 22:57:40
[version.h]
openssh-6.6
- dtucker@cvs.openbsd.org 2014/01/19 23:43:02
[regress/sftp-chroot.sh]
Don't use -q on sftp as it suppresses logging, instead redirect the
output to the regress logfile.
- dtucker@cvs.openbsd.org 2014/01/20 00:00:30
[sregress/ftp-chroot.sh]
append to rather than truncating the log file
- dtucker@cvs.openbsd.org 2014/01/25 04:35:32
[regress/Makefile regress/dhgex.sh]
Add a test for DH GEX sizes
- djm@cvs.openbsd.org 2014/01/26 10:22:10
[regress/cert-hostkey.sh]
automatically generate revoked keys from listed keys rather than
manually specifying each type; from portable
(Id sync only)
- djm@cvs.openbsd.org 2014/01/26 10:49:17
[scp-ssh-wrapper.sh scp.sh]
make sure $SCP is tested on the remote end rather than whichever one
happens to be in $PATH; from portable
(Id sync only)
- djm@cvs.openbsd.org 2014/02/27 20:04:16
[login-timeout.sh]
remove any existing LoginGraceTime from sshd_config before adding
a specific one for the test back in
- djm@cvs.openbsd.org 2014/02/27 21:21:25
[agent-ptrace.sh agent.sh]
keep return values that are printed in error messages;
from portable
(Id sync only)
- (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec]
[contrib/suse/openssh.spec] Crank version numbers
- (djm) [regress/host-expand.sh] Add RCS Id
20140227
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2014/02/26 20:18:37
[ssh.c]
bz#2205: avoid early hostname lookups unless canonicalisation is enabled;
ok dtucker@ markus@
- djm@cvs.openbsd.org 2014/02/26 20:28:44
[auth2-gss.c gss-serv.c ssh-gss.h sshd.c]
bz#2107 - cache OIDs of supported GSSAPI mechanisms before privsep
sandboxing, as running this code in the sandbox can cause violations;
ok markus@
- djm@cvs.openbsd.org 2014/02/26 20:29:29
[channels.c]
don't assume that the socks4 username is \0 terminated;
spotted by Ben Hawkes; ok markus@
- markus@cvs.openbsd.org 2014/02/26 21:53:37
[sshd.c]
ssh_gssapi_prepare_supported_oids needs GSSAPI
20140224
- OpenBSD CVS Sync
- djm@cvs.openbsd.org 2014/02/07 06:55:54
[cipher.c mac.c]
remove some logging that makes ssh debugging output very verbose;
ok markus
- djm@cvs.openbsd.org 2014/02/15 23:05:36
[channels.c]
avoid spurious "getsockname failed: Bad file descriptor" errors in ssh -W;
bz#2200, debian#738692 via Colin Watson; ok dtucker@
- djm@cvs.openbsd.org 2014/02/22 01:32:19
[readconf.c]
when processing Match blocks, skip 'exec' clauses if previous predicates
failed to match; ok markus@
- djm@cvs.openbsd.org 2014/02/23 20:03:42
[ssh-ed25519.c]
check for unsigned overflow; not reachable in OpenSSH but others might
copy our code...
- djm@cvs.openbsd.org 2014/02/23 20:11:36
[readconf.c readconf.h ssh.c ssh_config.5]
reparse ssh_config and ~/.ssh/config if hostname canonicalisation changes
the hostname. This allows users to write configurations that always
refer to canonical hostnames, e.g.
CanonicalizeHostname yes
CanonicalDomains int.example.org example.org
CanonicalizeFallbackLocal no
Host *.int.example.org
Compression off
Host *.example.org
User djm
ok markus@
20140213
- (dtucker) [configure.ac openbsd-compat/openssl-compat.{c,h}] Add compat
code for older OpenSSL versions that don't have EVP_MD_CTX_copy_ex.
20140207
- OpenBSD CVS Sync
- naddy@cvs.openbsd.org 2014/02/05 20:13:25
[ssh-keygen.1 ssh-keygen.c]
tweak synopsis: calling ssh-keygen without any arguments is fine; ok jmc@
while here, fix ordering in usage(); requested by jmc@
- djm@cvs.openbsd.org 2014/02/06 22:21:01
[sshconnect.c]
in ssh_create_socket(), only do the getaddrinfo for BindAddress when
BindAddress is actually specified. Fixes regression in 6.5 for
UsePrivilegedPort=yes; patch from Corinna Vinschen
20140206
- (dtucker) [openbsd-compat/bsd-poll.c] Don't bother checking for non-NULL
before freeing since free(NULL) is a no-op. ok djm.
- (djm) [sandbox-seccomp-filter.c] Not all Linux architectures define
__NR_shutdown; some go via the socketcall(2) multiplexer.
20140205
- (djm) [sandbox-capsicum.c] Don't fatal if Capsicum is offered by
headers/libc but not supported by the kernel. Patch from Loganaden
Velvindron @ AfriNIC
20140204
- OpenBSD CVS Sync
- markus@cvs.openbsd.org 2014/01/27 18:58:14
[Makefile.in digest.c digest.h hostfile.c kex.h mac.c hmac.c hmac.h]
replace openssl HMAC with an implementation based on our ssh_digest_*
ok and feedback djm@
- markus@cvs.openbsd.org 2014/01/27 19:18:54
[auth-rsa.c cipher.c ssh-agent.c sshconnect1.c sshd.c]
replace openssl MD5 with our ssh_digest_*; ok djm@
- markus@cvs.openbsd.org 2014/01/27 20:13:46
[digest.c digest-openssl.c digest-libc.c Makefile.in]
rename digest.c to digest-openssl.c and add libc variant; ok djm@
- jmc@cvs.openbsd.org 2014/01/28 14:13:39
[ssh-keyscan.1]
kill some bad Pa;
From: Jan Stary
- djm@cvs.openbsd.org 2014/01/29 00:19:26
[sshd.c]
use kill(0, ...) instead of killpg(0, ...); on most operating systems
they are equivalent, but SUSv2 describes the latter as having undefined
behaviour; from portable; ok dtucker
(Id sync only; change is already in portable)
- djm@cvs.openbsd.org 2014/01/29 06:18:35
[Makefile.in auth.h auth2-jpake.c auth2.c jpake.c jpake.h monitor.c]
[monitor.h monitor_wrap.c monitor_wrap.h readconf.c readconf.h]
[schnorr.c schnorr.h servconf.c servconf.h ssh2.h sshconnect2.c]
remove experimental, never-enabled JPAKE code; ok markus@
- jmc@cvs.openbsd.org 2014/01/29 14:04:51
[sshd_config.5]
document kbdinteractiveauthentication;
requested From: Ross L Richardson
dtucker/markus helped explain its workings;
- djm@cvs.openbsd.org 2014/01/30 22:26:14
[sandbox-systrace.c]
allow shutdown(2) syscall in sandbox - it may be called by packet_close()
from portable
(Id sync only; change is already in portable)
- tedu@cvs.openbsd.org 2014/01/31 16:39:19
[auth2-chall.c authfd.c authfile.c bufaux.c bufec.c canohost.c]
[channels.c cipher-chachapoly.c clientloop.c configure.ac hostfile.c]
[kexc25519.c krl.c monitor.c sandbox-systrace.c session.c]
[sftp-client.c ssh-keygen.c ssh.c sshconnect2.c sshd.c sshlogin.c]
[openbsd-compat/explicit_bzero.c openbsd-compat/openbsd-compat.h]
replace most bzero with explicit_bzero, except a few that cna be memset
ok djm dtucker
- djm@cvs.openbsd.org 2014/02/02 03:44:32
[auth1.c auth2-chall.c auth2-passwd.c authfile.c bufaux.c bufbn.c]
[buffer.c cipher-3des1.c cipher.c clientloop.c gss-serv.c kex.c]
[kexdhc.c kexdhs.c kexecdhc.c kexgexc.c kexecdhs.c kexgexs.c key.c]
[monitor.c monitor_wrap.c packet.c readpass.c rsa.c serverloop.c]
[ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c]
[ssh-keygen.c ssh-rsa.c sshconnect.c sshconnect1.c sshconnect2.c]
[sshd.c]
convert memset of potentially-private data to explicit_bzero()
- djm@cvs.openbsd.org 2014/02/03 23:28:00
[ssh-ecdsa.c]
fix memory leak; ECDSA_SIG_new() allocates 'r' and 's' for us, unlike
DSA_SIG_new. Reported by Batz Spear; ok markus@
- djm@cvs.openbsd.org 2014/02/02 03:44:31
[digest-libc.c digest-openssl.c]
convert memset of potentially-private data to explicit_bzero()
- djm@cvs.openbsd.org 2014/02/04 00:24:29
[ssh.c]
delay lowercasing of hostname until right before hostname
canonicalisation to unbreak case-sensitive matching of ssh_config;
reported by Ike Devolder; ok markus@
- (djm) [openbsd-compat/Makefile.in] Add missing explicit_bzero.o
- (djm) [regress/setuid-allowed.c] Missing string.h for strerror()
20140131
- (djm) [sandbox-seccomp-filter.c sandbox-systrace.c] Allow shutdown(2)
syscall from sandboxes; it may be called by packet_close.
- (dtucker) [readconf.c] Include <arpa/inet.h> for the hton macros. Fixes
build with HP-UX's compiler. Patch from Kevin Brott.
- (tim) [Makefile.in] build regress/setuid-allow.
20140130
- (djm) [configure.ac] Only check for width-specified integer types
in headers that actually exist. patch from Tom G. Christensen;
@ -2663,3 +2884,4 @@
[contrib/suse/openssh.spec] Update for release 6.0
- (djm) [README] Update URL to release notes.
- (djm) Release openssh-6.0

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.352 2014/01/27 06:35:04 dtucker Exp $
# $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $
# uncomment if you run a non bourne compatable shell. Ie. csh
#SHELL = @SH@
@ -73,9 +73,9 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \
monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
jpake.o schnorr.o ssh-pkcs11.o krl.o smult_curve25519_ref.o \
ssh-pkcs11.o krl.o smult_curve25519_ref.o \
kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
ssh-ed25519.o digest.o \
ssh-ed25519.o digest-openssl.o hmac.o \
sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o blocks.o
SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \
@ -88,7 +88,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
auth.o auth1.o auth2.o auth-options.o session.o \
auth-chall.o auth2-chall.o groupaccess.o \
auth-skey.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-jpake.o \
auth2-none.o auth2-passwd.o auth2-pubkey.o \
monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
kexc25519s.o auth-krb5.o \
auth2-gss.o gss-serv.o gss-serv-krb5.o \
@ -408,7 +408,7 @@ regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
$(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT)
tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$(EXEEXT)
BUILDDIR=`pwd`; \
TEST_SHELL="@TEST_SHELL@"; \
TEST_SSH_SCP="$${BUILDDIR}/scp"; \

4
README
View File

@ -1,4 +1,4 @@
See http://www.openssh.com/txt/release-6.5 for the release notes.
See http://www.openssh.com/txt/release-6.6 for the release notes.
- A Japanese translation of this document and of the OpenSSH FAQ is
- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@ -62,4 +62,4 @@ References -
[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
[7] http://www.openssh.com/faq.html
$Id: README,v 1.85 2014/01/16 07:51:45 djm Exp $
$Id: README,v 1.86 2014/02/27 23:03:53 djm Exp $

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-rsa.c,v 1.85 2013/07/12 00:19:58 djm Exp $ */
/* $OpenBSD: auth-rsa.c,v 1.86 2014/01/27 19:18:54 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -20,7 +20,6 @@
#include <sys/stat.h>
#include <openssl/rsa.h>
#include <openssl/md5.h>
#include <pwd.h>
#include <stdio.h>
@ -48,6 +47,8 @@
#include "ssh.h"
#include "misc.h"
#include "digest.h"
/* import */
extern ServerOptions options;
@ -91,12 +92,13 @@ int
auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
{
u_char buf[32], mdbuf[16];
MD5_CTX md;
struct ssh_digest_ctx *md;
int len;
/* don't allow short keys */
if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits",
error("%s: RSA modulus too small: %d < minimum %d bits",
__func__,
BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE);
return (0);
}
@ -104,13 +106,15 @@ auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16])
/* The response is MD5 of decrypted challenge plus session id. */
len = BN_num_bytes(challenge);
if (len <= 0 || len > 32)
fatal("auth_rsa_verify_response: bad challenge length %d", len);
fatal("%s: bad challenge length %d", __func__, len);
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
ssh_digest_update(md, buf, 32) < 0 ||
ssh_digest_update(md, session_id, 16) < 0 ||
ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
fatal("%s: md5 failed", __func__);
ssh_digest_free(md);
/* Verify that the response is the original challenge. */
if (timingsafe_bcmp(response, mdbuf, 16) != 0) {

6
auth.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.h,v 1.76 2013/07/19 07:37:48 markus Exp $ */
/* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -61,7 +61,6 @@ struct Authctxt {
char *style;
void *kbdintctxt;
char *info; /* Extra info for next auth_log */
void *jpake_ctx;
#ifdef BSD_AUTH
auth_session_t *as;
#endif
@ -175,9 +174,6 @@ int bsdauth_respond(void *, u_int, char **);
int skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int skey_respond(void *, u_int, char **);
void auth2_jpake_get_pwdata(Authctxt *, BIGNUM **, char **, char **);
void auth2_jpake_stop(Authctxt *);
int allowed_user(struct passwd *);
struct passwd * getpwnamallow(const char *user);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth1.c,v 1.79 2013/05/19 02:42:42 djm Exp $ */
/* $OpenBSD: auth1.c,v 1.80 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -129,7 +129,7 @@ auth1_process_password(Authctxt *authctxt)
/* Try authentication with the password. */
authenticated = PRIVSEP(auth_password(authctxt, password));
memset(password, 0, dlen);
explicit_bzero(password, dlen);
free(password);
return (authenticated);
@ -222,7 +222,7 @@ auth1_process_tis_response(Authctxt *authctxt)
response = packet_get_string(&dlen);
packet_check_eom();
authenticated = verify_response(authctxt, response);
memset(response, 'r', dlen);
explicit_bzero(response, dlen);
free(response);
return (authenticated);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-chall.c,v 1.39 2013/11/08 00:39:14 djm Exp $ */
/* $OpenBSD: auth2-chall.c,v 1.41 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2001 Per Allansson. All rights reserved.
@ -148,7 +148,7 @@ kbdint_free(KbdintAuthctxt *kbdintctxt)
if (kbdintctxt->device)
kbdint_reset_device(kbdintctxt);
free(kbdintctxt->devices);
bzero(kbdintctxt, sizeof(*kbdintctxt));
explicit_bzero(kbdintctxt, sizeof(*kbdintctxt));
free(kbdintctxt);
}
/* get next device */
@ -312,7 +312,7 @@ input_userauth_info_response(int type, u_int32_t seq, void *ctxt)
res = kbdintctxt->device->respond(kbdintctxt->ctxt, nresp, response);
for (i = 0; i < nresp; i++) {
memset(response[i], 'r', strlen(response[i]));
explicit_bzero(response[i], strlen(response[i]));
free(response[i]);
}
free(response);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-gss.c,v 1.20 2013/05/17 00:13:13 djm Exp $ */
/* $OpenBSD: auth2-gss.c,v 1.21 2014/02/26 20:28:44 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@ -62,7 +62,6 @@ userauth_gssapi(Authctxt *authctxt)
gss_OID_desc goid = {0, NULL};
Gssctxt *ctxt = NULL;
int mechs;
gss_OID_set supported;
int present;
OM_uint32 ms;
u_int len;
@ -77,7 +76,6 @@ userauth_gssapi(Authctxt *authctxt)
return (0);
}
ssh_gssapi_supported_oids(&supported);
do {
mechs--;
@ -90,15 +88,12 @@ userauth_gssapi(Authctxt *authctxt)
doid[1] == len - 2) {
goid.elements = doid + 2;
goid.length = len - 2;
gss_test_oid_set_member(&ms, &goid, supported,
&present);
ssh_gssapi_test_oid_supported(&ms, &goid, &present);
} else {
logit("Badly formed OID received");
}
} while (mechs > 0 && !present);
gss_release_oid_set(&ms, &supported);
if (!present) {
free(doid);
authctxt->server_caused_failure = 1;

View File

@ -1,563 +0,0 @@
/* $OpenBSD: auth2-jpake.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Server side of zero-knowledge password auth using J-PAKE protocol
* as described in:
*
* F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
* 16th Workshop on Security Protocols, Cambridge, April 2008
*
* http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
*/
#ifdef JPAKE
#include <sys/types.h>
#include <sys/param.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <login_cap.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "ssh2.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "buffer.h"
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "servconf.h"
#include "auth-options.h"
#include "canohost.h"
#ifdef GSSAPI
#include "ssh-gss.h"
#endif
#include "monitor_wrap.h"
#include "schnorr.h"
#include "jpake.h"
/*
* XXX options->permit_empty_passwd (at the moment, they will be refused
* anyway because they will mismatch on fake salt.
*/
/* Dispatch handlers */
static void input_userauth_jpake_client_step1(int, u_int32_t, void *);
static void input_userauth_jpake_client_step2(int, u_int32_t, void *);
static void input_userauth_jpake_client_confirm(int, u_int32_t, void *);
static int auth2_jpake_start(Authctxt *);
/* import */
extern ServerOptions options;
extern u_char *session_id2;
extern u_int session_id2_len;
/*
* Attempt J-PAKE authentication.
*/
static int
userauth_jpake(Authctxt *authctxt)
{
int authenticated = 0;
packet_check_eom();
debug("jpake-01@openssh.com requested");
if (authctxt->user != NULL) {
if (authctxt->jpake_ctx == NULL)
authctxt->jpake_ctx = jpake_new();
if (options.zero_knowledge_password_authentication)
authenticated = auth2_jpake_start(authctxt);
}
return authenticated;
}
Authmethod method_jpake = {
"jpake-01@openssh.com",
userauth_jpake,
&options.zero_knowledge_password_authentication
};
/* Clear context and callbacks */
void
auth2_jpake_stop(Authctxt *authctxt)
{
/* unregister callbacks */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
if (authctxt->jpake_ctx != NULL) {
jpake_free(authctxt->jpake_ctx);
authctxt->jpake_ctx = NULL;
}
}
/* Returns 1 if 'c' is a valid crypt(3) salt character, 0 otherwise */
static int
valid_crypt_salt(int c)
{
if (c >= 'A' && c <= 'Z')
return 1;
if (c >= 'a' && c <= 'z')
return 1;
if (c >= '.' && c <= '9')
return 1;
return 0;
}
/*
* Derive fake salt as H(username || first_private_host_key)
* This provides relatively stable fake salts for non-existent
* users and avoids the jpake method becoming an account validity
* oracle.
*/
static void
derive_rawsalt(const char *username, u_char *rawsalt, u_int len)
{
u_char *digest;
u_int digest_len;
Buffer b;
Key *k;
buffer_init(&b);
buffer_put_cstring(&b, username);
if ((k = get_hostkey_by_index(0)) == NULL ||
(k->flags & KEY_FLAG_EXT))
fatal("%s: no hostkeys", __func__);
switch (k->type) {
case KEY_RSA1:
case KEY_RSA:
if (k->rsa->p == NULL || k->rsa->q == NULL)
fatal("%s: RSA key missing p and/or q", __func__);
buffer_put_bignum2(&b, k->rsa->p);
buffer_put_bignum2(&b, k->rsa->q);
break;
case KEY_DSA:
if (k->dsa->priv_key == NULL)
fatal("%s: DSA key missing priv_key", __func__);
buffer_put_bignum2(&b, k->dsa->priv_key);
break;
case KEY_ECDSA:
if (EC_KEY_get0_private_key(k->ecdsa) == NULL)
fatal("%s: ECDSA key missing priv_key", __func__);
buffer_put_bignum2(&b, EC_KEY_get0_private_key(k->ecdsa));
break;
default:
fatal("%s: unknown key type %d", __func__, k->type);
}
if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
&digest, &digest_len) != 0)
fatal("%s: hash_buffer", __func__);
buffer_free(&b);
if (len > digest_len)
fatal("%s: not enough bytes for rawsalt (want %u have %u)",
__func__, len, digest_len);
memcpy(rawsalt, digest, len);
bzero(digest, digest_len);
free(digest);
}
/* ASCII an integer [0, 64) for inclusion in a password/salt */
static char
pw_encode64(u_int i64)
{
const u_char e64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
return e64[i64 % 64];
}
/* Generate ASCII salt bytes for user */
static char *
makesalt(u_int want, const char *user)
{
u_char rawsalt[32];
static char ret[33];
u_int i;
if (want > sizeof(ret) - 1)
fatal("%s: want %u", __func__, want);
derive_rawsalt(user, rawsalt, sizeof(rawsalt));
bzero(ret, sizeof(ret));
for (i = 0; i < want; i++)
ret[i] = pw_encode64(rawsalt[i]);
bzero(rawsalt, sizeof(rawsalt));
return ret;
}
/*
* Select the system's default password hashing scheme and generate
* a stable fake salt under it for use by a non-existent account.
* Prevents jpake method being used to infer the validity of accounts.
*/
static void
fake_salt_and_scheme(Authctxt *authctxt, char **salt, char **scheme)
{
char *rounds_s, *style;
long long rounds;
login_cap_t *lc;
if ((lc = login_getclass(authctxt->pw->pw_class)) == NULL &&
(lc = login_getclass(NULL)) == NULL)
fatal("%s: login_getclass failed", __func__);
style = login_getcapstr(lc, "localcipher", NULL, NULL);
if (style == NULL)
style = xstrdup("blowfish,6");
login_close(lc);
if ((rounds_s = strchr(style, ',')) != NULL)
*rounds_s++ = '\0';
rounds = strtonum(rounds_s, 1, 1<<31, NULL);
if (strcmp(style, "md5") == 0) {
xasprintf(salt, "$1$%s$", makesalt(8, authctxt->user));
*scheme = xstrdup("md5");
} else if (strcmp(style, "old") == 0) {
*salt = xstrdup(makesalt(2, authctxt->user));
*scheme = xstrdup("crypt");
} else if (strcmp(style, "newsalt") == 0) {
rounds = MAX(rounds, 7250);
rounds = MIN(rounds, (1<<24) - 1);
xasprintf(salt, "_%c%c%c%c%s",
pw_encode64(rounds), pw_encode64(rounds >> 6),
pw_encode64(rounds >> 12), pw_encode64(rounds >> 18),
makesalt(4, authctxt->user));
*scheme = xstrdup("crypt-extended");
} else {
/* Default to blowfish */
rounds = MAX(rounds, 3);
rounds = MIN(rounds, 31);
xasprintf(salt, "$2a$%02lld$%s", rounds,
makesalt(22, authctxt->user));
*scheme = xstrdup("bcrypt");
}
free(style);
debug3("%s: fake %s salt for user %s: %s",
__func__, *scheme, authctxt->user, *salt);
}
/*
* Fetch password hashing scheme, password salt and derive shared secret
* for user. If user does not exist, a fake but stable and user-unique
* salt will be returned.
*/
void
auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
char **hash_scheme, char **salt)
{
char *cp;
u_char *secret;
u_int secret_len, salt_len;
#ifdef JPAKE_DEBUG
debug3("%s: valid %d pw %.5s...", __func__,
authctxt->valid, authctxt->pw->pw_passwd);
#endif
*salt = NULL;
*hash_scheme = NULL;
if (authctxt->valid) {
if (strncmp(authctxt->pw->pw_passwd, "$2$", 3) == 0 &&
strlen(authctxt->pw->pw_passwd) > 28) {
/*
* old-variant bcrypt:
* "$2$", 2 digit rounds, "$", 22 bytes salt
*/
salt_len = 3 + 2 + 1 + 22 + 1;
*salt = xmalloc(salt_len);
strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
*hash_scheme = xstrdup("bcrypt");
} else if (strncmp(authctxt->pw->pw_passwd, "$2a$", 4) == 0 &&
strlen(authctxt->pw->pw_passwd) > 29) {
/*
* current-variant bcrypt:
* "$2a$", 2 digit rounds, "$", 22 bytes salt
*/
salt_len = 4 + 2 + 1 + 22 + 1;
*salt = xmalloc(salt_len);
strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
*hash_scheme = xstrdup("bcrypt");
} else if (strncmp(authctxt->pw->pw_passwd, "$1$", 3) == 0 &&
strlen(authctxt->pw->pw_passwd) > 5) {
/*
* md5crypt:
* "$1$", salt until "$"
*/
cp = strchr(authctxt->pw->pw_passwd + 3, '$');
if (cp != NULL) {
salt_len = (cp - authctxt->pw->pw_passwd) + 1;
*salt = xmalloc(salt_len);
strlcpy(*salt, authctxt->pw->pw_passwd,
salt_len);
*hash_scheme = xstrdup("md5crypt");
}
} else if (strncmp(authctxt->pw->pw_passwd, "_", 1) == 0 &&
strlen(authctxt->pw->pw_passwd) > 9) {
/*
* BSDI extended crypt:
* "_", 4 digits count, 4 chars salt
*/
salt_len = 1 + 4 + 4 + 1;
*salt = xmalloc(salt_len);
strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
*hash_scheme = xstrdup("crypt-extended");
} else if (strlen(authctxt->pw->pw_passwd) == 13 &&
valid_crypt_salt(authctxt->pw->pw_passwd[0]) &&
valid_crypt_salt(authctxt->pw->pw_passwd[1])) {
/*
* traditional crypt:
* 2 chars salt
*/
salt_len = 2 + 1;
*salt = xmalloc(salt_len);
strlcpy(*salt, authctxt->pw->pw_passwd, salt_len);
*hash_scheme = xstrdup("crypt");
}
if (*salt == NULL) {
debug("%s: unrecognised crypt scheme for user %s",
__func__, authctxt->pw->pw_name);
}
}
if (*salt == NULL)
fake_salt_and_scheme(authctxt, salt, hash_scheme);
if (hash_buffer(authctxt->pw->pw_passwd,
strlen(authctxt->pw->pw_passwd), EVP_sha256(),
&secret, &secret_len) != 0)
fatal("%s: hash_buffer", __func__);
if ((*s = BN_bin2bn(secret, secret_len, NULL)) == NULL)
fatal("%s: BN_bin2bn (secret)", __func__);
#ifdef JPAKE_DEBUG
debug3("%s: salt = %s (len %u)", __func__,
*salt, (u_int)strlen(*salt));
debug3("%s: scheme = %s", __func__, *hash_scheme);
JPAKE_DEBUG_BN((*s, "%s: s = ", __func__));
#endif
bzero(secret, secret_len);
free(secret);
}
/*
* Begin authentication attempt.
* Note, sets authctxt->postponed while in subprotocol
*/
static int
auth2_jpake_start(Authctxt *authctxt)
{
struct jpake_ctx *pctx = authctxt->jpake_ctx;
u_char *x3_proof, *x4_proof;
u_int x3_proof_len, x4_proof_len;
char *salt, *hash_scheme;
debug("%s: start", __func__);
PRIVSEP(jpake_step1(pctx->grp,
&pctx->server_id, &pctx->server_id_len,
&pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
&x3_proof, &x3_proof_len,
&x4_proof, &x4_proof_len));
PRIVSEP(auth2_jpake_get_pwdata(authctxt, &pctx->s,
&hash_scheme, &salt));
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "step 1 sending in %s", __func__));
packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP1);
packet_put_cstring(hash_scheme);
packet_put_cstring(salt);
packet_put_string(pctx->server_id, pctx->server_id_len);
packet_put_bignum2(pctx->g_x3);
packet_put_bignum2(pctx->g_x4);
packet_put_string(x3_proof, x3_proof_len);
packet_put_string(x4_proof, x4_proof_len);
packet_send();
packet_write_wait();
bzero(hash_scheme, strlen(hash_scheme));
bzero(salt, strlen(salt));
free(hash_scheme);
free(salt);
bzero(x3_proof, x3_proof_len);
bzero(x4_proof, x4_proof_len);
free(x3_proof);
free(x4_proof);
/* Expect step 1 packet from peer */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1,
input_userauth_jpake_client_step1);
authctxt->postponed = 1;
return 0;
}
/* ARGSUSED */
static void
input_userauth_jpake_client_step1(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
struct jpake_ctx *pctx = authctxt->jpake_ctx;
u_char *x1_proof, *x2_proof, *x4_s_proof;
u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
/* Disable this message */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP1, NULL);
/* Fetch step 1 values */
if ((pctx->g_x1 = BN_new()) == NULL ||
(pctx->g_x2 = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
pctx->client_id = packet_get_string(&pctx->client_id_len);
packet_get_bignum2(pctx->g_x1);
packet_get_bignum2(pctx->g_x2);
x1_proof = packet_get_string(&x1_proof_len);
x2_proof = packet_get_string(&x2_proof_len);
packet_check_eom();
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "step 1 received in %s", __func__));
PRIVSEP(jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
pctx->g_x1, pctx->g_x2, pctx->x4,
pctx->client_id, pctx->client_id_len,
pctx->server_id, pctx->server_id_len,
x1_proof, x1_proof_len,
x2_proof, x2_proof_len,
&pctx->b,
&x4_s_proof, &x4_s_proof_len));
bzero(x1_proof, x1_proof_len);
bzero(x2_proof, x2_proof_len);
free(x1_proof);
free(x2_proof);
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "step 2 sending in %s", __func__));
/* Send values for step 2 */
packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_STEP2);
packet_put_bignum2(pctx->b);
packet_put_string(x4_s_proof, x4_s_proof_len);
packet_send();
packet_write_wait();
bzero(x4_s_proof, x4_s_proof_len);
free(x4_s_proof);
/* Expect step 2 packet from peer */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2,
input_userauth_jpake_client_step2);
}
/* ARGSUSED */
static void
input_userauth_jpake_client_step2(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
struct jpake_ctx *pctx = authctxt->jpake_ctx;
u_char *x2_s_proof;
u_int x2_s_proof_len;
/* Disable this message */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_STEP2, NULL);
if ((pctx->a = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
/* Fetch step 2 values */
packet_get_bignum2(pctx->a);
x2_s_proof = packet_get_string(&x2_s_proof_len);
packet_check_eom();
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "step 2 received in %s", __func__));
/* Derive shared key and calculate confirmation hash */
PRIVSEP(jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
pctx->server_id, pctx->server_id_len,
pctx->client_id, pctx->client_id_len,
session_id2, session_id2_len,
x2_s_proof, x2_s_proof_len,
&pctx->k,
&pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len));
bzero(x2_s_proof, x2_s_proof_len);
free(x2_s_proof);
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "confirm sending in %s", __func__));
/* Send key confirmation proof */
packet_start(SSH2_MSG_USERAUTH_JPAKE_SERVER_CONFIRM);
packet_put_string(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
packet_send();
packet_write_wait();
/* Expect confirmation from peer */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM,
input_userauth_jpake_client_confirm);
}
/* ARGSUSED */
static void
input_userauth_jpake_client_confirm(int type, u_int32_t seq, void *ctxt)
{
Authctxt *authctxt = ctxt;
struct jpake_ctx *pctx = authctxt->jpake_ctx;
int authenticated = 0;
/* Disable this message */
dispatch_set(SSH2_MSG_USERAUTH_JPAKE_CLIENT_CONFIRM, NULL);
pctx->h_k_cid_sessid = packet_get_string(&pctx->h_k_cid_sessid_len);
packet_check_eom();
if (!use_privsep)
JPAKE_DEBUG_CTX((pctx, "confirm received in %s", __func__));
/* Verify expected confirmation hash */
if (PRIVSEP(jpake_check_confirm(pctx->k,
pctx->client_id, pctx->client_id_len,
session_id2, session_id2_len,
pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len)) == 1)
authenticated = authctxt->valid ? 1 : 0;
else
debug("%s: confirmation mismatch", __func__);
/* done */
authctxt->postponed = 0;
jpake_free(authctxt->jpake_ctx);
authctxt->jpake_ctx = NULL;
userauth_finish(authctxt, authenticated, method_jpake.name, NULL);
}
#endif /* JPAKE */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-passwd.c,v 1.10 2013/05/17 00:13:13 djm Exp $ */
/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -59,7 +59,7 @@ userauth_passwd(Authctxt *authctxt)
if (change) {
/* discard new password from packet */
newpass = packet_get_string(&newlen);
memset(newpass, 0, newlen);
explicit_bzero(newpass, newlen);
free(newpass);
}
packet_check_eom();
@ -68,7 +68,7 @@ userauth_passwd(Authctxt *authctxt)
logit("password change not supported");
else if (PRIVSEP(auth_password(authctxt, password)) == 1)
authenticated = 1;
memset(password, 0, len);
explicit_bzero(password, len);
free(password);
return authenticated;
}

11
auth2.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */
/* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -71,18 +71,12 @@ extern Authmethod method_hostbased;
#ifdef GSSAPI
extern Authmethod method_gssapi;
#endif
#ifdef JPAKE
extern Authmethod method_jpake;
#endif
Authmethod *authmethods[] = {
&method_none,
&method_pubkey,
#ifdef GSSAPI
&method_gssapi,
#endif
#ifdef JPAKE
&method_jpake,
#endif
&method_passwd,
&method_kbdint,
@ -270,9 +264,6 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
}
/* reset state */
auth2_challenge_stop(authctxt);
#ifdef JPAKE
auth2_jpake_stop(authctxt);
#endif
#ifdef GSSAPI
/* XXX move to auth2_gssapi_stop() */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfd.c,v 1.91 2013/12/29 04:29:25 djm Exp $ */
/* $OpenBSD: authfd.c,v 1.92 2014/01/31 16:39:19 tedu Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -102,7 +102,7 @@ ssh_get_authentication_socket(void)
if (!authsocket)
return -1;
bzero(&sunaddr, sizeof(sunaddr));
memset(&sunaddr, 0, sizeof(sunaddr));
sunaddr.sun_family = AF_UNIX;
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.c,v 1.101 2013/12/29 04:35:50 djm Exp $ */
/* $OpenBSD: authfile.c,v 1.103 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -131,7 +131,7 @@ key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase,
buffer_put_int(&kdf, rounds);
}
cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1);
memset(key, 0, keylen + ivlen);
explicit_bzero(key, keylen + ivlen);
free(key);
buffer_init(&encoded);
@ -143,7 +143,7 @@ key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase,
key_to_blob(prv, &cp, &len); /* public key */
buffer_put_string(&encoded, cp, len);
memset(cp, 0, len);
explicit_bzero(cp, len);
free(cp);
buffer_free(&kdf);
@ -409,7 +409,7 @@ key_parse_private2(Buffer *blob, int type, const char *passphrase,
free(salt);
free(comment);
if (key)
memset(key, 0, keylen + ivlen);
explicit_bzero(key, keylen + ivlen);
free(key);
buffer_free(&encoded);
buffer_free(&copy);
@ -496,10 +496,10 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0)
fatal("%s: cipher_crypt failed", __func__);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
explicit_bzero(&ciphercontext, sizeof(ciphercontext));
/* Destroy temporary data. */
memset(buf, 0, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
buffer_free(&buffer);
buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
@ -703,17 +703,17 @@ key_load_file(int fd, const char *filename, Buffer *blob)
__func__, filename == NULL ? "" : filename,
filename == NULL ? "" : " ", strerror(errno));
buffer_clear(blob);
bzero(buf, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
return 0;
}
buffer_append(blob, buf, len);
if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
buffer_clear(blob);
bzero(buf, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
goto toobig;
}
}
bzero(buf, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
st.st_size != buffer_len(blob)) {
debug("%s: key file %.200s%schanged size while reading",
@ -831,7 +831,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
buffer_ptr(&copy), buffer_len(&copy), 0, 0) != 0)
fatal("%s: cipher_crypt failed", __func__);
cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext));
explicit_bzero(&ciphercontext, sizeof(ciphercontext));
buffer_free(&copy);
check1 = buffer_get_char(&decrypted);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufaux.c,v 1.54 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -216,7 +216,7 @@ buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
if (cp == ret + length - 1)
error("buffer_get_cstring_ret: string contains \\0");
else {
bzero(ret, length);
explicit_bzero(ret, length);
free(ret);
return NULL;
}
@ -346,7 +346,7 @@ buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
}
ret = xmalloc(len);
memcpy(ret, p, len);
memset(p, '\0', len);
explicit_bzero(p, len);
free(bin);
return ret;
}
@ -383,7 +383,7 @@ buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
}
memcpy(p, s, l);
buffer_put_string(buffer, buf, l + pad);
memset(buf, '\0', l + pad);
explicit_bzero(buf, l + pad);
free(buf);
}

11
bufbn.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufbn.c,v 1.8 2013/11/08 11:15:19 dtucker Exp $*/
/* $OpenBSD: bufbn.c,v 1.11 2014/02/27 08:25:09 djm Exp $*/
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -80,7 +80,7 @@ buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
/* Store the binary data. */
buffer_append(buffer, buf, oi);
memset(buf, 0, bin_size);
explicit_bzero(buf, bin_size);
free(buf);
return (0);
@ -108,6 +108,11 @@ buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
return (-1);
}
bits = get_u16(buf);
if (bits > 65535-7) {
error("buffer_get_bignum_ret: cannot handle BN of size %d",
bits);
return (-1);
}
/* Compute the number of binary bytes that follow. */
bytes = (bits + 7) / 8;
if (bytes > 8 * 1024) {
@ -173,7 +178,7 @@ buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
}
hasnohigh = (buf[1] & 0x80) ? 0 : 1;
buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
memset(buf, 0, bytes);
explicit_bzero(buf, bytes);
free(buf);
return (0);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bufec.c,v 1.2 2013/05/17 00:13:13 djm Exp $ */
/* $OpenBSD: bufec.c,v 1.3 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2010 Damien Miller <djm@mindrot.org>
*
@ -77,7 +77,7 @@ buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
ret = 0;
out:
if (buf != NULL) {
bzero(buf, len);
explicit_bzero(buf, len);
free(buf);
}
BN_CTX_free(bnctx);
@ -130,7 +130,7 @@ buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
ret = 0;
out:
BN_CTX_free(bnctx);
bzero(buf, len);
explicit_bzero(buf, len);
free(buf);
return ret;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: buffer.c,v 1.34 2013/11/08 11:15:19 dtucker Exp $ */
/* $OpenBSD: buffer.c,v 1.35 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -49,7 +49,7 @@ void
buffer_free(Buffer *buffer)
{
if (buffer->alloc > 0) {
memset(buffer->buf, 0, buffer->alloc);
explicit_bzero(buffer->buf, buffer->alloc);
buffer->alloc = 0;
free(buffer->buf);
}

View File

@ -192,7 +192,7 @@ ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr));
port = a6->sin6_port;
bzero(a4, sizeof(*a4));
memset(a4, 0, sizeof(*a4));
a4->sin_family = AF_INET;
*len = sizeof(*a4);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.c,v 1.328 2013/12/19 01:04:36 djm Exp $ */
/* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -423,7 +423,7 @@ channel_free(Channel *c)
if (cc->abandon_cb != NULL)
cc->abandon_cb(c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
bzero(cc, sizeof(*cc));
explicit_bzero(cc, sizeof(*cc));
free(cc);
}
if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
@ -1072,6 +1072,9 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset)
buffer_get(&c->input, (char *)&s4_req.dest_addr, 4);
have = buffer_len(&c->input);
p = buffer_ptr(&c->input);
if (memchr(p, '\0', have) == NULL)
fatal("channel %d: decode socks4: user not nul terminated",
c->self);
len = strlen(p);
debug2("channel %d: decode socks4: user %s/%d", c->self, p, len);
len++; /* trailing '\0' */
@ -1386,7 +1389,7 @@ port_open_helper(Channel *c, char *rtype)
int direct;
char buf[1024];
char *local_ipaddr = get_local_ipaddr(c->sock);
int local_port = get_sock_port(c->sock, 1);
int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
char *remote_ipaddr = get_peer_ipaddr(c->sock);
int remote_port = get_peer_port(c->sock);
@ -2671,7 +2674,7 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
return;
cc->cb(type, c, cc->ctx);
TAILQ_REMOVE(&c->status_confirms, cc, entry);
bzero(cc, sizeof(*cc));
explicit_bzero(cc, sizeof(*cc));
free(cc);
}
@ -3304,9 +3307,7 @@ channel_connect_ctx_free(struct channel_connect *cctx)
free(cctx->host);
if (cctx->aitop)
freeaddrinfo(cctx->aitop);
bzero(cctx, sizeof(*cctx));
cctx->host = NULL;
cctx->ai = cctx->aitop = NULL;
memset(cctx, 0, sizeof(*cctx));
}
/* Return CONNECTING channel to remote host, port */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher-3des1.c,v 1.9 2013/11/08 00:39:15 djm Exp $ */
/* $OpenBSD: cipher-3des1.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2003 Markus Friedl. All rights reserved.
*
@ -93,7 +93,7 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
memset(c, 0, sizeof(*c));
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
return (0);
@ -134,7 +134,7 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
EVP_CIPHER_CTX_cleanup(&c->k1);
EVP_CIPHER_CTX_cleanup(&c->k2);
EVP_CIPHER_CTX_cleanup(&c->k3);
memset(c, 0, sizeof(*c));
explicit_bzero(c, sizeof(*c));
free(c);
EVP_CIPHER_CTX_set_app_data(ctx, NULL);
}

View File

@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: cipher-chachapoly.c,v 1.3 2013/12/15 21:42:35 djm Exp $ */
/* $OpenBSD: cipher-chachapoly.c,v 1.4 2014/01/31 16:39:19 tedu Exp $ */
#include "includes.h"
@ -58,7 +58,7 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
* Run ChaCha20 once to generate the Poly1305 key. The IV is the
* packet sequence number.
*/
bzero(poly_key, sizeof(poly_key));
memset(poly_key, 0, sizeof(poly_key));
put_u64(seqbuf, seqnr);
chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
chacha_encrypt_bytes(&ctx->main_ctx,
@ -90,9 +90,9 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
r = 0;
out:
bzero(expected_tag, sizeof(expected_tag));
bzero(seqbuf, sizeof(seqbuf));
bzero(poly_key, sizeof(poly_key));
explicit_bzero(expected_tag, sizeof(expected_tag));
explicit_bzero(seqbuf, sizeof(seqbuf));
explicit_bzero(poly_key, sizeof(poly_key));
return r;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.c,v 1.94 2014/01/25 10:12:50 dtucker Exp $ */
/* $OpenBSD: cipher.c,v 1.97 2014/02/07 06:55:54 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -39,8 +39,6 @@
#include <sys/types.h>
#include <openssl/md5.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
@ -49,6 +47,8 @@
#include "log.h"
#include "misc.h"
#include "cipher.h"
#include "buffer.h"
#include "digest.h"
/* compatibility with old or broken OpenSSL versions */
#include "openbsd-compat/openssl-compat.h"
@ -228,8 +228,6 @@ ciphers_valid(const char *names)
debug("bad cipher %s [%s]", p, names);
free(cipher_list);
return 0;
} else {
debug3("cipher ok: %s [%s]", p, names);
}
}
debug3("ciphers ok: [%s]", names);
@ -337,7 +335,7 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
if (EVP_Cipher(&cc->evp, discard, junk,
cipher->discard_len) == 0)
fatal("evp_crypt: EVP_Cipher failed during discard");
memset(discard, 0, cipher->discard_len);
explicit_bzero(discard, cipher->discard_len);
free(junk);
free(discard);
}
@ -422,7 +420,7 @@ void
cipher_cleanup(CipherContext *cc)
{
if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
memset(&cc->cp_ctx, 0, sizeof(cc->cp_ctx));
explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed");
}
@ -436,17 +434,15 @@ void
cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
const char *passphrase, int do_encrypt)
{
MD5_CTX md;
u_char digest[16];
MD5_Init(&md);
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
MD5_Final(digest, &md);
if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase),
digest, sizeof(digest)) < 0)
fatal("%s: md5 failed", __func__);
cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
explicit_bzero(digest, sizeof(digest));
}
/*

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.256 2013/11/20 20:54:10 deraadt Exp $ */
/* $OpenBSD: clientloop.c,v 1.258 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -549,7 +549,7 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt)
gc->cb(type, seq, gc->ctx);
if (--gc->ref_count <= 0) {
TAILQ_REMOVE(&global_confirms, gc, entry);
bzero(gc, sizeof(*gc));
explicit_bzero(gc, sizeof(*gc));
free(gc);
}
@ -876,7 +876,7 @@ process_cmdline(void)
int cancel_port, ok;
Forward fwd;
bzero(&fwd, sizeof(fwd));
memset(&fwd, 0, sizeof(fwd));
fwd.listen_host = fwd.connect_host = NULL;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
@ -1761,7 +1761,7 @@ client_input_stdout_data(int type, u_int32_t seq, void *ctxt)
char *data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stdout_buffer, data, data_len);
memset(data, 0, data_len);
explicit_bzero(data, data_len);
free(data);
}
static void
@ -1771,7 +1771,7 @@ client_input_stderr_data(int type, u_int32_t seq, void *ctxt)
char *data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stderr_buffer, data, data_len);
memset(data, 0, data_len);
explicit_bzero(data, data_len);
free(data);
}
static void

View File

@ -414,6 +414,9 @@
/* Define to 1 if you have the `EVP_MD_CTX_cleanup' function. */
#undef HAVE_EVP_MD_CTX_CLEANUP
/* Define to 1 if you have the `EVP_MD_CTX_copy_ex' function. */
#undef HAVE_EVP_MD_CTX_COPY_EX
/* Define to 1 if you have the `EVP_MD_CTX_init' function. */
#undef HAVE_EVP_MD_CTX_INIT
@ -423,6 +426,9 @@
/* Define if you have ut_exit in utmp.h */
#undef HAVE_EXIT_IN_UTMP
/* Define to 1 if you have the `explicit_bzero' function. */
#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the `fchmod' function. */
#undef HAVE_FCHMOD

6
configure vendored
View File

@ -1,5 +1,5 @@
#! /bin/sh
# From configure.ac Revision: 1.568 .
# From configure.ac Revision: 1.571 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.68 for OpenSSH Portable.
#
@ -7607,7 +7607,7 @@ $as_echo "#define BROKEN_STRNVIS 1" >>confdefs.h
# and will crash if they cannot be opened.
$as_echo "#define SANDBOX_SKIP_RLIMIT_NOFILE 1" >>confdefs.h
],
;;
*-*-bsdi*)
$as_echo "#define SETEUID_BREAKS_SETUID 1" >>confdefs.h
@ -10366,6 +10366,7 @@ for ac_func in \
closefrom \
dirfd \
endgrent \
explicit_bzero \
fchmod \
fchown \
freeaddrinfo \
@ -12113,6 +12114,7 @@ for ac_func in \
EVP_DigestFinal_ex \
EVP_MD_CTX_init \
EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \

View File

@ -1,4 +1,4 @@
# $Id: configure.ac,v 1.568 2014/01/30 00:26:46 djm Exp $
# $Id: configure.ac,v 1.571 2014/02/21 17:09:34 tim Exp $
#
# Copyright (c) 1999-2004 Damien Miller
#
@ -15,7 +15,7 @@
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
AC_REVISION($Revision: 1.568 $)
AC_REVISION($Revision: 1.571 $)
AC_CONFIG_SRCDIR([ssh.c])
AC_LANG([C])
@ -785,7 +785,7 @@ mips-sony-bsd|mips-sony-newsos4)
# Preauth crypto occasionally uses file descriptors for crypto offload
# and will crash if they cannot be opened.
AC_DEFINE([SANDBOX_SKIP_RLIMIT_NOFILE], [1],
[define if setrlimit RLIMIT_NOFILE breaks things])],
[define if setrlimit RLIMIT_NOFILE breaks things])
;;
*-*-bsdi*)
AC_DEFINE([SETEUID_BREAKS_SETUID])
@ -1649,6 +1649,7 @@ AC_CHECK_FUNCS([ \
closefrom \
dirfd \
endgrent \
explicit_bzero \
fchmod \
fchown \
freeaddrinfo \
@ -2429,6 +2430,7 @@ AC_CHECK_FUNCS([ \
EVP_DigestFinal_ex \
EVP_MD_CTX_init \
EVP_MD_CTX_cleanup \
EVP_MD_CTX_copy_ex \
HMAC_CTX_init \
RSA_generate_key_ex \
RSA_get_default_method \

View File

@ -16,7 +16,7 @@
#old cvs stuff. please update before use. may be deprecated.
%define use_stable 1
%define version 6.5p1
%define version 6.6p1
%if %{use_stable}
%define cvs %{nil}
%define release 1
@ -363,4 +363,4 @@ fi
* Mon Jan 01 1998 ...
Template Version: 1.31
$Id: openssh.spec,v 1.82 2014/01/16 07:51:10 djm Exp $
$Id: openssh.spec,v 1.83 2014/02/27 23:03:55 djm Exp $

View File

@ -1,4 +1,4 @@
%define ver 6.5p1
%define ver 6.6p1
%define rel 1
# OpenSSH privilege separation requires a user & group ID

View File

@ -13,7 +13,7 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh
Version: 6.5p1
Version: 6.6p1
URL: http://www.openssh.com/
Release: 1
Source0: openssh-%{version}.tar.gz

238
digest-libc.c Normal file
View File

@ -0,0 +1,238 @@
/* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <md5.h>
#include <rmd160.h>
#include <sha1.h>
#include <sha2.h>
#include "buffer.h"
#include "digest.h"
typedef void md_init_fn(void *mdctx);
typedef void md_update_fn(void *mdctx, const u_int8_t *m, size_t mlen);
typedef void md_final_fn(u_int8_t[], void *mdctx);
struct ssh_digest_ctx {
int alg;
void *mdctx;
};
struct ssh_digest {
int id;
const char *name;
size_t block_len;
size_t digest_len;
size_t ctx_len;
md_init_fn *md_init;
md_update_fn *md_update;
md_final_fn *md_final;
};
/* NB. Indexed directly by algorithm number */
const struct ssh_digest digests[SSH_DIGEST_MAX] = {
{
SSH_DIGEST_MD5,
"MD5",
MD5_BLOCK_LENGTH,
MD5_DIGEST_LENGTH,
sizeof(MD5_CTX),
(md_init_fn *) MD5Init,
(md_update_fn *) MD5Update,
(md_final_fn *) MD5Final
},
{
SSH_DIGEST_RIPEMD160,
"RIPEMD160",
RMD160_BLOCK_LENGTH,
RMD160_DIGEST_LENGTH,
sizeof(RMD160_CTX),
(md_init_fn *) RMD160Init,
(md_update_fn *) RMD160Update,
(md_final_fn *) RMD160Final
},
{
SSH_DIGEST_SHA1,
"SHA1",
SHA1_BLOCK_LENGTH,
SHA1_DIGEST_LENGTH,
sizeof(SHA1_CTX),
(md_init_fn *) SHA1Init,
(md_update_fn *) SHA1Update,
(md_final_fn *) SHA1Final
},
{
SSH_DIGEST_SHA256,
"SHA256",
SHA256_BLOCK_LENGTH,
SHA256_DIGEST_LENGTH,
sizeof(SHA2_CTX),
(md_init_fn *) SHA256Init,
(md_update_fn *) SHA256Update,
(md_final_fn *) SHA256Final
},
{
SSH_DIGEST_SHA384,
"SHA384",
SHA384_BLOCK_LENGTH,
SHA384_DIGEST_LENGTH,
sizeof(SHA2_CTX),
(md_init_fn *) SHA384Init,
(md_update_fn *) SHA384Update,
(md_final_fn *) SHA384Final
},
{
SSH_DIGEST_SHA512,
"SHA512",
SHA512_BLOCK_LENGTH,
SHA512_DIGEST_LENGTH,
sizeof(SHA2_CTX),
(md_init_fn *) SHA512Init,
(md_update_fn *) SHA512Update,
(md_final_fn *) SHA512Final
}
};
static const struct ssh_digest *
ssh_digest_by_alg(int alg)
{
if (alg < 0 || alg >= SSH_DIGEST_MAX)
return NULL;
if (digests[alg].id != alg) /* sanity */
return NULL;
return &(digests[alg]);
}
size_t
ssh_digest_bytes(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
return digest == NULL ? 0 : digest->digest_len;
}
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
return digest == NULL ? 0 : digest->block_len;
}
struct ssh_digest_ctx *
ssh_digest_start(int alg)
{
const struct ssh_digest *digest = ssh_digest_by_alg(alg);
struct ssh_digest_ctx *ret;
if (digest == NULL || (ret = calloc(1, sizeof(ret))) == NULL)
return NULL;
if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) {
free(ret);
return NULL;
}
ret->alg = alg;
digest->md_init(ret->mdctx);
return ret;
}
int
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
{
const struct ssh_digest *digest = ssh_digest_by_alg(from->alg);
if (digest == NULL || from->alg != to->alg)
return -1;
memcpy(to->mdctx, from->mdctx, digest->ctx_len);
return 0;
}
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
if (digest == NULL)
return -1;
digest->md_update(ctx->mdctx, m, mlen);
return 0;
}
int
ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b)
{
return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b));
}
int
ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
{
const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
if (digest == NULL)
return -1;
if (dlen > UINT_MAX)
return -1;
if (dlen < digest->digest_len) /* No truncation allowed */
return -1;
digest->md_final(d, ctx->mdctx);
return 0;
}
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
const struct ssh_digest *digest;
if (ctx != NULL) {
digest = ssh_digest_by_alg(ctx->alg);
if (digest) {
explicit_bzero(ctx->mdctx, digest->ctx_len);
free(ctx->mdctx);
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
}
int
ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
{
struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
if (ctx == NULL)
return -1;
if (ssh_digest_update(ctx, m, mlen) != 0 ||
ssh_digest_final(ctx, d, dlen) != 0)
return -1;
ssh_digest_free(ctx);
return 0;
}
int
ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
{
return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: digest.c,v 1.3 2014/01/20 00:08:48 djm Exp $ */
/* $OpenBSD: digest-openssl.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@ -72,6 +72,12 @@ ssh_digest_bytes(int alg)
return digest == NULL ? 0 : digest->digest_len;
}
size_t
ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
{
return EVP_MD_CTX_block_size(&ctx->mdctx);
}
struct ssh_digest_ctx *
ssh_digest_start(int alg)
{
@ -89,6 +95,15 @@ ssh_digest_start(int alg)
return ret;
}
int
ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
{
/* we have bcopy-style order while openssl has memcpy-style */
if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
return -1;
return 0;
}
int
ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
{
@ -123,9 +138,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
void
ssh_digest_free(struct ssh_digest_ctx *ctx)
{
EVP_MD_CTX_cleanup(&ctx->mdctx);
memset(ctx, 0, sizeof(*ctx));
free(ctx);
if (ctx != NULL) {
EVP_MD_CTX_cleanup(&ctx->mdctx);
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: digest.h,v 1.1 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2013 Damien Miller <djm@mindrot.org>
*
@ -30,9 +30,18 @@
#define SSH_DIGEST_SHA512 5
#define SSH_DIGEST_MAX 6
struct ssh_digest_ctx;
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_digest_bytes(int alg);
/* Returns the block size of the digest, e.g. for implementing HMAC */
size_t ssh_digest_blocksize(struct ssh_digest_ctx *ctx);
/* Copies internal state of digest of 'from' to 'to' */
int ssh_digest_copy_state(struct ssh_digest_ctx *from,
struct ssh_digest_ctx *to);
/* One-shot API */
int ssh_digest_memory(int alg, const void *m, size_t mlen,
u_char *d, size_t dlen)
@ -42,7 +51,6 @@ int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 3, 4)));
/* Update API */
struct ssh_digest_ctx;
struct ssh_digest_ctx *ssh_digest_start(int alg);
int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
__attribute__((__bounded__(__buffer__, 2, 3)));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: gss-serv.c,v 1.24 2013/07/20 01:55:13 djm Exp $ */
/* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@ -66,6 +66,25 @@ ssh_gssapi_mech* supported_mechs[]= {
&gssapi_null_mech,
};
/*
* ssh_gssapi_supported_oids() can cause sandbox violations, so prepare the
* list of supported mechanisms before privsep is set up.
*/
static gss_OID_set supported_oids;
void
ssh_gssapi_prepare_supported_oids(void)
{
ssh_gssapi_supported_oids(&supported_oids);
}
OM_uint32
ssh_gssapi_test_oid_supported(OM_uint32 *ms, gss_OID member, int *present)
{
if (supported_oids == NULL)
ssh_gssapi_prepare_supported_oids();
return gss_test_oid_set_member(ms, member, supported_oids, present);
}
/*
* Acquire credentials for a server running on the current host.
@ -346,7 +365,8 @@ ssh_gssapi_userok(char *user)
gss_release_buffer(&lmin, &gssapi_client.displayname);
gss_release_buffer(&lmin, &gssapi_client.exportedname);
gss_release_cred(&lmin, &gssapi_client.creds);
memset(&gssapi_client, 0, sizeof(ssh_gssapi_client));
explicit_bzero(&gssapi_client,
sizeof(ssh_gssapi_client));
return 0;
}
else

197
hmac.c Normal file
View File

@ -0,0 +1,197 @@
/* $OpenBSD: hmac.c,v 1.10 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include "buffer.h"
#include "digest.h"
#include "hmac.h"
struct ssh_hmac_ctx {
int alg;
struct ssh_digest_ctx *ictx;
struct ssh_digest_ctx *octx;
struct ssh_digest_ctx *digest;
u_char *buf;
size_t buf_len;
};
size_t
ssh_hmac_bytes(int alg)
{
return ssh_digest_bytes(alg);
}
struct ssh_hmac_ctx *
ssh_hmac_start(int alg)
{
struct ssh_hmac_ctx *ret;
if ((ret = calloc(1, sizeof(*ret))) == NULL)
return NULL;
ret->alg = alg;
if ((ret->ictx = ssh_digest_start(alg)) == NULL ||
(ret->octx = ssh_digest_start(alg)) == NULL ||
(ret->digest = ssh_digest_start(alg)) == NULL)
goto fail;
ret->buf_len = ssh_digest_blocksize(ret->ictx);
if ((ret->buf = calloc(1, ret->buf_len)) == NULL)
goto fail;
return ret;
fail:
ssh_hmac_free(ret);
return NULL;
}
int
ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
{
size_t i;
/* reset ictx and octx if no is key given */
if (key != NULL) {
/* truncate long keys */
if (klen <= ctx->buf_len)
memcpy(ctx->buf, key, klen);
else if (ssh_digest_memory(ctx->alg, key, klen, ctx->buf,
ctx->buf_len) < 0)
return -1;
for (i = 0; i < ctx->buf_len; i++)
ctx->buf[i] ^= 0x36;
if (ssh_digest_update(ctx->ictx, ctx->buf, ctx->buf_len) < 0)
return -1;
for (i = 0; i < ctx->buf_len; i++)
ctx->buf[i] ^= 0x36 ^ 0x5c;
if (ssh_digest_update(ctx->octx, ctx->buf, ctx->buf_len) < 0)
return -1;
explicit_bzero(ctx->buf, ctx->buf_len);
}
/* start with ictx */
if (ssh_digest_copy_state(ctx->ictx, ctx->digest) < 0)
return -1;
return 0;
}
int
ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
{
return ssh_digest_update(ctx->digest, m, mlen);
}
int
ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b)
{
return ssh_digest_update_buffer(ctx->digest, b);
}
int
ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
{
size_t len;
len = ssh_digest_bytes(ctx->alg);
if (dlen < len ||
ssh_digest_final(ctx->digest, ctx->buf, len))
return -1;
/* switch to octx */
if (ssh_digest_copy_state(ctx->octx, ctx->digest) < 0 ||
ssh_digest_update(ctx->digest, ctx->buf, len) < 0 ||
ssh_digest_final(ctx->digest, d, dlen) < 0)
return -1;
return 0;
}
void
ssh_hmac_free(struct ssh_hmac_ctx *ctx)
{
if (ctx != NULL) {
ssh_digest_free(ctx->ictx);
ssh_digest_free(ctx->octx);
ssh_digest_free(ctx->digest);
if (ctx->buf) {
explicit_bzero(ctx->buf, ctx->buf_len);
free(ctx->buf);
}
explicit_bzero(ctx, sizeof(*ctx));
free(ctx);
}
}
#ifdef TEST
/* cc -DTEST hmac.c digest.c buffer.c cleanup.c fatal.c log.c xmalloc.c -lcrypto */
static void
hmac_test(void *key, size_t klen, void *m, size_t mlen, u_char *e, size_t elen)
{
struct ssh_hmac_ctx *ctx;
size_t i;
u_char digest[16];
if ((ctx = ssh_hmac_start(SSH_DIGEST_MD5)) == NULL)
printf("ssh_hmac_start failed");
if (ssh_hmac_init(ctx, key, klen) < 0 ||
ssh_hmac_update(ctx, m, mlen) < 0 ||
ssh_hmac_final(ctx, digest, sizeof(digest)) < 0)
printf("ssh_hmac_xxx failed");
ssh_hmac_free(ctx);
if (memcmp(e, digest, elen)) {
for (i = 0; i < elen; i++)
printf("[%zd] %2.2x %2.2x\n", i, e[i], digest[i]);
printf("mismatch\n");
} else
printf("ok\n");
}
int
main(int argc, char **argv)
{
/* try test vectors from RFC 2104 */
u_char key1[16] = {
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb,
0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb };
u_char *data1 = "Hi There";
u_char dig1[16] = {
0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c,
0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d };
u_char *key2 = "Jefe";
u_char *data2 = "what do ya want for nothing?";
u_char dig2[16] = {
0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03,
0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38 };
u_char key3[16];
u_char data3[50];
u_char dig3[16] = {
0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88,
0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6 };
memset(key3, 0xaa, sizeof(key3));
memset(data3, 0xdd, sizeof(data3));
hmac_test(key1, sizeof(key1), data1, strlen(data1), dig1, sizeof(dig1));
hmac_test(key2, strlen(key2), data2, strlen(data2), dig2, sizeof(dig2));
hmac_test(key3, sizeof(key3), data3, sizeof(data3), dig3, sizeof(dig3));
return 0;
}
#endif

37
hmac.h Normal file
View File

@ -0,0 +1,37 @@
/* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2014 Markus Friedl. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _HMAC_H
#define _HMAC_H
/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
size_t ssh_hmac_bytes(int alg);
struct ssh_hmac_ctx;
struct ssh_hmac_ctx *ssh_hmac_start(int alg);
/* Sets the state of the HMAC or resets the state if key == NULL */
int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b);
int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
__attribute__((__bounded__(__buffer__, 2, 3)));
void ssh_hmac_free(struct ssh_hmac_ctx *ctx);
#endif /* _HMAC_H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: hostfile.c,v 1.53 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: hostfile.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -42,9 +42,6 @@
#include <netinet/in.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <resolv.h>
#include <stdarg.h>
#include <stdio.h>
@ -58,6 +55,7 @@
#include "log.h"
#include "misc.h"
#include "digest.h"
#include "hmac.h"
struct hostkeys {
struct hostkey_entry *entries;
@ -102,9 +100,9 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
debug2("extract_salt: salt decode error");
return (-1);
}
if (ret != SHA_DIGEST_LENGTH) {
debug2("extract_salt: expected salt len %d, got %d",
SHA_DIGEST_LENGTH, ret);
if (ret != (int)ssh_hmac_bytes(SSH_DIGEST_SHA1)) {
debug2("extract_salt: expected salt len %zd, got %d",
ssh_hmac_bytes(SSH_DIGEST_SHA1), ret);
return (-1);
}
@ -114,14 +112,13 @@ extract_salt(const char *s, u_int l, u_char *salt, size_t salt_len)
char *
host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
{
const EVP_MD *md = EVP_sha1();
HMAC_CTX mac_ctx;
struct ssh_hmac_ctx *ctx;
u_char salt[256], result[256];
char uu_salt[512], uu_result[512];
static char encoded[1024];
u_int i, len;
len = EVP_MD_size(md);
len = ssh_digest_bytes(SSH_DIGEST_SHA1);
if (name_from_hostfile == NULL) {
/* Create new salt */
@ -134,14 +131,16 @@ host_hash(const char *host, const char *name_from_hostfile, u_int src_len)
return (NULL);
}
HMAC_Init(&mac_ctx, salt, len, md);
HMAC_Update(&mac_ctx, (u_char *)host, strlen(host));
HMAC_Final(&mac_ctx, result, NULL);
HMAC_cleanup(&mac_ctx);
if ((ctx = ssh_hmac_start(SSH_DIGEST_SHA1)) == NULL ||
ssh_hmac_init(ctx, salt, len) < 0 ||
ssh_hmac_update(ctx, host, strlen(host)) < 0 ||
ssh_hmac_final(ctx, result, sizeof(result)))
fatal("%s: ssh_hmac failed", __func__);
ssh_hmac_free(ctx);
if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 ||
__b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1)
fatal("host_hash: __b64_ntop failed");
fatal("%s: __b64_ntop failed", __func__);
snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt,
HASH_DELIM, uu_result);
@ -334,10 +333,10 @@ free_hostkeys(struct hostkeys *hostkeys)
free(hostkeys->entries[i].host);
free(hostkeys->entries[i].file);
key_free(hostkeys->entries[i].key);
bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
}
free(hostkeys->entries);
bzero(hostkeys, sizeof(*hostkeys));
explicit_bzero(hostkeys, sizeof(*hostkeys));
free(hostkeys);
}

456
jpake.c
View File

@ -1,456 +0,0 @@
/* $OpenBSD: jpake.c,v 1.8 2013/05/17 00:13:13 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Shared components of zero-knowledge password auth using J-PAKE protocol
* as described in:
*
* F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
* 16th Workshop on Security Protocols, Cambridge, April 2008
*
* http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
*/
#include "includes.h"
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "ssh2.h"
#include "key.h"
#include "hostfile.h"
#include "auth.h"
#include "buffer.h"
#include "packet.h"
#include "dispatch.h"
#include "log.h"
#include "misc.h"
#include "jpake.h"
#include "schnorr.h"
#ifdef JPAKE
/* RFC3526 group 5, 1536 bits */
#define JPAKE_GROUP_G "2"
#define JPAKE_GROUP_P \
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74" \
"020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437" \
"4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF05" \
"98DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB" \
"9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
struct modp_group *
jpake_default_group(void)
{
return modp_group_from_g_and_safe_p(JPAKE_GROUP_G, JPAKE_GROUP_P);
}
struct jpake_ctx *
jpake_new(void)
{
struct jpake_ctx *ret;
ret = xcalloc(1, sizeof(*ret));
ret->grp = jpake_default_group();
ret->s = ret->k = NULL;
ret->x1 = ret->x2 = ret->x3 = ret->x4 = NULL;
ret->g_x1 = ret->g_x2 = ret->g_x3 = ret->g_x4 = NULL;
ret->a = ret->b = NULL;
ret->client_id = ret->server_id = NULL;
ret->h_k_cid_sessid = ret->h_k_sid_sessid = NULL;
debug3("%s: alloc %p", __func__, ret);
return ret;
}
void
jpake_free(struct jpake_ctx *pctx)
{
debug3("%s: free %p", __func__, pctx);
#define JPAKE_BN_CLEAR_FREE(v) \
do { \
if ((v) != NULL) { \
BN_clear_free(v); \
(v) = NULL; \
} \
} while (0)
#define JPAKE_BUF_CLEAR_FREE(v, l) \
do { \
if ((v) != NULL) { \
bzero((v), (l)); \
free(v); \
(v) = NULL; \
(l) = 0; \
} \
} while (0)
JPAKE_BN_CLEAR_FREE(pctx->s);
JPAKE_BN_CLEAR_FREE(pctx->k);
JPAKE_BN_CLEAR_FREE(pctx->x1);
JPAKE_BN_CLEAR_FREE(pctx->x2);
JPAKE_BN_CLEAR_FREE(pctx->x3);
JPAKE_BN_CLEAR_FREE(pctx->x4);
JPAKE_BN_CLEAR_FREE(pctx->g_x1);
JPAKE_BN_CLEAR_FREE(pctx->g_x2);
JPAKE_BN_CLEAR_FREE(pctx->g_x3);
JPAKE_BN_CLEAR_FREE(pctx->g_x4);
JPAKE_BN_CLEAR_FREE(pctx->a);
JPAKE_BN_CLEAR_FREE(pctx->b);
JPAKE_BUF_CLEAR_FREE(pctx->client_id, pctx->client_id_len);
JPAKE_BUF_CLEAR_FREE(pctx->server_id, pctx->server_id_len);
JPAKE_BUF_CLEAR_FREE(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
JPAKE_BUF_CLEAR_FREE(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
#undef JPAKE_BN_CLEAR_FREE
#undef JPAKE_BUF_CLEAR_FREE
bzero(pctx, sizeof(*pctx));
free(pctx);
}
/* dump entire jpake_ctx. NB. includes private values! */
void
jpake_dump(struct jpake_ctx *pctx, const char *fmt, ...)
{
char *out;
va_list args;
out = NULL;
va_start(args, fmt);
vasprintf(&out, fmt, args);
va_end(args);
if (out == NULL)
fatal("%s: vasprintf failed", __func__);
debug3("%s: %s (ctx at %p)", __func__, out, pctx);
if (pctx == NULL) {
free(out);
return;
}
#define JPAKE_DUMP_BN(a) do { \
if ((a) != NULL) \
JPAKE_DEBUG_BN(((a), "%s = ", #a)); \
} while (0)
#define JPAKE_DUMP_BUF(a, b) do { \
if ((a) != NULL) \
JPAKE_DEBUG_BUF((a, b, "%s", #a)); \
} while (0)
JPAKE_DUMP_BN(pctx->s);
JPAKE_DUMP_BN(pctx->k);
JPAKE_DUMP_BN(pctx->x1);
JPAKE_DUMP_BN(pctx->x2);
JPAKE_DUMP_BN(pctx->x3);
JPAKE_DUMP_BN(pctx->x4);
JPAKE_DUMP_BN(pctx->g_x1);
JPAKE_DUMP_BN(pctx->g_x2);
JPAKE_DUMP_BN(pctx->g_x3);
JPAKE_DUMP_BN(pctx->g_x4);
JPAKE_DUMP_BN(pctx->a);
JPAKE_DUMP_BN(pctx->b);
JPAKE_DUMP_BUF(pctx->client_id, pctx->client_id_len);
JPAKE_DUMP_BUF(pctx->server_id, pctx->server_id_len);
JPAKE_DUMP_BUF(pctx->h_k_cid_sessid, pctx->h_k_cid_sessid_len);
JPAKE_DUMP_BUF(pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
debug3("%s: %s done", __func__, out);
free(out);
}
/* Shared parts of step 1 exchange calculation */
void
jpake_step1(struct modp_group *grp,
u_char **id, u_int *id_len,
BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
u_char **priv1_proof, u_int *priv1_proof_len,
u_char **priv2_proof, u_int *priv2_proof_len)
{
BN_CTX *bn_ctx;
if ((bn_ctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new", __func__);
/* Random nonce to prevent replay */
*id = xmalloc(KZP_ID_LEN);
*id_len = KZP_ID_LEN;
arc4random_buf(*id, *id_len);
/*
* x1/x3 is a random element of Zq
* x2/x4 is a random element of Z*q
* We also exclude [1] from x1/x3 candidates and [0, 1] from
* x2/x4 candiates to avoid possible degeneracy (i.e. g^0, g^1).
*/
if ((*priv1 = bn_rand_range_gt_one(grp->q)) == NULL ||
(*priv2 = bn_rand_range_gt_one(grp->q)) == NULL)
fatal("%s: bn_rand_range_gt_one", __func__);
/*
* client: g_x1 = g^x1 mod p / server: g_x3 = g^x3 mod p
* client: g_x2 = g^x2 mod p / server: g_x4 = g^x4 mod p
*/
if ((*g_priv1 = BN_new()) == NULL ||
(*g_priv2 = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
if (BN_mod_exp(*g_priv1, grp->g, *priv1, grp->p, bn_ctx) == -1)
fatal("%s: BN_mod_exp", __func__);
if (BN_mod_exp(*g_priv2, grp->g, *priv2, grp->p, bn_ctx) == -1)
fatal("%s: BN_mod_exp", __func__);
/* Generate proofs for holding x1/x3 and x2/x4 */
if (schnorr_sign_buf(grp->p, grp->q, grp->g,
*priv1, *g_priv1, *id, *id_len,
priv1_proof, priv1_proof_len) != 0)
fatal("%s: schnorr_sign", __func__);
if (schnorr_sign_buf(grp->p, grp->q, grp->g,
*priv2, *g_priv2, *id, *id_len,
priv2_proof, priv2_proof_len) != 0)
fatal("%s: schnorr_sign", __func__);
BN_CTX_free(bn_ctx);
}
/* Shared parts of step 2 exchange calculation */
void
jpake_step2(struct modp_group *grp, BIGNUM *s,
BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
const u_char *theirid, u_int theirid_len,
const u_char *myid, u_int myid_len,
const u_char *theirpub1_proof, u_int theirpub1_proof_len,
const u_char *theirpub2_proof, u_int theirpub2_proof_len,
BIGNUM **newpub,
u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
{
BN_CTX *bn_ctx;
BIGNUM *tmp, *exponent;
/* Validate peer's step 1 values */
if (BN_cmp(theirpub1, BN_value_one()) <= 0)
fatal("%s: theirpub1 <= 1", __func__);
if (BN_cmp(theirpub1, grp->p) >= 0)
fatal("%s: theirpub1 >= p", __func__);
if (BN_cmp(theirpub2, BN_value_one()) <= 0)
fatal("%s: theirpub2 <= 1", __func__);
if (BN_cmp(theirpub2, grp->p) >= 0)
fatal("%s: theirpub2 >= p", __func__);
if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub1,
theirid, theirid_len, theirpub1_proof, theirpub1_proof_len) != 1)
fatal("%s: schnorr_verify theirpub1 failed", __func__);
if (schnorr_verify_buf(grp->p, grp->q, grp->g, theirpub2,
theirid, theirid_len, theirpub2_proof, theirpub2_proof_len) != 1)
fatal("%s: schnorr_verify theirpub2 failed", __func__);
if ((bn_ctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new", __func__);
if ((*newpub = BN_new()) == NULL ||
(tmp = BN_new()) == NULL ||
(exponent = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
/*
* client: exponent = x2 * s mod p
* server: exponent = x4 * s mod p
*/
if (BN_mod_mul(exponent, mypriv2, s, grp->q, bn_ctx) != 1)
fatal("%s: BN_mod_mul (exponent = mypriv2 * s mod p)",
__func__);
/*
* client: tmp = g^(x1 + x3 + x4) mod p
* server: tmp = g^(x1 + x2 + x3) mod p
*/
if (BN_mod_mul(tmp, mypub1, theirpub1, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (tmp = mypub1 * theirpub1 mod p)",
__func__);
if (BN_mod_mul(tmp, tmp, theirpub2, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (tmp = tmp * theirpub2 mod p)", __func__);
/*
* client: a = tmp^exponent = g^((x1+x3+x4) * x2 * s) mod p
* server: b = tmp^exponent = g^((x1+x2+x3) * x4 * s) mod p
*/
if (BN_mod_exp(*newpub, tmp, exponent, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (newpub = tmp^exponent mod p)", __func__);
JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
JPAKE_DEBUG_BN((exponent, "%s: exponent = ", __func__));
/* Note the generator here is 'tmp', not g */
if (schnorr_sign_buf(grp->p, grp->q, tmp, exponent, *newpub,
myid, myid_len,
newpub_exponent_proof, newpub_exponent_proof_len) != 0)
fatal("%s: schnorr_sign newpub", __func__);
BN_clear_free(tmp); /* XXX stash for later use? */
BN_clear_free(exponent); /* XXX stash for later use? (yes, in conf) */
BN_CTX_free(bn_ctx);
}
/* Confirmation hash calculation */
void
jpake_confirm_hash(const BIGNUM *k,
const u_char *endpoint_id, u_int endpoint_id_len,
const u_char *sess_id, u_int sess_id_len,
u_char **confirm_hash, u_int *confirm_hash_len)
{
Buffer b;
/*
* Calculate confirmation proof:
* client: H(k || client_id || session_id)
* server: H(k || server_id || session_id)
*/
buffer_init(&b);
buffer_put_bignum2(&b, k);
buffer_put_string(&b, endpoint_id, endpoint_id_len);
buffer_put_string(&b, sess_id, sess_id_len);
if (hash_buffer(buffer_ptr(&b), buffer_len(&b), EVP_sha256(),
confirm_hash, confirm_hash_len) != 0)
fatal("%s: hash_buffer", __func__);
buffer_free(&b);
}
/* Shared parts of key derivation and confirmation calculation */
void
jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
BIGNUM *theirpub1, BIGNUM *theirpub2,
const u_char *my_id, u_int my_id_len,
const u_char *their_id, u_int their_id_len,
const u_char *sess_id, u_int sess_id_len,
const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
BIGNUM **k,
u_char **confirm_hash, u_int *confirm_hash_len)
{
BN_CTX *bn_ctx;
BIGNUM *tmp;
if ((bn_ctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new", __func__);
if ((tmp = BN_new()) == NULL ||
(*k = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
/* Validate step 2 values */
if (BN_cmp(step2_val, BN_value_one()) <= 0)
fatal("%s: step2_val <= 1", __func__);
if (BN_cmp(step2_val, grp->p) >= 0)
fatal("%s: step2_val >= p", __func__);
/*
* theirpriv2_s_proof is calculated with a different generator:
* tmp = g^(mypriv1+mypriv2+theirpub1) = g^mypub1*g^mypub2*g^theirpub1
* Calculate it here so we can check the signature.
*/
if (BN_mod_mul(tmp, mypub1, mypub2, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (tmp = mypub1 * mypub2 mod p)", __func__);
if (BN_mod_mul(tmp, tmp, theirpub1, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (tmp = tmp * theirpub1 mod p)", __func__);
JPAKE_DEBUG_BN((tmp, "%s: tmp = ", __func__));
if (schnorr_verify_buf(grp->p, grp->q, tmp, step2_val,
their_id, their_id_len,
theirpriv2_s_proof, theirpriv2_s_proof_len) != 1)
fatal("%s: schnorr_verify theirpriv2_s_proof failed", __func__);
/*
* Derive shared key:
* client: k = (b / g^(x2*x4*s))^x2 = g^((x1+x3)*x2*x4*s)
* server: k = (a / g^(x2*x4*s))^x4 = g^((x1+x3)*x2*x4*s)
*
* Computed as:
* client: k = (g_x4^(q - (x2 * s)) * b)^x2 mod p
* server: k = (g_x2^(q - (x4 * s)) * b)^x4 mod p
*/
if (BN_mul(tmp, mypriv2, s, bn_ctx) != 1)
fatal("%s: BN_mul (tmp = mypriv2 * s)", __func__);
if (BN_mod_sub(tmp, grp->q, tmp, grp->q, bn_ctx) != 1)
fatal("%s: BN_mod_sub (tmp = q - tmp mod q)", __func__);
if (BN_mod_exp(tmp, theirpub2, tmp, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_exp (tmp = theirpub2^tmp) mod p", __func__);
if (BN_mod_mul(tmp, tmp, step2_val, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_mul (tmp = tmp * step2_val) mod p", __func__);
if (BN_mod_exp(*k, tmp, mypriv2, grp->p, bn_ctx) != 1)
fatal("%s: BN_mod_exp (k = tmp^mypriv2) mod p", __func__);
BN_CTX_free(bn_ctx);
BN_clear_free(tmp);
jpake_confirm_hash(*k, my_id, my_id_len, sess_id, sess_id_len,
confirm_hash, confirm_hash_len);
}
/*
* Calculate and check confirmation hash from peer. Returns 1 on success
* 0 on failure/mismatch.
*/
int
jpake_check_confirm(const BIGNUM *k,
const u_char *peer_id, u_int peer_id_len,
const u_char *sess_id, u_int sess_id_len,
const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
{
u_char *expected_confirm_hash;
u_int expected_confirm_hash_len;
int success = 0;
/* Calculate and verify expected confirmation hash */
jpake_confirm_hash(k, peer_id, peer_id_len, sess_id, sess_id_len,
&expected_confirm_hash, &expected_confirm_hash_len);
JPAKE_DEBUG_BUF((expected_confirm_hash, expected_confirm_hash_len,
"%s: expected confirm hash", __func__));
JPAKE_DEBUG_BUF((peer_confirm_hash, peer_confirm_hash_len,
"%s: received confirm hash", __func__));
if (peer_confirm_hash_len != expected_confirm_hash_len)
error("%s: confirmation length mismatch (my %u them %u)",
__func__, expected_confirm_hash_len, peer_confirm_hash_len);
else if (timingsafe_bcmp(peer_confirm_hash, expected_confirm_hash,
expected_confirm_hash_len) == 0)
success = 1;
bzero(expected_confirm_hash, expected_confirm_hash_len);
free(expected_confirm_hash);
debug3("%s: success = %d", __func__, success);
return success;
}
/* XXX main() function with tests */
#endif /* JPAKE */

114
jpake.h
View File

@ -1,114 +0,0 @@
/* $OpenBSD: jpake.h,v 1.2 2009/03/05 07:18:19 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef JPAKE_H
#define JPAKE_H
#include <sys/types.h>
#include <openssl/bn.h>
/* Set JPAKE_DEBUG in CFLAGS for privacy-violating debugging */
#ifndef JPAKE_DEBUG
# define JPAKE_DEBUG_BN(a)
# define JPAKE_DEBUG_BUF(a)
# define JPAKE_DEBUG_CTX(a)
#else
# define JPAKE_DEBUG_BN(a) debug3_bn a
# define JPAKE_DEBUG_BUF(a) debug3_buf a
# define JPAKE_DEBUG_CTX(a) jpake_dump a
#endif /* JPAKE_DEBUG */
#define KZP_ID_LEN 16 /* Length of client and server IDs */
struct jpake_ctx {
/* Parameters */
struct modp_group *grp;
/* Private values shared by client and server */
BIGNUM *s; /* Secret (salted, crypted password) */
BIGNUM *k; /* Derived key */
/* Client private values (NULL for server) */
BIGNUM *x1; /* random in Zq */
BIGNUM *x2; /* random in Z*q */
/* Server private values (NULL for server) */
BIGNUM *x3; /* random in Zq */
BIGNUM *x4; /* random in Z*q */
/* Step 1: C->S */
u_char *client_id; /* Anti-replay nonce */
u_int client_id_len;
BIGNUM *g_x1; /* g^x1 */
BIGNUM *g_x2; /* g^x2 */
/* Step 1: S->C */
u_char *server_id; /* Anti-replay nonce */
u_int server_id_len;
BIGNUM *g_x3; /* g^x3 */
BIGNUM *g_x4; /* g^x4 */
/* Step 2: C->S */
BIGNUM *a; /* g^((x1+x3+x4)*x2*s) */
/* Step 2: S->C */
BIGNUM *b; /* g^((x1+x2+x3)*x4*s) */
/* Confirmation: C->S */
u_char *h_k_cid_sessid; /* H(k || client_id || session_id) */
u_int h_k_cid_sessid_len;
/* Confirmation: S->C */
u_char *h_k_sid_sessid; /* H(k || server_id || session_id) */
u_int h_k_sid_sessid_len;
};
/* jpake.c */
struct modp_group *jpake_default_group(void);
void jpake_dump(struct jpake_ctx *, const char *, ...)
__attribute__((__nonnull__ (2)))
__attribute__((format(printf, 2, 3)));
struct jpake_ctx *jpake_new(void);
void jpake_free(struct jpake_ctx *);
void jpake_step1(struct modp_group *, u_char **, u_int *,
BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
u_char **, u_int *, u_char **, u_int *);
void jpake_step2(struct modp_group *, BIGNUM *,
BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
const u_char *, u_int, const u_char *, u_int,
const u_char *, u_int, const u_char *, u_int,
BIGNUM **, u_char **, u_int *);
void jpake_confirm_hash(const BIGNUM *,
const u_char *, u_int,
const u_char *, u_int,
u_char **, u_int *);
void jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
const u_char *, u_int, const u_char *, u_int,
const u_char *, u_int, const u_char *, u_int,
BIGNUM **, u_char **, u_int *);
int jpake_check_confirm(const BIGNUM *, const u_char *, u_int,
const u_char *, u_int, const u_char *, u_int);
#endif /* JPAKE_H */

6
kex.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.97 2014/01/25 20:35:37 markus Exp $ */
/* $OpenBSD: kex.c,v 1.98 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
@ -666,8 +666,8 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
fatal("%s: ssh_digest_final failed", __func__);
memcpy(id, obuf, ssh_digest_bytes(SSH_DIGEST_MD5));
memset(nbuf, 0, sizeof(nbuf));
memset(obuf, 0, sizeof(obuf));
explicit_bzero(nbuf, sizeof(nbuf));
explicit_bzero(obuf, sizeof(obuf));
}
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)

7
kex.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.61 2014/01/25 10:12:50 dtucker Exp $ */
/* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -105,9 +105,8 @@ struct Mac {
u_int key_len;
int type;
int etm; /* Encrypt-then-MAC */
const EVP_MD *evp_md;
HMAC_CTX evp_ctx;
struct umac_ctx *umac_ctx;
struct ssh_hmac_ctx *hmac_ctx;
struct umac_ctx *umac_ctx;
};
struct Comp {
int type;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexc25519.c,v 1.4 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexc25519.c,v 1.5 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -70,7 +70,7 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
#endif
buffer_clear(out);
buffer_put_bignum2_from_string(out, shared_key, CURVE25519_SIZE);
memset(shared_key, 0, CURVE25519_SIZE); /* XXX explicit_bzero() */
explicit_bzero(shared_key, CURVE25519_SIZE);
}
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexdhc.c,v 1.14 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexdhc.c,v 1.15 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -124,7 +124,7 @@ kexdh_client(Kex *kex)
fatal("kexdh_client: BN_new failed");
if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
fatal("kexdh_client: BN_bin2bn failed");
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
/* calc and verify H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexdhs.c,v 1.17 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexdhs.c,v 1.18 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -110,7 +110,7 @@ kexdh_server(Kex *kex)
fatal("kexdh_server: BN_new failed");
if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
fatal("kexdh_server: BN_bin2bn failed");
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexecdhc.c,v 1.6 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexecdhc.c,v 1.7 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -119,7 +119,7 @@ kexecdh_client(Kex *kex)
fatal("%s: BN_new failed", __func__);
if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
fatal("%s: BN_bin2bn failed", __func__);
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
/* calc and verify H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexecdhs.c,v 1.9 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexecdhs.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -103,7 +103,7 @@ kexecdh_server(Kex *kex)
fatal("%s: BN_new failed", __func__);
if (BN_bin2bn(kbuf, klen, shared_secret) == NULL)
fatal("%s: BN_bin2bn failed", __func__);
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
/* calc H */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexgexc.c,v 1.16 2014/01/25 10:12:50 dtucker Exp $ */
/* $OpenBSD: kexgexc.c,v 1.17 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -162,7 +162,7 @@ kexgex_client(Kex *kex)
fatal("kexgex_client: BN_new failed");
if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
fatal("kexgex_client: BN_bin2bn failed");
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
if (datafellows & SSH_OLD_DHGEX)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: kexgexs.c,v 1.18 2014/01/12 08:13:13 djm Exp $ */
/* $OpenBSD: kexgexs.c,v 1.19 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2000 Niels Provos. All rights reserved.
* Copyright (c) 2001 Markus Friedl. All rights reserved.
@ -150,7 +150,7 @@ kexgex_server(Kex *kex)
fatal("kexgex_server: BN_new failed");
if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
fatal("kexgex_server: BN_bin2bn failed");
memset(kbuf, 0, klen);
explicit_bzero(kbuf, klen);
free(kbuf);
key_to_blob(server_host_public, &server_host_key_blob, &sbloblen);

12
key.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: key.c,v 1.115 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: key.c,v 1.116 2014/02/02 03:44:31 djm Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -242,12 +242,12 @@ key_free(Key *k)
case KEY_ED25519:
case KEY_ED25519_CERT:
if (k->ed25519_pk) {
memset(k->ed25519_pk, 0, ED25519_PK_SZ);
explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
free(k->ed25519_pk);
k->ed25519_pk = NULL;
}
if (k->ed25519_sk) {
memset(k->ed25519_sk, 0, ED25519_SK_SZ);
explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
free(k->ed25519_sk);
k->ed25519_sk = NULL;
}
@ -415,7 +415,7 @@ key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
if ((ssh_digest_memory(hash_alg, blob, len,
retval, SSH_DIGEST_MAX_LENGTH)) != 0)
fatal("%s: digest_memory failed", __func__);
memset(blob, 0, len);
explicit_bzero(blob, len);
free(blob);
*dgst_raw_length = ssh_digest_bytes(hash_alg);
} else {
@ -623,7 +623,7 @@ key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
dgst_rep);
break;
}
memset(dgst_raw, 0, dgst_raw_len);
explicit_bzero(dgst_raw, dgst_raw_len);
free(dgst_raw);
return retval;
}
@ -1744,7 +1744,7 @@ to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain)
*blobp = xmalloc(len);
memcpy(*blobp, buffer_ptr(&b), len);
}
memset(buffer_ptr(&b), 0, len);
explicit_bzero(buffer_ptr(&b), len);
buffer_free(&b);
return len;
}

12
krl.c
View File

@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $OpenBSD: krl.c,v 1.13 2013/07/20 22:20:42 djm Exp $ */
/* $OpenBSD: krl.c,v 1.14 2014/01/31 16:39:19 tedu Exp $ */
#include "includes.h"
@ -238,7 +238,7 @@ insert_serial_range(struct revoked_serial_tree *rt, u_int64_t lo, u_int64_t hi)
struct revoked_serial rs, *ers, *crs, *irs;
KRL_DBG(("%s: insert %llu:%llu", __func__, lo, hi));
bzero(&rs, sizeof(rs));
memset(&rs, 0, sizeof(rs));
rs.lo = lo;
rs.hi = hi;
ers = RB_NFIND(revoked_serial_tree, rt, &rs);
@ -1115,7 +1115,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
struct revoked_certs *rc;
/* Check explicitly revoked hashes first */
bzero(&rb, sizeof(rb));
memset(&rb, 0, sizeof(rb));
if ((rb.blob = key_fingerprint_raw(key, SSH_FP_SHA1, &rb.len)) == NULL)
return -1;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
@ -1126,7 +1126,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
}
/* Next, explicit keys */
bzero(&rb, sizeof(rb));
memset(&rb, 0, sizeof(rb));
if (plain_key_blob(key, &rb.blob, &rb.len) != 0)
return -1;
erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
@ -1147,7 +1147,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
return 0; /* No entry for this CA */
/* Check revocation by cert key ID */
bzero(&rki, sizeof(rki));
memset(&rki, 0, sizeof(rki));
rki.key_id = key->cert->key_id;
erki = RB_FIND(revoked_key_id_tree, &rc->revoked_key_ids, &rki);
if (erki != NULL) {
@ -1162,7 +1162,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
if (key_cert_is_legacy(key) || key->cert->serial == 0)
return 0;
bzero(&rs, sizeof(rs));
memset(&rs, 0, sizeof(rs));
rs.lo = rs.hi = key->cert->serial;
ers = RB_FIND(revoked_serial_tree, &rc->revoked_serials, &rs);
if (ers != NULL) {

94
mac.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mac.c,v 1.26 2014/01/04 17:50:55 tedu Exp $ */
/* $OpenBSD: mac.c,v 1.28 2014/02/07 06:55:54 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -27,8 +27,6 @@
#include <sys/types.h>
#include <openssl/hmac.h>
#include <stdarg.h>
#include <string.h>
#include <signal.h>
@ -42,18 +40,20 @@
#include "mac.h"
#include "misc.h"
#include "digest.h"
#include "hmac.h"
#include "umac.h"
#include "openbsd-compat/openssl-compat.h"
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */
#define SSH_DIGEST 1 /* SSH_DIGEST_XXX */
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
#define SSH_UMAC128 3
struct macalg {
char *name;
int type;
const EVP_MD * (*mdfunc)(void);
int alg;
int truncatebits; /* truncate digest if != 0 */
int key_len; /* just for UMAC */
int len; /* just for UMAC */
@ -62,33 +62,33 @@ struct macalg {
static const struct macalg macs[] = {
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 },
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 },
#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 },
{ "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 },
{ "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 },
#endif
{ "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 },
{ "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 },
{ "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 },
{ "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 },
{ "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 },
{ "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
{ "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 },
{ "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 },
{ "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 },
/* Encrypt-then-MAC variants */
{ "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 },
{ "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 },
{ "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 },
#ifdef HAVE_EVP_SHA256
{ "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 },
{ "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 },
{ "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 },
#endif
{ "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 },
{ "hmac-ripemd160-etm@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 },
{ "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 },
{ "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 },
{ "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 },
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 },
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 },
{ NULL, 0, NULL, 0, 0, 0, 0 }
{ NULL, 0, 0, 0, 0, 0, 0 }
};
/* Returns a list of supported MACs separated by the specified char. */
@ -113,14 +113,11 @@ mac_alg_list(char sep)
static void
mac_setup_by_alg(Mac *mac, const struct macalg *macalg)
{
int evp_len;
mac->type = macalg->type;
if (mac->type == SSH_EVP) {
mac->evp_md = macalg->mdfunc();
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
fatal("mac %s len %d", mac->name, evp_len);
mac->key_len = mac->mac_len = (u_int)evp_len;
if (mac->type == SSH_DIGEST) {
if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)
fatal("ssh_hmac_start(alg=%d) failed", macalg->alg);
mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);
} else {
mac->mac_len = macalg->len / 8;
mac->key_len = macalg->key_len / 8;
@ -139,9 +136,10 @@ mac_setup(Mac *mac, char *name)
for (m = macs; m->name != NULL; m++) {
if (strcmp(name, m->name) != 0)
continue;
if (mac != NULL)
if (mac != NULL) {
mac_setup_by_alg(mac, m);
debug2("mac_setup: found %s", name);
debug2("mac_setup: setup %s", name);
}
return (0);
}
debug2("mac_setup: unknown %s", name);
@ -152,13 +150,12 @@ int
mac_init(Mac *mac)
{
if (mac->key == NULL)
fatal("mac_init: no key");
fatal("%s: no key", __func__);
switch (mac->type) {
case SSH_EVP:
if (mac->evp_md == NULL)
case SSH_DIGEST:
if (mac->hmac_ctx == NULL ||
ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)
return -1;
HMAC_CTX_init(&mac->evp_ctx);
HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
return 0;
case SSH_UMAC:
mac->umac_ctx = umac_new(mac->key);
@ -185,13 +182,14 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
mac->mac_len, sizeof(u));
switch (mac->type) {
case SSH_EVP:
case SSH_DIGEST:
put_u32(b, seqno);
/* reset HMAC context */
HMAC_Init(&mac->evp_ctx, NULL, 0, NULL);
HMAC_Update(&mac->evp_ctx, b, sizeof(b));
HMAC_Update(&mac->evp_ctx, data, datalen);
HMAC_Final(&mac->evp_ctx, u.m, NULL);
if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 ||
ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 ||
ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 ||
ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)
fatal("ssh_hmac failed");
break;
case SSH_UMAC:
put_u64(nonce, seqno);
@ -218,9 +216,9 @@ mac_clear(Mac *mac)
} else if (mac->type == SSH_UMAC128) {
if (mac->umac_ctx != NULL)
umac128_delete(mac->umac_ctx);
} else if (mac->evp_md != NULL)
HMAC_cleanup(&mac->evp_ctx);
mac->evp_md = NULL;
} else if (mac->hmac_ctx != NULL)
ssh_hmac_free(mac->hmac_ctx);
mac->hmac_ctx = NULL;
mac->umac_ctx = NULL;
}
@ -240,8 +238,6 @@ mac_valid(const char *names)
debug("bad mac %s [%s]", p, names);
free(maclist);
return (0);
} else {
debug3("mac ok: %s [%s]", p, names);
}
}
debug3("macs ok: [%s]", names);

View File

@ -71,4 +71,4 @@ STANDARDS
the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006,
2006.
OpenBSD 5.4 September 26, 2012 OpenBSD 5.4
OpenBSD 5.5 September 26, 2012 OpenBSD 5.5

234
monitor.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.128 2013/11/04 11:51:16 markus Exp $ */
/* $OpenBSD: monitor.c,v 1.131 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -95,7 +95,6 @@
#include "misc.h"
#include "compat.h"
#include "ssh2.h"
#include "jpake.h"
#include "roaming.h"
#include "authfd.h"
@ -161,11 +160,6 @@ int mm_answer_rsa_challenge(int, Buffer *);
int mm_answer_rsa_response(int, Buffer *);
int mm_answer_sesskey(int, Buffer *);
int mm_answer_sessid(int, Buffer *);
int mm_answer_jpake_get_pwdata(int, Buffer *);
int mm_answer_jpake_step1(int, Buffer *);
int mm_answer_jpake_step2(int, Buffer *);
int mm_answer_jpake_key_confirm(int, Buffer *);
int mm_answer_jpake_check_confirm(int, Buffer *);
#ifdef USE_PAM
int mm_answer_pam_start(int, Buffer *);
@ -253,13 +247,6 @@ struct mon_table mon_dispatch_proto20[] = {
{MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
{MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
{MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
#endif
#ifdef JPAKE
{MONITOR_REQ_JPAKE_GET_PWDATA, MON_ONCE, mm_answer_jpake_get_pwdata},
{MONITOR_REQ_JPAKE_STEP1, MON_ISAUTH, mm_answer_jpake_step1},
{MONITOR_REQ_JPAKE_STEP2, MON_ONCE, mm_answer_jpake_step2},
{MONITOR_REQ_JPAKE_KEY_CONFIRM, MON_ONCE, mm_answer_jpake_key_confirm},
{MONITOR_REQ_JPAKE_CHECK_CONFIRM, MON_AUTH, mm_answer_jpake_check_confirm},
#endif
{0, 0, NULL}
};
@ -427,15 +414,6 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
if (!authenticated)
authctxt->failures++;
}
#ifdef JPAKE
/* Cleanup JPAKE context after authentication */
if (ent->flags & MON_AUTHDECIDE) {
if (authctxt->jpake_ctx != NULL) {
jpake_free(authctxt->jpake_ctx);
authctxt->jpake_ctx = NULL;
}
}
#endif
}
if (!authctxt->valid)
@ -566,7 +544,7 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent,
struct pollfd pfd[2];
for (;;) {
bzero(&pfd, sizeof(pfd));
memset(&pfd, 0, sizeof(pfd));
pfd[0].fd = pmonitor->m_sendfd;
pfd[0].events = POLLIN;
pfd[1].fd = pmonitor->m_log_recvfd;
@ -880,7 +858,7 @@ mm_answer_authpassword(int sock, Buffer *m)
/* Only authenticate if the context is valid */
authenticated = options.password_authentication &&
auth_password(authctxt, passwd);
memset(passwd, 0, strlen(passwd));
explicit_bzero(passwd, strlen(passwd));
free(passwd);
buffer_clear(m);
@ -1822,13 +1800,13 @@ monitor_apply_keystate(struct monitor *pmonitor)
/* XXX inefficient for large buffers, need: buffer_init_from_string */
buffer_clear(packet_get_input());
buffer_append(packet_get_input(), child_state.input, child_state.ilen);
memset(child_state.input, 0, child_state.ilen);
explicit_bzero(child_state.input, child_state.ilen);
free(child_state.input);
buffer_clear(packet_get_output());
buffer_append(packet_get_output(), child_state.output,
child_state.olen);
memset(child_state.output, 0, child_state.olen);
explicit_bzero(child_state.output, child_state.olen);
free(child_state.output);
/* Roaming */
@ -2159,205 +2137,3 @@ mm_answer_gss_userok(int sock, Buffer *m)
}
#endif /* GSSAPI */
#ifdef JPAKE
int
mm_answer_jpake_step1(int sock, Buffer *m)
{
struct jpake_ctx *pctx;
u_char *x3_proof, *x4_proof;
u_int x3_proof_len, x4_proof_len;
if (!options.zero_knowledge_password_authentication)
fatal("zero_knowledge_password_authentication disabled");
if (authctxt->jpake_ctx != NULL)
fatal("%s: authctxt->jpake_ctx already set (%p)",
__func__, authctxt->jpake_ctx);
authctxt->jpake_ctx = pctx = jpake_new();
jpake_step1(pctx->grp,
&pctx->server_id, &pctx->server_id_len,
&pctx->x3, &pctx->x4, &pctx->g_x3, &pctx->g_x4,
&x3_proof, &x3_proof_len,
&x4_proof, &x4_proof_len);
JPAKE_DEBUG_CTX((pctx, "step1 done in %s", __func__));
buffer_clear(m);
buffer_put_string(m, pctx->server_id, pctx->server_id_len);
buffer_put_bignum2(m, pctx->g_x3);
buffer_put_bignum2(m, pctx->g_x4);
buffer_put_string(m, x3_proof, x3_proof_len);
buffer_put_string(m, x4_proof, x4_proof_len);
debug3("%s: sending step1", __func__);
mm_request_send(sock, MONITOR_ANS_JPAKE_STEP1, m);
bzero(x3_proof, x3_proof_len);
bzero(x4_proof, x4_proof_len);
free(x3_proof);
free(x4_proof);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_GET_PWDATA, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 0);
return 0;
}
int
mm_answer_jpake_get_pwdata(int sock, Buffer *m)
{
struct jpake_ctx *pctx = authctxt->jpake_ctx;
char *hash_scheme, *salt;
if (pctx == NULL)
fatal("%s: pctx == NULL", __func__);
auth2_jpake_get_pwdata(authctxt, &pctx->s, &hash_scheme, &salt);
buffer_clear(m);
/* pctx->s is sensitive, not returned to slave */
buffer_put_cstring(m, hash_scheme);
buffer_put_cstring(m, salt);
debug3("%s: sending pwdata", __func__);
mm_request_send(sock, MONITOR_ANS_JPAKE_GET_PWDATA, m);
bzero(hash_scheme, strlen(hash_scheme));
bzero(salt, strlen(salt));
free(hash_scheme);
free(salt);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP2, 1);
return 0;
}
int
mm_answer_jpake_step2(int sock, Buffer *m)
{
struct jpake_ctx *pctx = authctxt->jpake_ctx;
u_char *x1_proof, *x2_proof, *x4_s_proof;
u_int x1_proof_len, x2_proof_len, x4_s_proof_len;
if (pctx == NULL)
fatal("%s: pctx == NULL", __func__);
if ((pctx->g_x1 = BN_new()) == NULL ||
(pctx->g_x2 = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
buffer_get_bignum2(m, pctx->g_x1);
buffer_get_bignum2(m, pctx->g_x2);
pctx->client_id = buffer_get_string(m, &pctx->client_id_len);
x1_proof = buffer_get_string(m, &x1_proof_len);
x2_proof = buffer_get_string(m, &x2_proof_len);
jpake_step2(pctx->grp, pctx->s, pctx->g_x3,
pctx->g_x1, pctx->g_x2, pctx->x4,
pctx->client_id, pctx->client_id_len,
pctx->server_id, pctx->server_id_len,
x1_proof, x1_proof_len,
x2_proof, x2_proof_len,
&pctx->b,
&x4_s_proof, &x4_s_proof_len);
JPAKE_DEBUG_CTX((pctx, "step2 done in %s", __func__));
bzero(x1_proof, x1_proof_len);
bzero(x2_proof, x2_proof_len);
free(x1_proof);
free(x2_proof);
buffer_clear(m);
buffer_put_bignum2(m, pctx->b);
buffer_put_string(m, x4_s_proof, x4_s_proof_len);
debug3("%s: sending step2", __func__);
mm_request_send(sock, MONITOR_ANS_JPAKE_STEP2, m);
bzero(x4_s_proof, x4_s_proof_len);
free(x4_s_proof);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_KEY_CONFIRM, 1);
return 0;
}
int
mm_answer_jpake_key_confirm(int sock, Buffer *m)
{
struct jpake_ctx *pctx = authctxt->jpake_ctx;
u_char *x2_s_proof;
u_int x2_s_proof_len;
if (pctx == NULL)
fatal("%s: pctx == NULL", __func__);
if ((pctx->a = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
buffer_get_bignum2(m, pctx->a);
x2_s_proof = buffer_get_string(m, &x2_s_proof_len);
jpake_key_confirm(pctx->grp, pctx->s, pctx->a,
pctx->x4, pctx->g_x3, pctx->g_x4, pctx->g_x1, pctx->g_x2,
pctx->server_id, pctx->server_id_len,
pctx->client_id, pctx->client_id_len,
session_id2, session_id2_len,
x2_s_proof, x2_s_proof_len,
&pctx->k,
&pctx->h_k_sid_sessid, &pctx->h_k_sid_sessid_len);
JPAKE_DEBUG_CTX((pctx, "key_confirm done in %s", __func__));
bzero(x2_s_proof, x2_s_proof_len);
buffer_clear(m);
/* pctx->k is sensitive, not sent */
buffer_put_string(m, pctx->h_k_sid_sessid, pctx->h_k_sid_sessid_len);
debug3("%s: sending confirmation hash", __func__);
mm_request_send(sock, MONITOR_ANS_JPAKE_KEY_CONFIRM, m);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_CHECK_CONFIRM, 1);
return 0;
}
int
mm_answer_jpake_check_confirm(int sock, Buffer *m)
{
int authenticated = 0;
u_char *peer_confirm_hash;
u_int peer_confirm_hash_len;
struct jpake_ctx *pctx = authctxt->jpake_ctx;
if (pctx == NULL)
fatal("%s: pctx == NULL", __func__);
peer_confirm_hash = buffer_get_string(m, &peer_confirm_hash_len);
authenticated = jpake_check_confirm(pctx->k,
pctx->client_id, pctx->client_id_len,
session_id2, session_id2_len,
peer_confirm_hash, peer_confirm_hash_len) && authctxt->valid;
JPAKE_DEBUG_CTX((pctx, "check_confirm done in %s", __func__));
bzero(peer_confirm_hash, peer_confirm_hash_len);
free(peer_confirm_hash);
buffer_clear(m);
buffer_put_int(m, authenticated);
debug3("%s: sending result %d", __func__, authenticated);
mm_request_send(sock, MONITOR_ANS_JPAKE_CHECK_CONFIRM, m);
monitor_permit(mon_dispatch, MONITOR_REQ_JPAKE_STEP1, 1);
auth_method = "jpake-01@openssh.com";
return authenticated;
}
#endif /* JPAKE */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.h,v 1.17 2012/12/02 20:34:10 djm Exp $ */
/* $OpenBSD: monitor.h,v 1.18 2014/01/29 06:18:35 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -56,11 +56,6 @@ enum monitor_reqtype {
MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
MONITOR_REQ_TERM = 50,
MONITOR_REQ_JPAKE_STEP1 = 52, MONITOR_ANS_JPAKE_STEP1 = 53,
MONITOR_REQ_JPAKE_GET_PWDATA = 54, MONITOR_ANS_JPAKE_GET_PWDATA = 55,
MONITOR_REQ_JPAKE_STEP2 = 56, MONITOR_ANS_JPAKE_STEP2 = 57,
MONITOR_REQ_JPAKE_KEY_CONFIRM = 58, MONITOR_ANS_JPAKE_KEY_CONFIRM = 59,
MONITOR_REQ_JPAKE_CHECK_CONFIRM = 60, MONITOR_ANS_JPAKE_CHECK_CONFIRM = 61,
MONITOR_REQ_PAM_START = 100,
MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.77 2013/11/06 16:52:11 markus Exp $ */
/* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -71,8 +71,6 @@
#include "atomicio.h"
#include "monitor_fdpass.h"
#include "misc.h"
#include "schnorr.h"
#include "jpake.h"
#include "uuencode.h"
#include "channels.h"
@ -574,7 +572,7 @@ mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
*blobp = xmalloc(len);
memcpy(*blobp, buffer_ptr(&b), len);
}
memset(buffer_ptr(&b), 0, len);
explicit_bzero(buffer_ptr(&b), len);
buffer_free(&b);
return len;
}
@ -618,7 +616,7 @@ mm_send_keystate(struct monitor *monitor)
key = xmalloc(keylen+1); /* add 1 if keylen == 0 */
keylen = packet_get_encryption_key(key);
buffer_put_string(&m, key, keylen);
memset(key, 0, keylen);
explicit_bzero(key, keylen);
free(key);
ivlen = packet_get_keyiv_len(MODE_OUT);
@ -1292,164 +1290,3 @@ mm_ssh_gssapi_userok(char *user)
}
#endif /* GSSAPI */
#ifdef JPAKE
void
mm_auth2_jpake_get_pwdata(Authctxt *authctxt, BIGNUM **s,
char **hash_scheme, char **salt)
{
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_JPAKE_GET_PWDATA, &m);
debug3("%s: waiting for MONITOR_ANS_JPAKE_GET_PWDATA", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_JPAKE_GET_PWDATA, &m);
*hash_scheme = buffer_get_string(&m, NULL);
*salt = buffer_get_string(&m, NULL);
buffer_free(&m);
}
void
mm_jpake_step1(struct modp_group *grp,
u_char **id, u_int *id_len,
BIGNUM **priv1, BIGNUM **priv2, BIGNUM **g_priv1, BIGNUM **g_priv2,
u_char **priv1_proof, u_int *priv1_proof_len,
u_char **priv2_proof, u_int *priv2_proof_len)
{
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_JPAKE_STEP1, &m);
debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP1", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_JPAKE_STEP1, &m);
if ((*priv1 = BN_new()) == NULL ||
(*priv2 = BN_new()) == NULL ||
(*g_priv1 = BN_new()) == NULL ||
(*g_priv2 = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
*id = buffer_get_string(&m, id_len);
/* priv1 and priv2 are, well, private */
buffer_get_bignum2(&m, *g_priv1);
buffer_get_bignum2(&m, *g_priv2);
*priv1_proof = buffer_get_string(&m, priv1_proof_len);
*priv2_proof = buffer_get_string(&m, priv2_proof_len);
buffer_free(&m);
}
void
mm_jpake_step2(struct modp_group *grp, BIGNUM *s,
BIGNUM *mypub1, BIGNUM *theirpub1, BIGNUM *theirpub2, BIGNUM *mypriv2,
const u_char *theirid, u_int theirid_len,
const u_char *myid, u_int myid_len,
const u_char *theirpub1_proof, u_int theirpub1_proof_len,
const u_char *theirpub2_proof, u_int theirpub2_proof_len,
BIGNUM **newpub,
u_char **newpub_exponent_proof, u_int *newpub_exponent_proof_len)
{
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
/* monitor already has all bignums except theirpub1, theirpub2 */
buffer_put_bignum2(&m, theirpub1);
buffer_put_bignum2(&m, theirpub2);
/* monitor already knows our id */
buffer_put_string(&m, theirid, theirid_len);
buffer_put_string(&m, theirpub1_proof, theirpub1_proof_len);
buffer_put_string(&m, theirpub2_proof, theirpub2_proof_len);
mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_JPAKE_STEP2, &m);
debug3("%s: waiting for MONITOR_ANS_JPAKE_STEP2", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_JPAKE_STEP2, &m);
if ((*newpub = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
buffer_get_bignum2(&m, *newpub);
*newpub_exponent_proof = buffer_get_string(&m,
newpub_exponent_proof_len);
buffer_free(&m);
}
void
mm_jpake_key_confirm(struct modp_group *grp, BIGNUM *s, BIGNUM *step2_val,
BIGNUM *mypriv2, BIGNUM *mypub1, BIGNUM *mypub2,
BIGNUM *theirpub1, BIGNUM *theirpub2,
const u_char *my_id, u_int my_id_len,
const u_char *their_id, u_int their_id_len,
const u_char *sess_id, u_int sess_id_len,
const u_char *theirpriv2_s_proof, u_int theirpriv2_s_proof_len,
BIGNUM **k,
u_char **confirm_hash, u_int *confirm_hash_len)
{
Buffer m;
debug3("%s entering", __func__);
buffer_init(&m);
/* monitor already has all bignums except step2_val */
buffer_put_bignum2(&m, step2_val);
/* monitor already knows all the ids */
buffer_put_string(&m, theirpriv2_s_proof, theirpriv2_s_proof_len);
mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_JPAKE_KEY_CONFIRM, &m);
debug3("%s: waiting for MONITOR_ANS_JPAKE_KEY_CONFIRM", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_JPAKE_KEY_CONFIRM, &m);
/* 'k' is sensitive and stays in the monitor */
*confirm_hash = buffer_get_string(&m, confirm_hash_len);
buffer_free(&m);
}
int
mm_jpake_check_confirm(const BIGNUM *k,
const u_char *peer_id, u_int peer_id_len,
const u_char *sess_id, u_int sess_id_len,
const u_char *peer_confirm_hash, u_int peer_confirm_hash_len)
{
Buffer m;
int success = 0;
debug3("%s entering", __func__);
buffer_init(&m);
/* k is dummy in slave, ignored */
/* monitor knows all the ids */
buffer_put_string(&m, peer_confirm_hash, peer_confirm_hash_len);
mm_request_send(pmonitor->m_recvfd,
MONITOR_REQ_JPAKE_CHECK_CONFIRM, &m);
debug3("%s: waiting for MONITOR_ANS_JPAKE_CHECK_CONFIRM", __func__);
mm_request_receive_expect(pmonitor->m_recvfd,
MONITOR_ANS_JPAKE_CHECK_CONFIRM, &m);
success = buffer_get_int(&m);
buffer_free(&m);
debug3("%s: success = %d", __func__, success);
return success;
}
#endif /* JPAKE */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */
/* $OpenBSD: monitor_wrap.h,v 1.24 2014/01/29 06:18:35 djm Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -102,26 +102,6 @@ int mm_bsdauth_respond(void *, u_int, char **);
int mm_skey_query(void *, char **, char **, u_int *, char ***, u_int **);
int mm_skey_respond(void *, u_int, char **);
/* jpake */
struct modp_group;
void mm_auth2_jpake_get_pwdata(struct Authctxt *, BIGNUM **, char **, char **);
void mm_jpake_step1(struct modp_group *, u_char **, u_int *,
BIGNUM **, BIGNUM **, BIGNUM **, BIGNUM **,
u_char **, u_int *, u_char **, u_int *);
void mm_jpake_step2(struct modp_group *, BIGNUM *,
BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
const u_char *, u_int, const u_char *, u_int,
const u_char *, u_int, const u_char *, u_int,
BIGNUM **, u_char **, u_int *);
void mm_jpake_key_confirm(struct modp_group *, BIGNUM *, BIGNUM *,
BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *,
const u_char *, u_int, const u_char *, u_int,
const u_char *, u_int, const u_char *, u_int,
BIGNUM **, u_char **, u_int *);
int mm_jpake_check_confirm(const BIGNUM *,
const u_char *, u_int, const u_char *, u_int, const u_char *, u_int);
/* zlib allocation hooks */
void *mm_zalloc(struct mm_master *, u_int, u_int);

View File

@ -1,4 +1,4 @@
# $Id: Makefile.in,v 1.54 2013/12/07 01:37:54 djm Exp $
# $Id: Makefile.in,v 1.55 2014/02/04 00:37:50 djm Exp $
sysconfdir=@sysconfdir@
piddir=@piddir@
@ -16,7 +16,7 @@ RANLIB=@RANLIB@
INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xmmap.o xcrypt.o

View File

@ -1,4 +1,4 @@
/* $Id: bsd-poll.c,v 1.5 2013/11/08 10:12:58 dtucker Exp $ */
/* $Id: bsd-poll.c,v 1.6 2014/02/05 23:44:13 dtucker Exp $ */
/*
* Copyright (c) 2004, 2005, 2007 Darren Tucker (dtucker at zip com au).
@ -109,12 +109,9 @@ poll(struct pollfd *fds, nfds_t nfds, int timeout)
}
out:
if (readfds != NULL)
free(readfds);
if (writefds != NULL)
free(writefds);
if (exceptfds != NULL)
free(exceptfds);
free(readfds);
free(writefds);
free(exceptfds);
if (ret == -1)
errno = saved_errno;
return ret;

View File

@ -0,0 +1,20 @@
/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */
/* $OpenBSD: explicit_bzero.c,v 1.1 2014/01/22 21:06:45 tedu Exp $ */
/*
* Public domain.
* Written by Ted Unangst
*/
#include "includes.h"
#ifndef HAVE_EXPLICIT_BZERO
/*
* explicit_bzero - don't let the compiler optimize away bzero
*/
void
explicit_bzero(void *p, size_t n)
{
bzero(p, n);
}
#endif

View File

@ -1,4 +1,4 @@
/* $Id: openbsd-compat.h,v 1.60 2013/12/07 00:51:54 djm Exp $ */
/* $Id: openbsd-compat.h,v 1.61 2014/02/04 00:18:23 djm Exp $ */
/*
* Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@ -246,6 +246,10 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t,
u_int8_t *, size_t, unsigned int);
#endif
#ifndef HAVE_EXPLICIT_BZERO
void explicit_bzero(void *p, size_t n);
#endif
void *xmmap(size_t size);
char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw);

View File

@ -1,4 +1,4 @@
/* $Id: openssl-compat.c,v 1.16 2014/01/17 07:00:41 dtucker Exp $ */
/* $Id: openssl-compat.c,v 1.17 2014/02/13 05:38:33 dtucker Exp $ */
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@ -96,6 +96,14 @@ ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt)
}
#endif
#ifndef HAVE_EVP_MD_CTX_COPY_EX
int
EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
return EVP_MD_CTX_copy(out, in);
}
#endif
#ifndef HAVE_BN_IS_PRIME_EX
int
BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb)

View File

@ -1,4 +1,4 @@
/* $Id: openssl-compat.h,v 1.25 2014/01/17 06:32:31 dtucker Exp $ */
/* $Id: openssl-compat.h,v 1.26 2014/02/13 05:38:33 dtucker Exp $ */
/*
* Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@ -156,6 +156,10 @@ int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, void *);
int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
# endif
# ifndef EVP_MD_CTX_COPY_EX
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *);
# endif
int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *,
unsigned char *, int);
int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.191 2013/12/06 13:34:54 markus Exp $ */
/* $OpenBSD: packet.c,v 1.192 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -764,9 +764,9 @@ set_newkeys(int mode)
mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp;
mac_clear(mac);
memset(enc->iv, 0, enc->iv_len);
memset(enc->key, 0, enc->key_len);
memset(mac->key, 0, mac->key_len);
explicit_bzero(enc->iv, enc->iv_len);
explicit_bzero(enc->key, enc->key_len);
explicit_bzero(mac->key, mac->key_len);
free(enc->name);
free(enc->iv);
free(enc->key);
@ -787,9 +787,9 @@ set_newkeys(int mode)
cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->iv_len, crypt_type);
/* Deleting the keys does not gain extra security */
/* memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len);
memset(mac->key, 0, mac->key_len); */
/* explicit_bzero(enc->iv, enc->block_size);
explicit_bzero(enc->key, enc->key_len);
explicit_bzero(mac->key, mac->key_len); */
if ((comp->type == COMP_ZLIB ||
(comp->type == COMP_DELAYED &&
active_state->after_authentication)) && comp->enabled == 0) {
@ -928,7 +928,7 @@ packet_send2_wrapped(void)
}
} else {
/* clear padding */
memset(cp, 0, padlen);
explicit_bzero(cp, padlen);
}
/* sizeof (packet_len + pad_len + payload + padding) */
len = buffer_len(&active_state->outgoing_packet);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */
/* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -22,6 +22,7 @@
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
@ -144,7 +145,7 @@ typedef enum {
oSendEnv, oControlPath, oControlMaster, oControlPersist,
oHashKnownHosts,
oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
oVisualHostKey, oUseRoaming,
oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
@ -251,12 +252,6 @@ static struct {
{ "permitlocalcommand", oPermitLocalCommand },
{ "visualhostkey", oVisualHostKey },
{ "useroaming", oUseRoaming },
#ifdef JPAKE
{ "zeroknowledgepasswordauthentication",
oZeroKnowledgePasswordAuthentication },
#else
{ "zeroknowledgepasswordauthentication", oUnsupported },
#endif
{ "kexalgorithms", oKexAlgorithms },
{ "ipqos", oIPQoS },
{ "requesttty", oRequestTTY },
@ -542,16 +537,27 @@ match_cfg_line(Options *options, char **condition, struct passwd *pw,
"r", ruser,
"u", pw->pw_name,
(char *)NULL);
r = execute_in_shell(cmd);
if (r == -1) {
fatal("%.200s line %d: match exec '%.100s' "
"error", filename, linenum, cmd);
} else if (r == 0) {
debug("%.200s line %d: matched "
"'exec \"%.100s\"' ",
if (result != 1) {
/* skip execution if prior predicate failed */
debug("%.200s line %d: skipped exec \"%.100s\"",
filename, linenum, cmd);
} else
result = 0;
} else {
r = execute_in_shell(cmd);
if (r == -1) {
fatal("%.200s line %d: match exec "
"'%.100s' error", filename,
linenum, cmd);
} else if (r == 0) {
debug("%.200s line %d: matched "
"'exec \"%.100s\"'", filename,
linenum, cmd);
} else {
debug("%.200s line %d: no match "
"'exec \"%.100s\"'", filename,
linenum, cmd);
result = 0;
}
}
free(cmd);
} else {
error("Unsupported Match attribute %s", attrib);
@ -803,10 +809,6 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
intptr = &options->password_authentication;
goto parse_flag;
case oZeroKnowledgePasswordAuthentication:
intptr = &options->zero_knowledge_password_authentication;
goto parse_flag;
case oKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
@ -1465,6 +1467,13 @@ read_config_file(const char *filename, struct passwd *pw, const char *host,
return 1;
}
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
int
option_clear_or_none(const char *o)
{
return o == NULL || strcasecmp(o, "none") == 0;
}
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
@ -1549,7 +1558,6 @@ initialize_options(Options * options)
options->permit_local_command = -1;
options->use_roaming = -1;
options->visual_host_key = -1;
options->zero_knowledge_password_authentication = -1;
options->ip_qos_interactive = -1;
options->ip_qos_bulk = -1;
options->request_tty = -1;
@ -1562,11 +1570,25 @@ initialize_options(Options * options)
options->canonicalize_hostname = -1;
}
/*
* A petite version of fill_default_options() that just fills the options
* needed for hostname canonicalization to proceed.
*/
void
fill_default_options_for_canonicalization(Options *options)
{
if (options->canonicalize_max_dots == -1)
options->canonicalize_max_dots = 1;
if (options->canonicalize_fallback_local == -1)
options->canonicalize_fallback_local = 1;
if (options->canonicalize_hostname == -1)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
}
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void
fill_default_options(Options * options)
{
@ -1705,8 +1727,6 @@ fill_default_options(Options * options)
options->use_roaming = 1;
if (options->visual_host_key == -1)
options->visual_host_key = 0;
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_LOWDELAY;
if (options->ip_qos_bulk == -1)
@ -1723,7 +1743,7 @@ fill_default_options(Options * options)
options->canonicalize_hostname = SSH_CANONICALISE_NO;
#define CLEAR_ON_NONE(v) \
do { \
if (v != NULL && strcasecmp(v, "none") == 0) { \
if (option_clear_or_none(v)) { \
free(v); \
v = NULL; \
} \

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.99 2013/10/16 22:49:38 djm Exp $ */
/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -59,7 +59,6 @@ typedef struct {
* authentication. */
int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
char *kbd_interactive_devices; /* Keyboard-interactive auth devices. */
int zero_knowledge_password_authentication; /* Try jpake */
int batch_mode; /* Batch mode: do not ask for passwords. */
int check_host_ip; /* Also keep track of keys for IP address */
int strict_host_key_checking; /* Strict host key checking. */
@ -177,12 +176,14 @@ typedef struct {
void initialize_options(Options *);
void fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *);
int process_config_line(Options *, struct passwd *, const char *, char *,
const char *, int, int *, int);
int read_config_file(const char *, struct passwd *, const char *,
Options *, int);
int parse_forward(Forward *, const char *, int, int);
int default_ssh_port(void);
int option_clear_or_none(const char *);
void add_local_forward(Options *, const Forward *);
void add_remote_forward(Options *, const Forward *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readpass.c,v 1.49 2013/05/17 00:13:14 djm Exp $ */
/* $OpenBSD: readpass.c,v 1.50 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
*
@ -99,13 +99,13 @@ ssh_askpass(char *askpass, const char *msg)
break;
signal(SIGCHLD, osigchld);
if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
memset(buf, 0, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
return NULL;
}
buf[strcspn(buf, "\r\n")] = '\0';
pass = xstrdup(buf);
memset(buf, 0, sizeof(buf));
explicit_bzero(buf, sizeof(buf));
return pass;
}
@ -162,7 +162,7 @@ read_passphrase(const char *prompt, int flags)
}
ret = xstrdup(buf);
memset(buf, 'x', sizeof buf);
explicit_bzero(buf, sizeof(buf));
return ret;
}

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.67 2013/12/06 13:52:46 markus Exp $
# $OpenBSD: Makefile,v 1.68 2014/01/25 04:35:32 dtucker Exp $
REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec
tests: $(REGRESS_TARGETS)
@ -65,6 +65,7 @@ LTESTS= connect \
forward-control \
integrity \
krl
# dhgex \
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
#INTEROP_TESTS+=ssh-com ssh-com-client ssh-com-keygen ssh-com-sftp

View File

@ -1,4 +1,4 @@
# $OpenBSD: agent-ptrace.sh,v 1.1 2002/12/09 15:38:30 markus Exp $
# $OpenBSD: agent-ptrace.sh,v 1.2 2014/02/27 21:21:25 djm Exp $
# Placed in the Public Domain.
tid="disallow agent ptrace attach"

View File

@ -1,4 +1,4 @@
# $OpenBSD: agent.sh,v 1.9 2013/12/06 13:52:46 markus Exp $
# $OpenBSD: agent.sh,v 1.10 2014/02/27 21:21:25 djm Exp $
# Placed in the Public Domain.
tid="simple agent test"

View File

@ -1,4 +1,4 @@
# $OpenBSD: cert-hostkey.sh,v 1.8 2013/12/06 13:52:46 markus Exp $
# $OpenBSD: cert-hostkey.sh,v 1.9 2014/01/26 10:22:10 djm Exp $
# Placed in the Public Domain.
tid="certified host keys"

54
regress/dhgex.sh Executable file
View File

@ -0,0 +1,54 @@
# $OpenBSD: dhgex.sh,v 1.1 2014/01/25 04:35:32 dtucker Exp $
# Placed in the Public Domain.
tid="dhgex"
LOG=${TEST_SSH_LOGFILE}
rm -f ${LOG}
kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange`
ssh_test_dhgex()
{
bits="$1"; shift
cipher="$1"; shift
kex="$1"; shift
rm -f ${LOG}
opts="-oKexAlgorithms=$kex -oCiphers=$cipher"
groupsz="1024<$bits<8192"
verbose "$tid bits $bits $kex $cipher"
${SSH} ${opts} $@ -vvv -F ${OBJ}/ssh_proxy somehost true
if [ $? -ne 0 ]; then
fail "ssh failed ($@)"
fi
# check what we request
grep "SSH2_MSG_KEX_DH_GEX_REQUEST($groupsz) sent" ${LOG} >/dev/null
if [ $? != 0 ]; then
got=`egrep "SSH2_MSG_KEX_DH_GEX_REQUEST(.*) sent" ${LOG}`
fail "$tid unexpected GEX sizes, expected $groupsz, got $got"
fi
# check what we got (depends on contents of system moduli file)
gotbits="`awk '/bits set:/{print $4}' ${LOG} | head -1 | cut -f2 -d/`"
if [ "$gotbits" -lt "$bits" ]; then
fatal "$tid expected $bits bit group, got $gotbits"
fi
}
check()
{
bits="$1"; shift
for c in $@; do
for k in $kexs; do
ssh_test_dhgex $bits $c $k
done
done
}
#check 2048 3des-cbc
check 3072 `${SSH} -Q cipher | grep 128`
check 3072 arcfour blowfish-cbc
check 7680 `${SSH} -Q cipher | grep 192`
check 8192 `${SSH} -Q cipher | grep 256`
check 8192 rijndael-cbc@lysator.liu.se chacha20-poly1305@openssh.com

View File

@ -1,3 +1,4 @@
# $OpenBSD: host-expand.sh,v 1.3 2014/02/27 23:17:41 djm Exp $
# Placed in the Public Domain.
tid="expand %h and %n"

View File

@ -1,9 +1,11 @@
# $OpenBSD: login-timeout.sh,v 1.5 2013/05/17 10:23:52 dtucker Exp $
# $OpenBSD: login-timeout.sh,v 1.6 2014/02/27 20:04:16 djm Exp $
# Placed in the Public Domain.
tid="connect after login grace timeout"
trace "test login grace with privsep"
cp $OBJ/sshd_config $OBJ/sshd_config.orig
grep -vi LoginGraceTime $OBJ/sshd_config.orig > $OBJ/sshd_config
echo "LoginGraceTime 10s" >> $OBJ/sshd_config
echo "MaxStartups 1" >> $OBJ/sshd_config
start_sshd

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $OpenBSD: scp-ssh-wrapper.sh,v 1.2 2005/12/14 04:36:39 dtucker Exp $
# $OpenBSD: scp-ssh-wrapper.sh,v 1.3 2014/01/26 10:49:17 djm Exp $
# Placed in the Public Domain.
printname () {

View File

@ -1,4 +1,4 @@
# $OpenBSD: scp.sh,v 1.9 2013/05/17 10:35:43 dtucker Exp $
# $OpenBSD: scp.sh,v 1.10 2014/01/26 10:49:17 djm Exp $
# Placed in the Public Domain.
tid="scp"

View File

@ -23,6 +23,7 @@
# include <sys/statvfs.h>
#endif
#include <stdio.h>
#include <string.h>
#include <errno.h>
void

View File

@ -1,4 +1,4 @@
# $OpenBSD: sftp-chroot.sh,v 1.2 2013/05/17 04:29:14 dtucker Exp $
# $OpenBSD: sftp-chroot.sh,v 1.4 2014/01/20 00:00:30 dtucker Exp $
# Placed in the Public Domain.
tid="sftp in chroot"
@ -18,7 +18,8 @@ $SUDO sh -c "echo mekmitastdigoat > $PRIVDATA" || \
start_sshd -oChrootDirectory=$CHROOT -oForceCommand="internal-sftp -d /"
verbose "test $tid: get"
${SFTP} -qS "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY || \
${SFTP} -S "$SSH" -F $OBJ/ssh_config host:/${FILENAME} $COPY \
>>$TEST_REGRESS_LOGFILE 2>&1 || \
fatal "Fetch ${FILENAME} failed"
cmp $PRIVDATA $COPY || fail "$PRIVDATA $COPY differ"

10
rsa.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: rsa.c,v 1.30 2013/05/17 00:13:14 djm Exp $ */
/* $OpenBSD: rsa.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -94,8 +94,8 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
if (BN_bin2bn(outbuf, len, out) == NULL)
fatal("rsa_public_encrypt: BN_bin2bn failed");
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
explicit_bzero(outbuf, olen);
explicit_bzero(inbuf, ilen);
free(outbuf);
free(inbuf);
}
@ -120,8 +120,8 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
if (BN_bin2bn(outbuf, len, out) == NULL)
fatal("rsa_private_decrypt: BN_bin2bn failed");
}
memset(outbuf, 0, olen);
memset(inbuf, 0, ilen);
explicit_bzero(outbuf, olen);
explicit_bzero(inbuf, ilen);
free(outbuf);
free(inbuf);
return len;

View File

@ -94,10 +94,12 @@ ssh_sandbox_child(struct ssh_sandbox *box)
fatal("can't limit stderr: %m");
cap_rights_init(&rights, CAP_READ, CAP_WRITE);
if (cap_rights_limit(box->monitor->m_recvfd, &rights) == -1)
if (cap_rights_limit(box->monitor->m_recvfd, &rights) < 0 &&
errno != ENOSYS)
fatal("%s: failed to limit the network socket", __func__);
cap_rights_init(&rights, CAP_WRITE);
if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) == -1)
if (cap_rights_limit(box->monitor->m_log_sendfd, &rights) < 0 &&
errno != ENOSYS)
fatal("%s: failed to limit the logging socket", __func__);
if (cap_enter() < 0 && errno != ENOSYS)
fatal("%s: failed to enter capability mode", __func__);

View File

@ -98,6 +98,9 @@ static const struct sock_filter preauth_insns[] = {
SC_ALLOW(read),
SC_ALLOW(write),
SC_ALLOW(close),
#ifdef __NR_shutdown /* not defined on archs that go via socketcall(2) */
SC_ALLOW(shutdown),
#endif
SC_ALLOW(brk),
SC_ALLOW(poll),
#ifdef __NR__newselect

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sandbox-systrace.c,v 1.7 2013/06/01 13:15:52 dtucker Exp $ */
/* $OpenBSD: sandbox-systrace.c,v 1.9 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@ -66,6 +66,7 @@ static const struct sandbox_policy preauth_policy[] = {
{ SYS_munmap, SYSTR_POLICY_PERMIT },
{ SYS_read, SYSTR_POLICY_PERMIT },
{ SYS_select, SYSTR_POLICY_PERMIT },
{ SYS_shutdown, SYSTR_POLICY_PERMIT },
{ SYS_sigprocmask, SYSTR_POLICY_PERMIT },
{ SYS_write, SYSTR_POLICY_PERMIT },
{ -1, -1 }
@ -141,7 +142,7 @@ ssh_sandbox_parent(struct ssh_sandbox *box, pid_t child_pid,
box->systrace_fd, child_pid, strerror(errno));
/* Allocate and assign policy */
bzero(&policy, sizeof(policy));
memset(&policy, 0, sizeof(policy));
policy.strp_op = SYSTR_POLICY_NEW;
policy.strp_maxents = SYS_MAXSYSCALL;
if (ioctl(box->systrace_fd, STRIOCPOLICY, &policy) == -1)

668
schnorr.c
View File

@ -1,668 +0,0 @@
/* $OpenBSD: schnorr.c,v 1.9 2014/01/09 23:20:00 djm Exp $ */
/*
* Copyright (c) 2008 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Implementation of Schnorr signatures / zero-knowledge proofs, based on
* description in:
*
* F. Hao, P. Ryan, "Password Authenticated Key Exchange by Juggling",
* 16th Workshop on Security Protocols, Cambridge, April 2008
*
* http://grouper.ieee.org/groups/1363/Research/contributions/hao-ryan-2008.pdf
*/
#include "includes.h"
#include <sys/types.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include "xmalloc.h"
#include "buffer.h"
#include "log.h"
#include "schnorr.h"
#include "digest.h"
#include "openbsd-compat/openssl-compat.h"
/* #define SCHNORR_DEBUG */ /* Privacy-violating debugging */
/* #define SCHNORR_MAIN */ /* Include main() selftest */
#ifndef SCHNORR_DEBUG
# define SCHNORR_DEBUG_BN(a)
# define SCHNORR_DEBUG_BUF(a)
#else
# define SCHNORR_DEBUG_BN(a) debug3_bn a
# define SCHNORR_DEBUG_BUF(a) debug3_buf a
#endif /* SCHNORR_DEBUG */
/*
* Calculate hash component of Schnorr signature H(g || g^v || g^x || id)
* using the hash function defined by "hash_alg". Returns signature as
* bignum or NULL on error.
*/
static BIGNUM *
schnorr_hash(const BIGNUM *p, const BIGNUM *q, const BIGNUM *g,
int hash_alg, const BIGNUM *g_v, const BIGNUM *g_x,
const u_char *id, u_int idlen)
{
u_char *digest;
u_int digest_len;
BIGNUM *h;
Buffer b;
int success = -1;
if ((h = BN_new()) == NULL) {
error("%s: BN_new", __func__);
return NULL;
}
buffer_init(&b);
/* h = H(g || p || q || g^v || g^x || id) */
buffer_put_bignum2(&b, g);
buffer_put_bignum2(&b, p);
buffer_put_bignum2(&b, q);
buffer_put_bignum2(&b, g_v);
buffer_put_bignum2(&b, g_x);
buffer_put_string(&b, id, idlen);
SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
"%s: hashblob", __func__));
if (hash_buffer(buffer_ptr(&b), buffer_len(&b), hash_alg,
&digest, &digest_len) != 0) {
error("%s: hash_buffer", __func__);
goto out;
}
if (BN_bin2bn(digest, (int)digest_len, h) == NULL) {
error("%s: BN_bin2bn", __func__);
goto out;
}
success = 0;
SCHNORR_DEBUG_BN((h, "%s: h = ", __func__));
out:
buffer_free(&b);
bzero(digest, digest_len);
free(digest);
digest_len = 0;
if (success == 0)
return h;
BN_clear_free(h);
return NULL;
}
/*
* Generate Schnorr signature to prove knowledge of private value 'x' used
* in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
* using the hash function "hash_alg".
* 'idlen' bytes from 'id' will be included in the signature hash as an anti-
* replay salt.
*
* On success, 0 is returned. The signature values are returned as *e_p
* (g^v mod p) and *r_p (v - xh mod q). The caller must free these values.
* On failure, -1 is returned.
*/
int
schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
int hash_alg, const BIGNUM *x, const BIGNUM *g_x,
const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p)
{
int success = -1;
BIGNUM *h, *tmp, *v, *g_v, *r;
BN_CTX *bn_ctx;
SCHNORR_DEBUG_BN((x, "%s: x = ", __func__));
SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
/* Avoid degenerate cases: g^0 yields a spoofable signature */
if (BN_cmp(g_x, BN_value_one()) <= 0) {
error("%s: g_x < 1", __func__);
return -1;
}
if (BN_cmp(g_x, grp_p) >= 0) {
error("%s: g_x > g", __func__);
return -1;
}
h = g_v = r = tmp = v = NULL;
if ((bn_ctx = BN_CTX_new()) == NULL) {
error("%s: BN_CTX_new", __func__);
goto out;
}
if ((g_v = BN_new()) == NULL ||
(r = BN_new()) == NULL ||
(tmp = BN_new()) == NULL) {
error("%s: BN_new", __func__);
goto out;
}
/*
* v must be a random element of Zq, so 1 <= v < q
* we also exclude v = 1, since g^1 looks dangerous
*/
if ((v = bn_rand_range_gt_one(grp_p)) == NULL) {
error("%s: bn_rand_range2", __func__);
goto out;
}
SCHNORR_DEBUG_BN((v, "%s: v = ", __func__));
/* g_v = g^v mod p */
if (BN_mod_exp(g_v, grp_g, v, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_exp (g^v mod p)", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_v, "%s: g_v = ", __func__));
/* h = H(g || g^v || g^x || id) */
if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, g_v, g_x,
id, idlen)) == NULL) {
error("%s: schnorr_hash failed", __func__);
goto out;
}
/* r = v - xh mod q */
if (BN_mod_mul(tmp, x, h, grp_q, bn_ctx) == -1) {
error("%s: BN_mod_mul (tmp = xv mod q)", __func__);
goto out;
}
if (BN_mod_sub(r, v, tmp, grp_q, bn_ctx) == -1) {
error("%s: BN_mod_mul (r = v - tmp)", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_v, "%s: e = ", __func__));
SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
*e_p = g_v;
*r_p = r;
success = 0;
out:
BN_CTX_free(bn_ctx);
if (h != NULL)
BN_clear_free(h);
if (v != NULL)
BN_clear_free(v);
BN_clear_free(tmp);
return success;
}
/*
* Generate Schnorr signature to prove knowledge of private value 'x' used
* in public exponent g^x, under group defined by 'grp_p', 'grp_q' and 'grp_g'
* using a SHA256 hash.
* 'idlen' bytes from 'id' will be included in the signature hash as an anti-
* replay salt.
* On success, 0 is returned and *siglen bytes of signature are returned in
* *sig (caller to free). Returns -1 on failure.
*/
int
schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
u_char **sig, u_int *siglen)
{
Buffer b;
BIGNUM *r, *e;
if (schnorr_sign(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256,
x, g_x, id, idlen, &r, &e) != 0)
return -1;
/* Signature is (e, r) */
buffer_init(&b);
/* XXX sigtype-hash as string? */
buffer_put_bignum2(&b, e);
buffer_put_bignum2(&b, r);
*siglen = buffer_len(&b);
*sig = xmalloc(*siglen);
memcpy(*sig, buffer_ptr(&b), *siglen);
SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
"%s: sigblob", __func__));
buffer_free(&b);
BN_clear_free(r);
BN_clear_free(e);
return 0;
}
/*
* Verify Schnorr signature { r (v - xh mod q), e (g^v mod p) } against
* public exponent g_x (g^x) under group defined by 'grp_p', 'grp_q' and
* 'grp_g' using hash "hash_alg".
* Signature hash will be salted with 'idlen' bytes from 'id'.
* Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
*/
int
schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen,
const BIGNUM *r, const BIGNUM *e)
{
int success = -1;
BIGNUM *h = NULL, *g_xh = NULL, *g_r = NULL, *gx_q = NULL;
BIGNUM *expected = NULL;
BN_CTX *bn_ctx;
SCHNORR_DEBUG_BN((g_x, "%s: g_x = ", __func__));
/* Avoid degenerate cases: g^0 yields a spoofable signature */
if (BN_cmp(g_x, BN_value_one()) <= 0) {
error("%s: g_x <= 1", __func__);
return -1;
}
if (BN_cmp(g_x, grp_p) >= 0) {
error("%s: g_x >= p", __func__);
return -1;
}
h = g_xh = g_r = expected = NULL;
if ((bn_ctx = BN_CTX_new()) == NULL) {
error("%s: BN_CTX_new", __func__);
goto out;
}
if ((g_xh = BN_new()) == NULL ||
(g_r = BN_new()) == NULL ||
(gx_q = BN_new()) == NULL ||
(expected = BN_new()) == NULL) {
error("%s: BN_new", __func__);
goto out;
}
SCHNORR_DEBUG_BN((e, "%s: e = ", __func__));
SCHNORR_DEBUG_BN((r, "%s: r = ", __func__));
/* gx_q = (g^x)^q must === 1 mod p */
if (BN_mod_exp(gx_q, g_x, grp_q, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_exp (g_x^q mod p)", __func__);
goto out;
}
if (BN_cmp(gx_q, BN_value_one()) != 0) {
error("%s: Invalid signature (g^x)^q != 1 mod p", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
/* h = H(g || g^v || g^x || id) */
if ((h = schnorr_hash(grp_p, grp_q, grp_g, hash_alg, e, g_x,
id, idlen)) == NULL) {
error("%s: schnorr_hash failed", __func__);
goto out;
}
/* g_xh = (g^x)^h */
if (BN_mod_exp(g_xh, g_x, h, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_exp (g_x^h mod p)", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_xh, "%s: g_xh = ", __func__));
/* g_r = g^r */
if (BN_mod_exp(g_r, grp_g, r, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_exp (g_x^h mod p)", __func__);
goto out;
}
SCHNORR_DEBUG_BN((g_r, "%s: g_r = ", __func__));
/* expected = g^r * g_xh */
if (BN_mod_mul(expected, g_r, g_xh, grp_p, bn_ctx) == -1) {
error("%s: BN_mod_mul (expected = g_r mod p)", __func__);
goto out;
}
SCHNORR_DEBUG_BN((expected, "%s: expected = ", __func__));
/* Check e == expected */
success = BN_cmp(expected, e) == 0;
out:
BN_CTX_free(bn_ctx);
if (h != NULL)
BN_clear_free(h);
if (gx_q != NULL)
BN_clear_free(gx_q);
if (g_xh != NULL)
BN_clear_free(g_xh);
if (g_r != NULL)
BN_clear_free(g_r);
if (expected != NULL)
BN_clear_free(expected);
return success;
}
/*
* Verify Schnorr signature 'sig' of length 'siglen' against public exponent
* g_x (g^x) under group defined by 'grp_p', 'grp_q' and 'grp_g' using a
* SHA256 hash.
* Signature hash will be salted with 'idlen' bytes from 'id'.
* Returns -1 on failure, 0 on incorrect signature or 1 on matching signature.
*/
int
schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q,
const BIGNUM *grp_g,
const BIGNUM *g_x, const u_char *id, u_int idlen,
const u_char *sig, u_int siglen)
{
Buffer b;
int ret = -1;
u_int rlen;
BIGNUM *r, *e;
e = r = NULL;
if ((e = BN_new()) == NULL ||
(r = BN_new()) == NULL) {
error("%s: BN_new", __func__);
goto out;
}
/* Extract g^v and r from signature blob */
buffer_init(&b);
buffer_append(&b, sig, siglen);
SCHNORR_DEBUG_BUF((buffer_ptr(&b), buffer_len(&b),
"%s: sigblob", __func__));
buffer_get_bignum2(&b, e);
buffer_get_bignum2(&b, r);
rlen = buffer_len(&b);
buffer_free(&b);
if (rlen != 0) {
error("%s: remaining bytes in signature %d", __func__, rlen);
goto out;
}
ret = schnorr_verify(grp_p, grp_q, grp_g, SSH_DIGEST_SHA256,
g_x, id, idlen, r, e);
out:
BN_clear_free(e);
BN_clear_free(r);
return ret;
}
/* Helper functions */
/*
* Generate uniformly distributed random number in range (1, high).
* Return number on success, NULL on failure.
*/
BIGNUM *
bn_rand_range_gt_one(const BIGNUM *high)
{
BIGNUM *r, *tmp;
int success = -1;
if ((tmp = BN_new()) == NULL) {
error("%s: BN_new", __func__);
return NULL;
}
if ((r = BN_new()) == NULL) {
error("%s: BN_new failed", __func__);
goto out;
}
if (BN_set_word(tmp, 2) != 1) {
error("%s: BN_set_word(tmp, 2)", __func__);
goto out;
}
if (BN_sub(tmp, high, tmp) == -1) {
error("%s: BN_sub failed (tmp = high - 2)", __func__);
goto out;
}
if (BN_rand_range(r, tmp) == -1) {
error("%s: BN_rand_range failed", __func__);
goto out;
}
if (BN_set_word(tmp, 2) != 1) {
error("%s: BN_set_word(tmp, 2)", __func__);
goto out;
}
if (BN_add(r, r, tmp) == -1) {
error("%s: BN_add failed (r = r + 2)", __func__);
goto out;
}
success = 0;
out:
BN_clear_free(tmp);
if (success == 0)
return r;
BN_clear_free(r);
return NULL;
}
/* XXX convert all callers of this to use ssh_digest_memory() directly */
/*
* Hash contents of buffer 'b' with hash 'md'. Returns 0 on success,
* with digest via 'digestp' (caller to free) and length via 'lenp'.
* Returns -1 on failure.
*/
int
hash_buffer(const u_char *buf, u_int len, int hash_alg,
u_char **digestp, u_int *lenp)
{
u_char digest[SSH_DIGEST_MAX_LENGTH];
u_int digest_len = ssh_digest_bytes(hash_alg);
if (digest_len == 0) {
error("%s: invalid hash", __func__);
return -1;
}
if (ssh_digest_memory(hash_alg, buf, len, digest, digest_len) != 0) {
error("%s: digest_memory failed", __func__);
return -1;
}
*digestp = xmalloc(digest_len);
*lenp = digest_len;
memcpy(*digestp, digest, *lenp);
bzero(digest, sizeof(digest));
digest_len = 0;
return 0;
}
/* print formatted string followed by bignum */
void
debug3_bn(const BIGNUM *n, const char *fmt, ...)
{
char *out, *h;
va_list args;
int ret;
out = NULL;
va_start(args, fmt);
ret = vasprintf(&out, fmt, args);
va_end(args);
if (ret == -1 || out == NULL)
fatal("%s: vasprintf failed", __func__);
if (n == NULL)
debug3("%s(null)", out);
else {
h = BN_bn2hex(n);
debug3("%s0x%s", out, h);
free(h);
}
free(out);
}
/* print formatted string followed by buffer contents in hex */
void
debug3_buf(const u_char *buf, u_int len, const char *fmt, ...)
{
char *out, h[65];
u_int i, j;
va_list args;
int ret;
out = NULL;
va_start(args, fmt);
ret = vasprintf(&out, fmt, args);
va_end(args);
if (ret == -1 || out == NULL)
fatal("%s: vasprintf failed", __func__);
debug3("%s length %u%s", out, len, buf == NULL ? " (null)" : "");
free(out);
if (buf == NULL)
return;
*h = '\0';
for (i = j = 0; i < len; i++) {
snprintf(h + j, sizeof(h) - j, "%02x", buf[i]);
j += 2;
if (j >= sizeof(h) - 1 || i == len - 1) {
debug3(" %s", h);
*h = '\0';
j = 0;
}
}
}
/*
* Construct a MODP group from hex strings p (which must be a safe
* prime) and g, automatically calculating subgroup q as (p / 2)
*/
struct modp_group *
modp_group_from_g_and_safe_p(const char *grp_g, const char *grp_p)
{
struct modp_group *ret;
ret = xcalloc(1, sizeof(*ret));
ret->p = ret->q = ret->g = NULL;
if (BN_hex2bn(&ret->p, grp_p) == 0 ||
BN_hex2bn(&ret->g, grp_g) == 0)
fatal("%s: BN_hex2bn", __func__);
/* Subgroup order is p/2 (p is a safe prime) */
if ((ret->q = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
if (BN_rshift1(ret->q, ret->p) != 1)
fatal("%s: BN_rshift1", __func__);
return ret;
}
void
modp_group_free(struct modp_group *grp)
{
if (grp->g != NULL)
BN_clear_free(grp->g);
if (grp->p != NULL)
BN_clear_free(grp->p);
if (grp->q != NULL)
BN_clear_free(grp->q);
bzero(grp, sizeof(*grp));
free(grp);
}
/* main() function for self-test */
#ifdef SCHNORR_MAIN
static void
schnorr_selftest_one(const BIGNUM *grp_p, const BIGNUM *grp_q,
const BIGNUM *grp_g, const BIGNUM *x)
{
BIGNUM *g_x;
u_char *sig;
u_int siglen;
BN_CTX *bn_ctx;
if ((bn_ctx = BN_CTX_new()) == NULL)
fatal("%s: BN_CTX_new", __func__);
if ((g_x = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
if (BN_mod_exp(g_x, grp_g, x, grp_p, bn_ctx) == -1)
fatal("%s: g_x", __func__);
if (schnorr_sign_buf(grp_p, grp_q, grp_g, x, g_x, "junk", 4,
&sig, &siglen))
fatal("%s: schnorr_sign", __func__);
if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
sig, siglen) != 1)
fatal("%s: verify fail", __func__);
if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "JUNK", 4,
sig, siglen) != 0)
fatal("%s: verify should have failed (bad ID)", __func__);
sig[4] ^= 1;
if (schnorr_verify_buf(grp_p, grp_q, grp_g, g_x, "junk", 4,
sig, siglen) != 0)
fatal("%s: verify should have failed (bit error)", __func__);
free(sig);
BN_free(g_x);
BN_CTX_free(bn_ctx);
}
static void
schnorr_selftest(void)
{
BIGNUM *x;
struct modp_group *grp;
u_int i;
char *hh;
grp = jpake_default_group();
if ((x = BN_new()) == NULL)
fatal("%s: BN_new", __func__);
SCHNORR_DEBUG_BN((grp->p, "%s: grp->p = ", __func__));
SCHNORR_DEBUG_BN((grp->q, "%s: grp->q = ", __func__));
SCHNORR_DEBUG_BN((grp->g, "%s: grp->g = ", __func__));
/* [1, 20) */
for (i = 1; i < 20; i++) {
printf("x = %u\n", i);
fflush(stdout);
if (BN_set_word(x, i) != 1)
fatal("%s: set x word", __func__);
schnorr_selftest_one(grp->p, grp->q, grp->g, x);
}
/* 100 x random [0, p) */
for (i = 0; i < 100; i++) {
if (BN_rand_range(x, grp->p) != 1)
fatal("%s: BN_rand_range", __func__);
hh = BN_bn2hex(x);
printf("x = (random) 0x%s\n", hh);
free(hh);
fflush(stdout);
schnorr_selftest_one(grp->p, grp->q, grp->g, x);
}
/* [q-20, q) */
if (BN_set_word(x, 20) != 1)
fatal("%s: BN_set_word (x = 20)", __func__);
if (BN_sub(x, grp->q, x) != 1)
fatal("%s: BN_sub (q - x)", __func__);
for (i = 0; i < 19; i++) {
hh = BN_bn2hex(x);
printf("x = (q - %d) 0x%s\n", 20 - i, hh);
free(hh);
fflush(stdout);
schnorr_selftest_one(grp->p, grp->q, grp->g, x);
if (BN_add(x, x, BN_value_one()) != 1)
fatal("%s: BN_add (x + 1)", __func__);
}
BN_free(x);
}
int
main(int argc, char **argv)
{
log_init(argv[0], SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_USER, 1);
schnorr_selftest();
return 0;
}
#endif

View File

@ -1,60 +0,0 @@
/* $OpenBSD: schnorr.h,v 1.2 2014/01/09 23:20:00 djm Exp $ */
/*
* Copyright (c) 2009 Damien Miller. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SCHNORR_H
#define SCHNORR_H
#include <sys/types.h>
#include <openssl/bn.h>
struct modp_group {
BIGNUM *p, *q, *g;
};
BIGNUM *bn_rand_range_gt_one(const BIGNUM *high);
int hash_buffer(const u_char *, u_int, int, u_char **, u_int *);
void debug3_bn(const BIGNUM *, const char *, ...)
__attribute__((__nonnull__ (2)))
__attribute__((format(printf, 2, 3)));
void debug3_buf(const u_char *, u_int, const char *, ...)
__attribute__((__nonnull__ (3)))
__attribute__((format(printf, 3, 4)));
struct modp_group *modp_group_from_g_and_safe_p(const char *, const char *);
void modp_group_free(struct modp_group *);
/* Signature and verification functions */
int
schnorr_sign(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
int hash_alg, const BIGNUM *x, const BIGNUM *g_x,
const u_char *id, u_int idlen, BIGNUM **r_p, BIGNUM **e_p);
int
schnorr_sign_buf(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
const BIGNUM *x, const BIGNUM *g_x, const u_char *id, u_int idlen,
u_char **sig, u_int *siglen);
int
schnorr_verify(const BIGNUM *grp_p, const BIGNUM *grp_q, const BIGNUM *grp_g,
int hash_alg, const BIGNUM *g_x, const u_char *id, u_int idlen,
const BIGNUM *r, const BIGNUM *e);
int
schnorr_verify_buf(const BIGNUM *grp_p, const BIGNUM *grp_q,
const BIGNUM *grp_g,
const BIGNUM *g_x, const u_char *id, u_int idlen,
const u_char *sig, u_int siglen);
#endif /* JPAKE_H */

2
scp.0
View File

@ -160,4 +160,4 @@ AUTHORS
Timo Rinne <tri@iki.fi>
Tatu Ylonen <ylo@cs.hut.fi>
OpenBSD 5.4 October 20, 2013 OpenBSD 5.4
OpenBSD 5.5 October 20, 2013 OpenBSD 5.5

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.248 2013/12/06 13:39:49 markus Exp $ */
/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -147,7 +147,6 @@ initialize_server_options(ServerOptions *options)
options->chroot_directory = NULL;
options->authorized_keys_command = NULL;
options->authorized_keys_command_user = NULL;
options->zero_knowledge_password_authentication = -1;
options->revoked_keys_file = NULL;
options->trusted_user_ca_keys = NULL;
options->authorized_principals_file = NULL;
@ -295,8 +294,6 @@ fill_default_server_options(ServerOptions *options)
}
if (options->permit_tun == -1)
options->permit_tun = SSH_TUNMODE_NO;
if (options->zero_knowledge_password_authentication == -1)
options->zero_knowledge_password_authentication = 0;
if (options->ip_qos_interactive == -1)
options->ip_qos_interactive = IPTOS_LOWDELAY;
if (options->ip_qos_bulk == -1)
@ -346,7 +343,7 @@ typedef enum {
sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
sUsePrivilegeSeparation, sAllowAgentForwarding,
sZeroKnowledgePasswordAuthentication, sHostCertificate,
sHostCertificate,
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
sKexAlgorithms, sIPQoS, sVersionAddendum,
sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
@ -418,11 +415,6 @@ static struct {
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
#ifdef JPAKE
{ "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
#else
{ "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
#endif
{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
@ -1102,10 +1094,6 @@ process_server_config_line(ServerOptions *options, char *line,
intptr = &options->password_authentication;
goto parse_flag;
case sZeroKnowledgePasswordAuthentication:
intptr = &options->zero_knowledge_password_authentication;
goto parse_flag;
case sKbdInteractiveAuthentication:
intptr = &options->kbd_interactive_authentication;
goto parse_flag;
@ -1767,7 +1755,6 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
M_CP_INTOPT(hostbased_authentication);
M_CP_INTOPT(hostbased_uses_name_from_packet_only);
M_CP_INTOPT(kbd_interactive_authentication);
M_CP_INTOPT(zero_knowledge_password_authentication);
M_CP_INTOPT(permit_root_login);
M_CP_INTOPT(permit_empty_passwd);
@ -2009,10 +1996,6 @@ dump_config(ServerOptions *o)
#ifdef GSSAPI
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
#endif
#ifdef JPAKE
dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
o->zero_knowledge_password_authentication);
#endif
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
dump_cfg_fmtint(sKbdInteractiveAuthentication,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.111 2013/12/05 01:16:41 djm Exp $ */
/* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -117,8 +117,6 @@ typedef struct {
* authentication. */
int kbd_interactive_authentication; /* If true, permit */
int challenge_response_authentication;
int zero_knowledge_password_authentication;
/* If true, permit jpake auth */
int permit_empty_passwd; /* If false, do not permit empty
* passwords. */
int permit_user_env; /* If true, read ~/.ssh/environment */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.169 2013/12/19 00:19:12 dtucker Exp $ */
/* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -920,7 +920,7 @@ server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stdin_buffer, data, data_len);
memset(data, 0, data_len);
explicit_bzero(data, data_len);
free(data);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.269 2014/01/18 09:36:26 dtucker Exp $ */
/* $OpenBSD: session.c,v 1.270 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
@ -978,6 +978,11 @@ child_set_env(char ***envp, u_int *envsizep, const char *name,
u_int envsize;
u_int i, namelen;
if (strchr(name, '=') != NULL) {
error("Invalid environment variable \"%.100s\"", name);
return;
}
/*
* If we're passed an uninitialized list, allocate a single null
* entry before continuing.
@ -1889,7 +1894,7 @@ session_unused(int id)
fatal("%s: insane session id %d (max %d nalloc %d)",
__func__, id, options.max_sessions, sessions_nalloc);
}
bzero(&sessions[id], sizeof(*sessions));
memset(&sessions[id], 0, sizeof(*sessions));
sessions[id].self = id;
sessions[id].used = 0;
sessions[id].chanid = -1;
@ -2225,8 +2230,8 @@ session_env_req(Session *s)
char *name, *val;
u_int name_len, val_len, i;
name = packet_get_string(&name_len);
val = packet_get_string(&val_len);
name = packet_get_cstring(&name_len);
val = packet_get_cstring(&val_len);
packet_check_eom();
/* Don't set too many environment variables */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sftp-client.c,v 1.113 2014/01/17 00:21:06 djm Exp $ */
/* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@ -310,7 +310,7 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
SSH2_FXP_EXTENDED_REPLY, type);
}
bzero(st, sizeof(*st));
memset(st, 0, sizeof(*st));
st->f_bsize = buffer_get_int64(&msg);
st->f_frsize = buffer_get_int64(&msg);
st->f_blocks = buffer_get_int64(&msg);

View File

@ -92,4 +92,4 @@ HISTORY
AUTHORS
Markus Friedl <markus@openbsd.org>
OpenBSD 5.4 October 14, 2013 OpenBSD 5.4
OpenBSD 5.5 October 14, 2013 OpenBSD 5.5

2
sftp.0
View File

@ -367,4 +367,4 @@ SEE ALSO
T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
filexfer-00.txt, January 2001, work in progress material.
OpenBSD 5.4 October 20, 2013 OpenBSD 5.4
OpenBSD 5.5 October 20, 2013 OpenBSD 5.5

View File

@ -120,4 +120,4 @@ AUTHORS
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
OpenBSD 5.4 December 7, 2013 OpenBSD 5.4
OpenBSD 5.5 December 7, 2013 OpenBSD 5.5

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.108 2013/12/19 00:10:30 djm Exp $ */
/* $OpenBSD: ssh-add.c,v 1.109 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -90,7 +90,7 @@ static void
clear_pass(void)
{
if (pass) {
memset(pass, 0, strlen(pass));
explicit_bzero(pass, strlen(pass));
free(pass);
pass = NULL;
}
@ -366,7 +366,7 @@ lock_agent(AuthenticationConnection *ac, int lock)
fprintf(stderr, "Passwords do not match.\n");
passok = 0;
}
memset(p2, 0, strlen(p2));
explicit_bzero(p2, strlen(p2));
free(p2);
}
if (passok && ssh_lock_agent(ac, lock, p1)) {
@ -374,7 +374,7 @@ lock_agent(AuthenticationConnection *ac, int lock)
ret = 0;
} else
fprintf(stderr, "Failed to %slock agent.\n", lock ? "" : "un");
memset(p1, 0, strlen(p1));
explicit_bzero(p1, strlen(p1));
free(p1);
return (ret);
}

View File

@ -125,4 +125,4 @@ AUTHORS
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
OpenBSD 5.4 December 7, 2013 OpenBSD 5.4
OpenBSD 5.5 December 7, 2013 OpenBSD 5.5

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.181 2013/12/19 01:19:41 djm Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.183 2014/02/02 03:44:31 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -50,7 +50,6 @@
#include "openbsd-compat/sys-queue.h"
#include <openssl/evp.h>
#include <openssl/md5.h>
#include "openbsd-compat/openssl-compat.h"
#include <errno.h>
@ -75,6 +74,7 @@
#include "compat.h"
#include "log.h"
#include "misc.h"
#include "digest.h"
#ifdef ENABLE_PKCS11
#include "ssh-pkcs11.h"
@ -248,7 +248,7 @@ process_authentication_challenge1(SocketEntry *e)
Identity *id;
int i, len;
Buffer msg;
MD5_CTX md;
struct ssh_digest_ctx *md;
Key *key;
buffer_init(&msg);
@ -284,10 +284,12 @@ process_authentication_challenge1(SocketEntry *e)
}
memset(buf, 0, 32);
BN_bn2bin(challenge, buf + 32 - len);
MD5_Init(&md);
MD5_Update(&md, buf, 32);
MD5_Update(&md, session_id, 16);
MD5_Final(mdbuf, &md);
if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
ssh_digest_update(md, buf, 32) < 0 ||
ssh_digest_update(md, session_id, 16) < 0 ||
ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0)
fatal("%s: md5 failed", __func__);
ssh_digest_free(md);
/* Send the response. */
buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
@ -552,7 +554,7 @@ process_lock_agent(SocketEntry *e, int lock)
passwd = buffer_get_string(&e->request, NULL);
if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
locked = 0;
memset(lock_passwd, 0, strlen(lock_passwd));
explicit_bzero(lock_passwd, strlen(lock_passwd));
free(lock_passwd);
lock_passwd = NULL;
success = 1;
@ -561,7 +563,7 @@ process_lock_agent(SocketEntry *e, int lock)
lock_passwd = xstrdup(passwd);
success = 1;
}
memset(passwd, 0, strlen(passwd));
explicit_bzero(passwd, strlen(passwd));
free(passwd);
buffer_put_int(&e->output, 1);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-dss.c,v 1.30 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: ssh-dss.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
@ -65,7 +65,7 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
}
sig = DSA_do_sign(digest, dlen, key->dsa);
memset(digest, 'd', sizeof(digest));
explicit_bzero(digest, sizeof(digest));
if (sig == NULL) {
error("ssh_dss_sign: sign failed");
@ -79,7 +79,7 @@ ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp,
DSA_SIG_free(sig);
return -1;
}
memset(sigblob, 0, SIGBLOB_LEN);
explicit_bzero(sigblob, SIGBLOB_LEN);
BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen);
BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen);
DSA_SIG_free(sig);
@ -168,7 +168,7 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
fatal("%s: BN_bin2bn failed", __func__);
/* clean up */
memset(sigblob, 0, len);
explicit_bzero(sigblob, len);
free(sigblob);
/* sha1 the data */
@ -179,7 +179,7 @@ ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen,
}
ret = DSA_do_verify(digest, dlen, sig, key->dsa);
memset(digest, 'd', sizeof(digest));
explicit_bzero(digest, sizeof(digest));
DSA_SIG_free(sig);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ecdsa.c,v 1.8 2014/01/09 23:20:00 djm Exp $ */
/* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2010 Damien Miller. All rights reserved.
@ -72,7 +72,7 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
}
sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
memset(digest, 'd', sizeof(digest));
explicit_bzero(digest, sizeof(digest));
if (sig == NULL) {
error("%s: sign failed", __func__);
@ -140,9 +140,6 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
/* parse signature */
if ((sig = ECDSA_SIG_new()) == NULL)
fatal("%s: ECDSA_SIG_new failed", __func__);
if ((sig->r = BN_new()) == NULL ||
(sig->s = BN_new()) == NULL)
fatal("%s: BN_new failed", __func__);
buffer_init(&bb);
buffer_append(&bb, sigblob, len);
@ -153,7 +150,7 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
buffer_free(&bb);
/* clean up */
memset(sigblob, 0, len);
explicit_bzero(sigblob, len);
free(sigblob);
/* hash the data */
@ -169,7 +166,7 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
}
ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
memset(digest, 'd', sizeof(digest));
explicit_bzero(digest, sizeof(digest));
ECDSA_SIG_free(sig);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-ed25519.c,v 1.1 2013/12/06 13:39:49 markus Exp $ */
/* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */
/*
* Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
*
@ -21,6 +21,7 @@
#include "crypto_api.h"
#include <limits.h>
#include <string.h>
#include <stdarg.h>
@ -45,6 +46,11 @@ ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp,
error("%s: no ED25519 key", __func__);
return -1;
}
if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) {
error("%s: datalen %u too long", __func__, datalen);
return -1;
}
smlen = slen = datalen + crypto_sign_ed25519_BYTES;
sig = xmalloc(slen);
@ -66,7 +72,7 @@ ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp,
memcpy(*sigp, buffer_ptr(&b), len);
}
buffer_free(&b);
memset(sig, 's', slen);
explicit_bzero(sig, slen);
free(sig);
return 0;
@ -130,9 +136,9 @@ ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen,
}
/* XXX compare 'm' and 'data' ? */
memset(sigblob, 's', len);
memset(sm, 'S', smlen);
memset(m, 'm', smlen); /* NB. mlen may be invalid if ret != 0 */
explicit_bzero(sigblob, len);
explicit_bzero(sm, smlen);
explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */
free(sigblob);
free(sm);
free(m);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-gss.h,v 1.10 2007/06/12 08:20:00 djm Exp $ */
/* $OpenBSD: ssh-gss.h,v 1.11 2014/02/26 20:28:44 djm Exp $ */
/*
* Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
*
@ -104,6 +104,8 @@ void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
void ssh_gssapi_set_oid(Gssctxt *, gss_OID);
void ssh_gssapi_supported_oids(gss_OID_set *);
ssh_gssapi_mech *ssh_gssapi_get_ctype(Gssctxt *);
void ssh_gssapi_prepare_supported_oids(void);
OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *);
OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *);
OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int,

View File

@ -4,7 +4,7 @@ NAME
ssh-keygen - authentication key generation, management and conversion
SYNOPSIS
ssh-keygen [-q] [-b bits] -t type [-N new_passphrase] [-C comment]
ssh-keygen [-q] [-b bits] [-t type] [-N new_passphrase] [-C comment]
[-f output_keyfile]
ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
ssh-keygen -i [-m key_format] [-f input_keyfile]
@ -559,4 +559,4 @@ AUTHORS
created OpenSSH. Markus Friedl contributed the support for SSH protocol
versions 1.5 and 2.0.
OpenBSD 5.4 December 21, 2013 OpenBSD 5.4
OpenBSD 5.5 February 5, 2014 OpenBSD 5.5

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.119 2013/12/21 07:10:47 tedu Exp $
.\" $OpenBSD: ssh-keygen.1,v 1.120 2014/02/05 20:13:25 naddy Exp $
.\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd $Mdocdate: December 21 2013 $
.Dd $Mdocdate: February 5 2014 $
.Dt SSH-KEYGEN 1
.Os
.Sh NAME
@ -46,7 +46,7 @@
.Nm ssh-keygen
.Op Fl q
.Op Fl b Ar bits
.Fl t Ar type
.Op Fl t Ar type
.Op Fl N Ar new_passphrase
.Op Fl C Ar comment
.Op Fl f Ar output_keyfile

Some files were not shown because too many files have changed in this diff Show More