--- channels.c Wed Jun 13 12:18:05 2001 +++ channels.new.c Fri Oct 5 18:04:02 2001 @@ -27,6 +27,32 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -61,7 +87,8 @@ #include "canohost.h" #include "key.h" #include "authfd.h" - +#include "servconf.h" +#include "readconf.h" /* Maximum number of fake X11 displays to try. */ #define MAX_DISPLAYS 1000 @@ -1193,15 +1220,19 @@ /* If there is data to send to the connection, enqueue some of it now. */ +/* + * SD Mod: add arguments bogus_send_count and use_steno_timing_manipulation + * to channel_output_poll. +*/ void -channel_output_poll() +channel_output_poll(int *bogus_send_count, int use_steno_timing_manipulation) { int len, i; Channel *c; for (i = 0; i < channels_alloc; i++) { c = &channels[i]; - + /* We are only interested in channels that can have buffered incoming data. */ if (compat13) { if (c->type != SSH_CHANNEL_OPEN && @@ -1214,7 +1245,7 @@ if (compat20 && (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { /* XXX is this true? */ - debug2("channel %d: no data after CLOSE", c->self); + debug2("channel %d: no data after CLOSE", c->self); continue; } @@ -1243,11 +1274,49 @@ SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA); packet_put_int(c->remote_id); packet_put_string(buffer_ptr(&c->input), len); + /* + * Begin SD Mod: if using SSH2 and it is + * desired to use timing manipulation, reset + * counter since len > 0 implies packet will + * contain geniune data. + */ + if(compat20 && use_steno_timing_manipulation) + { + (*bogus_send_count)=0; + debug2("reseting count"); + } + /* End SD Mod */ packet_send(); buffer_consume(&c->input, len); c->remote_window -= len; } - } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { + + } /* + * Begin SD Mod: + * packet does not contain data, we are not in a draining state + * and timing manipulation is desired, check if bogus count is + * below threshold. + */ + else if ((len = buffer_len(&c->input)) == 0 + && !(c->istate == CHAN_INPUT_WAIT_DRAIN) + && use_steno_timing_manipulation) + { + /* + * If we have not sent too many bogus packets, sent a 16 + * byte ignore packet filled with garbage data and update + * the bogus_send_count; + */ + if((*bogus_send_count) < 20){ + debug2("sending garbage packet"); + packet_send_ignore(16); + packet_send(); + (*bogus_send_count)++; + } + else + debug("max number of timeouts exceeded: stop sending garbage packets"); + } + /* End SD Mod */ + else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { if (compat13) fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); /* @@ -1487,7 +1556,7 @@ { int id, remote_id; Channel *c; - + debug("requesting channel confirm"); if (!compat20) packet_integrity_check(plen, 4 + 4, type); @@ -1558,7 +1627,7 @@ id = packet_get_int(); c = channel_lookup(id); - + debug("received request"); if (c == NULL || (c->type != SSH_CHANNEL_OPEN && c->type != SSH_CHANNEL_LARVAL)) packet_disconnect("Received request for " @@ -1571,7 +1640,6 @@ char *service = packet_get_string(NULL); debug("channel %d: rcvd request for %s", c->self, service); debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event); - xfree(service); } } @@ -2420,6 +2488,7 @@ * with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */ + void x11_input_open(int type, int plen, void *ctxt) { @@ -2764,7 +2833,7 @@ if (c == NULL) { log("channel_register_callback: %d: bad id", id); return; - } + } c->cb_event = mtype; c->cb_fn = fn; c->cb_arg = arg; --- channels.h Wed Jun 13 12:18:05 2001 +++ channels.new.h Fri Oct 5 18:04:02 2001 @@ -8,8 +8,8 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". - */ -/* + * + * * Copyright (c) 2000 Markus Friedl. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -21,6 +21,32 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -182,8 +208,14 @@ void channel_after_select(fd_set * readset, fd_set * writeset); /* If there is data to send to the connection, send some of it now. */ -void channel_output_poll(void); +/* + * SD Mod: added parameters bogus_send_count, and use_steno_timing_manipulation. + * The bogus_send_count keeps track of how many bogus packets have been sent since + * the last packet containing real data. The use_steno_timining_manipulation flag + * keeps track of whether to perform timing analysis evasion. + */ +void channel_output_poll(int *bogus_send_count, int use_steno_timing_manipulation); /* Returns true if no channel has too much buffered data. */ int channel_not_very_much_buffered_data(void); @@ -310,5 +342,4 @@ int x11_connect_display(void); int channel_find_open(void); - #endif --- clientloop.c Fri Apr 20 05:50:51 2001 +++ clientloop.new.c Fri Oct 5 18:04:03 2001 @@ -46,6 +46,32 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -57,6 +83,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. */ + #include "includes.h" RCSID("$OpenBSD: clientloop.c,v 1.65 2001/04/20 07:17:51 djm Exp $"); @@ -262,7 +289,7 @@ len = buffer_len(&stdin_buffer); /* Keep the packets at reasonable size. */ if (len > packet_get_maxsize()) - len = packet_get_maxsize(); + len = packet_get_maxsize(); packet_start(SSH_CMSG_STDIN_DATA); packet_put_string(buffer_ptr(&stdin_buffer), len); packet_send(); @@ -315,20 +342,31 @@ } } + /* * Waits until the client can do something (some data becomes available on * one of the file descriptors). */ -void +/* + * SD Mod: We changed the return value of client_wait_until_can_do_something + * from void to int. It now returns 1 if the steno_timer has expired and 0 if not. + */ +int client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, int rekeying) { + /* SD Mod: added variable steno_timer */ + static struct timeval steno_timer = {0, 50000}; + + int return_val = 0; + long int prev_timer_val = 0; + /* Add any selections by the channel mechanism. */ channel_prepare_select(readsetp, writesetp, maxfdp, rekeying); if (!compat20) { - /* Read from the connection, unless our buffers are full. */ + /* Read from the connection, unless our buffers are full. */ if (buffer_len(&stdout_buffer) < buffer_high && buffer_len(&stderr_buffer) < buffer_high && channel_not_very_much_buffered_data()) @@ -361,9 +399,34 @@ * it: just have a random timeout for the select, and send a random * SSH_MSG_IGNORE packet when the timeout expires. */ + + /* + * Begin SD Mod: + * Enforce wait send packets every 50 ms. To do this add timer to + * select loop. Buffer input as it comes and force the timer to decrement + * if select call does not do so. + */ + prev_timer_val = steno_timer.tv_usec; - if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) { - char buf[100]; + return_val = select((*maxfdp)+1, *readsetp, *writesetp, NULL, &steno_timer); + + /* SD Mod continued: + * If the prev_timer_val is still equal to the steno_timer.tv_usec value + * then select did not decrement timer. So force decrement so timer can + * expire. This problem arises since the file descriptors change since they + * were reset just prior to entering the select loop. This is a strange + * fix but it works. + */ + + if(prev_timer_val == steno_timer.tv_usec){ + debug3("decrementing timer forcefully"); + steno_timer.tv_usec -= 100; + } + + if(return_val < 0){ + /* end of SD Mod */ + + char buf[100]; /* * We have to clear the select masks, because we return. @@ -374,12 +437,28 @@ memset(*writesetp, 0, *maxfdp); if (errno == EINTR) - return; + return 0; /* Note: we might still have data in the buffers. */ snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); buffer_append(&stderr_buffer, buf, strlen(buf)); quit_pending = 1; } + /* + * Begin SD Mod: Return to the caller whether the timer has + * expired or not. It is possible that the forced decrement caused + * the timer value to bbecome negative, if so the consider the + * timer expired, reset it and return 1 to the caller denoting timer + * expiration. + */ + if(steno_timer.tv_usec <= 0) + { + steno_timer.tv_usec = 50000; + return 1; + } + else + return 0; + /* End SD Mod */ + } void @@ -770,6 +849,8 @@ double start_time, total_time; int max_fd = 0, len, rekeying = 0; char buf[100]; + int bogus_send_count = 0; + int time_out = 0; debug("Entering interactive session."); @@ -829,6 +910,7 @@ if (session_ident != -1) channel_register_cleanup(session_ident, client_channel_closed); + } else { /* Check if we should immediately send eof on stdin. */ client_check_initial_eof_on_stdin(); @@ -859,9 +941,17 @@ * Make packets from buffered channel data, and * enqueue them for sending to the server. */ - if (packet_not_very_much_data_to_write()) - channel_output_poll(); - + + /* + * Begin SD Mod: on expiration of 50 ms timer call + * channel_ouput + */ + if(time_out){ + channel_output_poll(&bogus_send_count,options.use_steno_timing_manipulation); + time_out = 0; + } + /* End SD Mod */ + /* * Check if the window size has changed, and buffer a * message about it to the server if so. @@ -875,9 +965,11 @@ * Wait until we have something to do (something becomes * available on one of the descriptors). */ - client_wait_until_can_do_something(&readset, &writeset, + + time_out = client_wait_until_can_do_something(&readset, + &writeset, &max_fd, rekeying); - + if (quit_pending) break; @@ -910,8 +1002,9 @@ } /* Send as much buffered packet data as possible to the sender. */ - if (FD_ISSET(connection_out, writeset)) - packet_write_poll(); + if (FD_ISSET(connection_out, writeset)){ + packet_write_poll(); + } } if (readset) xfree(readset); @@ -982,7 +1075,6 @@ return exit_status; } -/*********/ void client_input_stdout_data(int type, int plen, void *ctxt) @@ -1170,7 +1262,6 @@ id = packet_get_int(); rtype = packet_get_string(NULL); reply = packet_get_char(); - debug("client_input_channel_req: channel %d rtype %s reply %d", id, rtype, reply); @@ -1187,7 +1278,22 @@ success = 1; exit_status = packet_get_int(); packet_done(); + } + /* + * Begin SD Mod: + * check to see if request from server is to turn off steno. + * If so, turn it off if neccessary. + */ + else if (strcmp(rtype, "no_steno") == 0) { + debug("received request not use use steno"); + if(options.use_steno_timing_manipulation) + { + options.use_steno_timing_manipulation = 0; + } + success = 1; + packet_done(); } + /* End SD Mod */ if (reply) { packet_start(success ? SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); --- readconf.c Tue Apr 17 11:11:37 2001 +++ readconf.new.c Fri Oct 5 18:04:03 2001 @@ -9,6 +9,32 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** */ #include "includes.h" @@ -761,6 +787,12 @@ options->num_remote_forwards = 0; options->log_level = (LogLevel) - 1; options->preferred_authentications = NULL; + /* + * SD Mod: Initialize option to use steno timing manipulation. + * By default, timing analysis evasion is used. The -S flag + * must be used to turn off this feature. + */ + options->use_steno_timing_manipulation = 1; } /* @@ -880,4 +912,6 @@ /* options->hostname will be set in the main program if appropriate */ /* options->host_key_alias should not be set by default */ /* options->preferred_authentications will be set in ssh */ + + } --- readconf.h Tue Apr 17 11:11:37 2001 +++ readconf.new.h Fri Oct 5 18:04:04 2001 @@ -9,6 +9,33 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * */ /* RCSID("$OpenBSD: readconf.h,v 1.30 2001/04/17 10:53:25 markus Exp $"); */ @@ -97,6 +124,14 @@ /* Remote TCP/IP forward requests. */ int num_remote_forwards; Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION]; + + /* + * SD Mod: Added option to use steno timing manipulation. + * By default, timing analysis evasion is used. The -S flag + * must be used to turn off this feature. + */ + int use_steno_timing_manipulation; + } Options; --- servconf.c Wed Apr 25 05:44:15 2001 +++ servconf.new.c Fri Oct 5 18:04:04 2001 @@ -7,6 +7,33 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + * *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * */ #include "includes.h" @@ -102,6 +129,12 @@ options->client_alive_interval = -1; options->client_alive_count_max = -1; options->pam_authentication_via_kbd_int = -1; + /* + * SD Mod: Initialize option to use steno timing manipulation. + * By default, timing analysis evasion is used. The -S flag + * must be used to turn off this feature. + */ + options->use_steno_timing_manipulation = 1; } void --- servconf.h Wed Apr 25 05:44:16 2001 +++ servconf.new.h Fri Oct 5 18:04:05 2001 @@ -9,6 +9,33 @@ * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". + * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * */ /* RCSID("$OpenBSD: servconf.h,v 1.41 2001/04/13 22:46:53 beck Exp $"); */ @@ -125,6 +152,13 @@ * diconnect the session */ int pam_authentication_via_kbd_int; + + /* + * SD Mod: Added option to use steno timing manipulation. + * By default, timing analysis evasion is used. The -S flag + * must be used to turn off this feature. + */ + int use_steno_timing_manipulation; } ServerOptions; /* * Initializes the server options to special values that indicate that they --- serverloop.c Fri Apr 13 16:28:03 2001 +++ serverloop.new.c Fri Oct 5 18:04:05 2001 @@ -32,6 +32,32 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** */ #include "includes.h" @@ -41,6 +67,7 @@ #include "packet.h" #include "buffer.h" #include "log.h" + #include "servconf.h" #include "sshpty.h" #include "channels.h" @@ -55,6 +82,7 @@ #include "misc.h" #include "kex.h" + extern ServerOptions options; /* XXX */ @@ -186,15 +214,24 @@ * have data or can accept data. Optionally, a maximum time can be specified * for the duration of the wait (0 = infinite). */ -void + +/* + * SD Mod: + * We changed wait_until_can_do_something's return value from void + * to int. It now returns 1 if the steno_timer has expired and 0 if not. + */ +int wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, u_int max_time_milliseconds) { - struct timeval tv, *tvp; + + struct timeval tv, *tvp; + /* SD Mod: added variable steno_timer*/ + static struct timeval steno_timer = {0, 50000}; int ret; int client_alive_scheduled = 0; - - /* + long int prev_timer_val = 0; + /* * if using client_alive, set the max timeout accordingly, * and indicate that this particular timeout was for client * alive by setting the client_alive_scheduled flag. @@ -218,7 +255,8 @@ /* wrong: bad condition XXX */ if (channel_not_very_much_buffered_data()) FD_SET(connection_in, *readsetp); - } else { + +} else { /* * Read packets from the client unless we have too much * buffered stdin or channel data. @@ -269,8 +307,21 @@ if (tvp!=NULL) debug3("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds); + + /* SD Mod: if select does not decrement timer, force it.*/ + prev_timer_val = steno_timer.tv_usec; + + ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, &steno_timer); + + if(prev_timer_val == steno_timer.tv_usec) + { + debug3 ("decrementing timer forcefully"); + steno_timer.tv_usec -= 100; + } + /* End SD Mod */ + /* Wait for something to happen, or the timeout to expire. */ - ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); + if (ret == -1) { if (errno != EINTR) @@ -278,9 +329,11 @@ else goto retry_select; } + if (ret == 0 && client_alive_scheduled) { /* timeout, check to see how many we have had */ - client_alive_timeouts++; + + client_alive_timeouts++; if (client_alive_timeouts > options.client_alive_count_max ) { packet_disconnect( @@ -301,7 +354,24 @@ packet_disconnect( "No open channels after timeout!"); } - } + } + + /* + * Begin SD Mod: Return to the caller whether the timer has + * expired or not. It is possible that the forced decrement caused + * the timer value to bbecome negative, if so the consider the + * timer expired, reset it and return 1 to the caller denoting timer + * expiration. + */ + if(steno_timer.tv_usec <= 0) + { + steno_timer.tv_usec = 50000; + return 1; + } + else + return 0; + /* End SD Mod */ + } /* @@ -369,7 +439,6 @@ { struct termios tio; int len; - /* Write buffered data to program stdin. */ if (!compat20 && fdin != -1 && FD_ISSET(fdin, writeset)) { len = write(fdin, buffer_ptr(&stdin_buffer), @@ -387,6 +456,7 @@ #endif fdin = -1; } else { + /* Successful write. */ if (fdin_is_tty && tcgetattr(fdin, &tio) == 0 && !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { @@ -394,6 +464,7 @@ * Simulate echo to reduce the impact of * traffic analysis */ + debug("simulating echo"); packet_send_ignore(len); packet_send(); } @@ -403,9 +474,10 @@ stdin_bytes += len; } } + /* Send any buffered packet data to the client. */ - if (FD_ISSET(connection_out, writeset)) - packet_write_poll(); + else if (FD_ISSET(connection_out, writeset)) + packet_write_poll(); } /* @@ -458,13 +530,16 @@ int wait_status; /* Status returned by wait(). */ pid_t wait_pid; /* pid returned by wait(). */ int waiting_termination = 0; /* Have displayed waiting close message. */ + int time_out = 0; u_int max_time_milliseconds; u_int previous_stdout_buffer_bytes; u_int stdout_buffer_bytes; int type; + /* SD Mod: NOT USED only here for compatibility with channel_output_poll()*/ + int bogus_send_count = 0 ; debug("Entering interactive session."); - + /* Initialize the SIGCHLD kludge. */ child_pid = pid; child_terminated = 0; @@ -521,10 +596,10 @@ /* Main loop of the server for the interactive session mode. */ for (;;) { - + /* Process buffered packets from the client. */ process_buffered_input_packets(); - + /* * If we have received eof, and there is no more pending * input data, cause a real eof by closing fdin. @@ -563,8 +638,15 @@ previous_stdout_buffer_bytes = buffer_len(&stdout_buffer); /* Send channel data to the client. */ - if (packet_not_very_much_data_to_write()) - channel_output_poll(); + + /* + * Begin SD Mod: Only send packets when 50 ms timer has expired. + */ + if (time_out){ + channel_output_poll(&bogus_send_count,options.use_steno_timing_manipulation); + time_out = 0; + } + /* End SD Mod */ /* * Bail out of the loop if the program has closed its output @@ -588,9 +670,9 @@ } } /* Sleep in select() until we can do something. */ - wait_until_can_do_something(&readset, &writeset, &max_fd, + time_out = wait_until_can_do_something(&readset, &writeset, &max_fd, max_time_milliseconds); - + /* Process any channel events. */ channel_after_select(readset, writeset); @@ -697,6 +779,8 @@ fd_set *readset = NULL, *writeset = NULL; int rekeying = 0, max_fd, status; pid_t pid; + int bogus_send_count = 0; + int time_out = 0; debug("Entering interactive session for SSH2."); @@ -707,17 +791,31 @@ max_fd = MAX(connection_in, connection_out); + server_init_dispatch(); for (;;) { - process_buffered_input_packets(); + process_buffered_input_packets(); + rekeying = (xxx_kex != NULL && !xxx_kex->done); + /* + * SD Mod: send packets only when not rekeying and + * 50 ms timer has expired. + */ + if (!rekeying && time_out) + { + channel_output_poll(&bogus_send_count,options.use_steno_timing_manipulation); + time_out = 0; + } - if (!rekeying && packet_not_very_much_data_to_write()) - channel_output_poll(); - wait_until_can_do_something(&readset, &writeset, &max_fd, + /* + * SD Mod: added time_out flag to record when 50 ms timer has + * expired. + */ + time_out = wait_until_can_do_something(&readset, &writeset, &max_fd, rekeying); + /* End SD Mod */ if (child_terminated) { while ((pid = waitpid(-1, &status, WNOHANG)) > 0) session_close_by_pid(pid, status); @@ -873,7 +971,7 @@ ctype, rchan, rwindow, rmaxpack); if (strcmp(ctype, "session") == 0) { - c = server_request_session(ctype); + c = server_request_session(ctype); } else if (strcmp(ctype, "direct-tcpip") == 0) { c = server_request_direct_tcpip(ctype); } @@ -889,6 +987,17 @@ packet_put_int(c->local_window); packet_put_int(c->local_maxpacket); packet_send(); + /* + * SD Mod: if -S option is used, request + * client to not use stenographic timing manipulation as well. + */ + if(!options.use_steno_timing_manipulation) + { + debug("sending no steno msg"); + channel_request(c->remote_id,"no_steno",0); + } + /* End SD Mod */ + } else { debug("server_input_channel_open: failure %s", ctype); packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); @@ -997,11 +1106,13 @@ void server_init_dispatch(void) { + if (compat20) server_init_dispatch_20(); else if (compat13) server_init_dispatch_13(); else server_init_dispatch_15(); + } --- session.c Sat Jun 16 20:40:51 2001 +++ session.new.c Fri Oct 5 18:04:06 2001 @@ -19,6 +19,34 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * + *************************************************************************** + * + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -239,6 +267,7 @@ s = session_new(); s->pw = authctxt->pw; + /* * We stay in this loop until the client requests to execute a shell * or a command. @@ -383,7 +412,6 @@ if (packet_set_maxsize(packet_get_int()) > 0) success = 1; break; - case SSH_CMSG_EXEC_SHELL: case SSH_CMSG_EXEC_CMD: if (type == SSH_CMSG_EXEC_CMD) { @@ -1746,7 +1774,22 @@ do_exec_pty(s, shell); return 1; } - +/* + * Begin SD Mod: This function is added to handle a request from the + * client to turn off steno timing manipulation. + */ +int +session_no_steno_req(Session *s) +{ + packet_done(); + debug("handling steno request"); + if(options.use_steno_timing_manipulation) + { + options.use_steno_timing_manipulation = 0; + } + return 1; +} +/* End SD Mod */ int session_exec_req(Session *s) { @@ -1824,7 +1867,20 @@ success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); + }/* + * Begin SD Mod: Handle request from the client + * to turn off server's timing manipulation. + */ + else if (strcmp(rtype, "no_steno") == 0) { + success = session_no_steno_req(s); + } + /* End SD Mod */ + else { + debug("rtype is %s",rtype); } + + + } if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(s); @@ -1967,6 +2023,7 @@ session_close(s); } + /* * this is called when a channel dies before * the session 'child' itself dies @@ -2026,6 +2083,6 @@ void do_authenticated2(Authctxt *authctxt) { - - server_loop2(); + server_loop2(); } + --- ssh.c Tue Apr 17 11:14:35 2001 +++ ssh.new.c Fri Oct 5 18:04:07 2001 @@ -1,3 +1,4 @@ + /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -26,6 +27,32 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * + * *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + *************************************************************************** + * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -36,6 +63,7 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * */ #include "includes.h" @@ -173,7 +201,7 @@ fprintf(stderr, " -q Quiet; don't display any warning messages.\n"); fprintf(stderr, " -f Fork into background after authentication.\n"); fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n"); - + fprintf(stderr, " -c cipher Select encryption algorithm: " "``3des'', ``blowfish''\n"); fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\n"); @@ -191,6 +219,8 @@ fprintf(stderr, " -6 Use IPv6 only.\n"); fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n"); fprintf(stderr, " -s Invoke command (mandatory) as SSH2 subsystem.\n"); + /* SD Mod: */ + fprintf(stderr, " -S Don't use stenographic timing manipulation\n"); exit(1); } @@ -517,6 +547,14 @@ case 's': subsystem_flag = 1; break; + /* + * Begin SD Mod: Add case to handle option to turn off + * steno timing manipulation. + */ + case 'S': + options.use_steno_timing_manipulation = 0; + break; + /* End SD Mod */ default: usage(); } @@ -832,7 +870,6 @@ int have_tty = 0; struct winsize ws; char *cp; - /* Enable compression if requested. */ if (options.compression) { debug("Requesting compression at level %d.", options.compression_level); @@ -851,8 +888,11 @@ else if (type == SSH_SMSG_FAILURE) log("Warning: Remote host refused compression."); else + { packet_disconnect("Protocol error waiting for compression response."); + } } + /* Allocate a pseudo tty if appropriate. */ if (tty_flag) { debug("Requesting pty."); @@ -1024,7 +1064,19 @@ channel_request_start(id, "auth-agent-req@openssh.com", 0); packet_send(); } - + /* + * Begin SD Mod: If the client has the option to turn of timing + * manipulation set, send a request message to the server to + * turn off its timing manipulation. + */ + if (!options.use_steno_timing_manipulation) + { + debug("sending request for no steno."); + channel_request_start(id, "no_steno",0); + packet_send(); + } + /* End SD Mod */ + len = buffer_len(&command); if (len > 0) { if (len > 900) @@ -1046,7 +1098,6 @@ channel_request(id, "shell", 0); } /* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */ - /* register different callback, etc. XXX */ packet_set_interactive(interactive); } --- sshd.c Sun Apr 15 19:00:02 2001 +++ sshd.new.c Fri Oct 5 18:04:06 2001 @@ -14,6 +14,7 @@ * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * + * * SSH2 implementation: * * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -26,6 +27,31 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. + * *************************************************************************** + * Timing Analysis Evasion changes were developed by C. Jason Coit and Roel + * Jonkman of Silicon Defense. + * + * These changes cause SSH to send packets unless requested not to, exactly + * every 50 ms. If no data is ready to be sent, SSH will send a bogus packet + * with 16 bytes of data (which is the same size as most keystrokes). Thus + * someone performing timing analysis cannot determine the inter keystroke + * timing of a user. SSH will send bogus data for about 1 sec after the last + * keystroke. This both increases the difficulty of determing exact password + * lengths and conserves bandwith when a user is idle (e.g. taking a coffee break). + * Both the server and the client exhibit this behavior and yet our code places no + * limit on the data rate (i.e if the server needs to respond with large amounts + * of data it will be about to do so with large packets able to do so with large + * packets and without the 50 ms timing constraint). + * + * All changes were developed in response to timing analysis attack on ssh + * published by Dawn Song et. al. + * + * The evasion methods are only applicable to SSH2. All single line changes + * and small comments are marked by SD Mod. All multiline modifications are + * delimited by Begin SD Mod and End SD Mod. + * + * The last change was committed on 10/3/2001. + ********************************************************************************** * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES @@ -553,7 +579,7 @@ int startups = 0; Key *key; int ret, key_used = 0; - + __progname = get_progname(av[0]); init_rng(); @@ -565,7 +591,8 @@ initialize_server_options(&options); /* Parse command-line arguments. */ - while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqQ46")) != -1) { + /* SD Mod: add s option to getopt() call */ + while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqQ46S")) != -1) { switch (opt) { case '4': IPv4or6 = AF_INET; @@ -638,6 +665,14 @@ case 'u': utmp_len = atoi(optarg); break; + /* + * Begin SD Mod: Add option to handle option to turn off + * steno timing manipulation. + */ + case 'S': + options.use_steno_timing_manipulation = 0; + break; + /* End SD Mod */ case '?': default: fprintf(stderr, "sshd version %s\n", SSH_VERSION); @@ -657,6 +692,8 @@ fprintf(stderr, " -u len Maximum hostname length for utmp recording\n"); fprintf(stderr, " -4 Use IPv4 only\n"); fprintf(stderr, " -6 Use IPv6 only\n"); + /* SD Mod */ + fprintf(stderr, " -S Don't use stenographic timing manipulation\n"); exit(1); } }