Defeating Timing Attacks

C. Jason Coit jasonc at silicondefense.com
Thu Oct 25 10:17:47 EST 2001


All,

Update 10/24/2001
 
Thanks to suggestions by David Wagner (one of the authors of the timing 
analysis attack) and Stuart Staniford,  we have recently updated our SSH 
patch slightly. The original patch turned off the stream of bogus
packets
sent during an idle time after 1 second. This could possibly leak a
small
amount of information about the last genuine packet transmitted. To make
such analysis more difficult, SSH will require 900 ms of idle time
before
considering to shut off the transmission of bogus packets. Then with 
probability 1/5, SSH will shut off the stream at each succeeding packet.
Thus the exponential lifetime decay in the shut off is about 250ms. This 
means that the eavesdropper only knows to within a few packets when the 
last key press was. 

The new patch for 2.9.9p2 is provided below and a gzipped tar file of 
patched versions of 2.9.9p2 and 2.9p2 are available at
http://www.silicondefense.com/software/ssh/index.htm

regards,

-Jason

Patch:
--- channels.c	Mon Sep 17 22:53:12 2001
+++ channels.new.c	Tue Oct 23 12:15:57 2001
@@ -25,6 +25,32 @@
  * 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/13/2001.
+
*************************************************************************** 
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
@@ -1590,11 +1616,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;
+	/*
+	 * SD Mod: Added for random shutoff of garbage packets past 900ms of
+	 * no real data sent.
+	 */
+	double rand_shutoff;
 	Channel *c;
 
 	for (i = 0; i < channels_alloc; i++) {
@@ -1649,11 +1683,93 @@
 				    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 to see if we are to send bogus packets.
+		   */
+		else if ((len = buffer_len(&c->input)) == 0 
+			 && !(c->istate == CHAN_INPUT_WAIT_DRAIN) 
+			 && use_steno_timing_manipulation) {   		     
+		  /* 
+		   * For the first 900 ms, send a 16 byte ignore packet 
+		   * filled with garbage data and update the bogus_send_count;
+		   * Note: 18*50ms = 900 ms.
+		   * Bogus_send count is used to keep state of the first 
+		   * 18 packets and then is set to 20 when we randomly
+		   * shut off flow of garbage packets as described below. 
+		   */
+		  
+		  if((*bogus_send_count) < 18){
+		      debug2("sending garbage packet");
+		      packet_send_ignore(16);
+		      packet_send();
+		      (*bogus_send_count)++;
+		    }
+		    else if((*bogus_send_count) != 20)
+		      {
+			/*
+			 * After 900 ms, shut off garbage output with 
+			 * probability 1/5.  Repeat for each succeeding
+			 * timeout past 900 ms until counter reset (i.e. real
+			 * data has been sent) or rand_shutoff <= .2.
+			 *  
+			 * Thus the exponential lifetime decay in the cutoff
+			 * is 250 ms.  So an eavesdropper only knows 
+			 * within a few packets when the last keypress was.
+			 *
+			 * Keep state by if checking bogus_send_count == 20.
+			 */
+			
+			rand_shutoff = arc4random() / (double) UINT_MAX;  
+			debug("Random is:%lf",rand_shutoff);
+			
+			if(rand_shutoff <= ((double) .2))
+			  {
+			    /* 
+			     * If we have hit that 1/5 chance, shut off 
+			     * the flow of garbage packets. 
+			     * Update bogus_send_count (now used as flag) to 
+			     * be 20.
+			     */
+			    (*bogus_send_count) = 20;
+			    debug("Random shutoff: stop sending garbage packets");
+			  }
+			else
+			  { 
+			    /* 
+			     * Random shutoff did not occur, so send bogus packet.
+			     */
+			    debug2("sending garbage packet");
+			    packet_send_ignore(16);
+			    packet_send();
+			  }
+		      }
+		    else
+		      debug("Random Shutoff past 900ms occurred: 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");
 			/*
--- channels.h	Mon Sep 17 22:51:14 2001
+++ channels.new.h	Tue Oct 23 12:15:57 2001
@@ -21,6 +21,33 @@
  *    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/13/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.
@@ -173,7 +200,15 @@
 
 void	 channel_prepare_select(fd_set **, fd_set **, int *, int*, int);
 void     channel_after_select(fd_set *, fd_set *);
-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);
+
 
 int      channel_not_very_much_buffered_data(void);
 void     channel_close_all(void);
--- clientloop.c	Mon Sep 17 22:51:14 2001
+++ clientloop.new.c	Tue Oct 23 12:15:57 2001
@@ -46,6 +46,33 @@
  *    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/22/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.
@@ -315,16 +342,28 @@
  * Waits until the client can do something (some data becomes available
on
  * one of the file descriptors).
  */
-
-static 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 *nallocp, int rekeying)
 {
+        /*
+	 * SD Mod: added variable steno_timer 
+	 * Added return_val and prev_timer_val
+	 */
+        static struct timeval steno_timer = {0, 50000};
+	int return_val = 0;
+	long int prev_timer_val = 0;
+	/* End SD Mod */
+
 	/* Add any selections by the channel mechanism. */
 	channel_prepare_select(readsetp, writesetp, maxfdp, nallocp,
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())
@@ -342,13 +381,7 @@
 		if (buffer_len(&stderr_buffer) > 0)
 			FD_SET(fileno(stderr), *writesetp);
 	} else {
-		/* channel_prepare_select could have closed the last channel */
-		if (session_closed && !channel_still_open()) {
-			if (!packet_have_data_to_write())
-				return;
-		} else {
-			FD_SET(connection_in, *readsetp);
-		}
+		FD_SET(connection_in, *readsetp);
 	}
 
 	/* Select server connection if have data to write to the server. */
@@ -363,9 +396,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;
+
+	return_val = select((*maxfdp)+1, *readsetp, *writesetp, NULL,
&steno_timer);
 
-	if (select((*maxfdp)+1, *readsetp, *writesetp, NULL, NULL) < 0) {
-		char buf[100];
+	/* 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.
@@ -376,14 +434,29 @@
 		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 */
+		  
 }
-
 static void
 client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
 {
@@ -773,6 +846,15 @@
 	int max_fd = 0, max_fd2 = 0, len, rekeying = 0, nalloc = 0;
 	char buf[100];
 
+	/*
+	 * Begin SD Mod: 
+	 * Add counter for number of fake packets that have been sent.
+	 * Add time_out flag for marking when timeout has occured.
+	 */
+	int bogus_send_count = 0;
+	int time_out = 0;
+	/* End SD Mod */
+
 	debug("Entering interactive session.");
 
 	start_time = get_current_time();
@@ -861,9 +943,16 @@
 			 * 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.
@@ -878,8 +967,10 @@
 		 * available on one of the descriptors).
 		 */
 		max_fd2 = max_fd;
-		client_wait_until_can_do_something(&readset, &writeset,
-		    &max_fd2, &nalloc, rekeying);
+
+		/* SD Mod: wait for data or timeout */
+	        time_out = client_wait_until_can_do_something(&readset,
+				 &writeset, &max_fd2, &nalloc, rekeying);		
 
 		if (quit_pending)
 			break;
@@ -1222,6 +1313,21 @@
 		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	Wed Sep 19 17:57:56 2001
+++ readconf.new.c	Tue Oct 23 12:15:57 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"
@@ -793,6 +819,12 @@
 	options->preferred_authentications = NULL;
 	options->bind_address = NULL;
 	options->smartcard_device = 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;
 }
 
 /*
--- readconf.h	Wed Sep 19 17:57:56 2001
+++ readconf.new.h	Tue Oct 23 12:15:57 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.
+
*************************************************************************** 
  */
 
 /* RCSID("$OpenBSD: readconf.h,v 1.39 2001/09/19 19:24:18 stevesk Exp
$"); */
@@ -101,6 +127,14 @@
 	int     num_remote_forwards;
 	Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
 	int	clear_forwardings;
+
+	/*
+	 * 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 Sep 12 09:32:15 2001
+++ servconf.new.c	Tue Oct 23 12:15:57 2001
@@ -7,6 +7,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"
@@ -105,6 +131,12 @@
 	options->authorized_keys_file = NULL;
 	options->authorized_keys_file2 = NULL;
 	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 Sep 12 09:40:06 2001
+++ servconf.new.h	Tue Oct 23 12:15:57 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.
+
*************************************************************************** 
+ *
  */
 
 /* RCSID("$OpenBSD: servconf.h,v 1.49 2001/08/17 18:59:47 stevesk Exp
$"); */
@@ -129,7 +155,12 @@
 	char   *authorized_keys_file;	/* File containing public keys */
 	char   *authorized_keys_file2;
 	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;
 
 void	 initialize_server_options(ServerOptions *);
--- serverloop.c	Mon Sep 17 22:53:13 2001
+++ serverloop.new.c	Tue Oct 23 12:15:57 2001
@@ -21,6 +21,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/22/2001.
+
***************************************************************************
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES
@@ -167,15 +192,29 @@
  * have data or can accept data.  Optionally, a maximum time can be
specified
  * for the duration of the wait (0 = infinite).
  */
-static 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,
     int *nallocp, u_int max_time_milliseconds)
 {
-	struct timeval tv, *tvp;
+  
+        struct timeval tv, *tvp;
 	int ret;
 	int client_alive_scheduled = 0;
-
 	/*
+	 * SD Mod: added variable steno_timer 
+	 * Added prev_timer_val
+	 */
+	static struct timeval steno_timer = {0, 50000};
+	long int prev_timer_val = 0;
+	/* End SD Mod */
+	
+	/* 
 	 * 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.
@@ -183,11 +222,11 @@
 	 * this could be randomized somewhat to make traffic
 	 * analysis more difficult, but we're not doing it yet.  
 	 */
-	if (compat20 &&
-	    max_time_milliseconds == 0 && options.client_alive_interval) {
-		client_alive_scheduled = 1;
+	if (max_time_milliseconds == 0 && options.client_alive_interval) {
+	        client_alive_scheduled = 1;
 		max_time_milliseconds = options.client_alive_interval * 1000;
-	}
+	} else 
+	        client_alive_scheduled = 0;
 
 	/* When select fails we restart from here. */
 retry_select:
@@ -199,7 +238,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.
@@ -250,8 +290,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)
@@ -259,9 +312,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(
@@ -282,9 +337,27 @@
 				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 */
+
 }
 
+
 /*
  * Processes input from the client and the program.  Input data is
stored
  * in buffers and processed later.
@@ -448,6 +521,13 @@
 	u_int stdout_buffer_bytes;
 	int type;
 
+	/*
+	 * Begin SD Mod: 
+ 	 * NOT USED only here for compatibility with channel_output_poll().
+	 */
+	int bogus_send_count = 0;
+	/* End SD Mod */
+
 	debug("Entering interactive session.");
 
 	/* Initialize the SIGCHLD kludge. */
@@ -549,8 +629,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: use bogus_send_count to comply 
+		 * with channel_output_poll definition.
+		 */
+		if(packet_not_very_much_data_to_write())
+		  channel_output_poll(&bogus_send_count,0);
+		/*
+		 * End SD Mod 
+		 */ 
 
 		/*
 		 * Bail out of the loop if the program has closed its output
@@ -579,7 +666,7 @@
 		max_fd = MAX(max_fd, fderr);
 
 		/* Sleep in select() until we can do something. */
-		wait_until_can_do_something(&readset, &writeset, &max_fd,
+		 wait_until_can_do_something(&readset, &writeset, &max_fd,
 		    &nalloc, max_time_milliseconds);
 
 		/* Process any channel events. */
@@ -676,6 +763,15 @@
 	int rekeying = 0, max_fd, status, nalloc = 0;
 	pid_t pid;
 
+	/* 
+	 * Begin SD Mod: 
+	 * Add counter for number of fake packets that have been sent.
+	 * Add time_out flag for marking when timeout has occured.
+	 */
+	int bogus_send_count = 0 ;
+	int time_out = 0;
+	/* End SD Mod */
+
 	debug("Entering interactive session for SSH2.");
 
 	mysignal(SIGCHLD, sigchld_handler);
@@ -692,30 +788,44 @@
 		process_buffered_input_packets();
 
 		rekeying = (xxx_kex != NULL && !xxx_kex->done);
-
-		if (!rekeying && packet_not_very_much_data_to_write())
-			channel_output_poll();
-		wait_until_can_do_something(&readset, &writeset, &max_fd,
-		    &nalloc, 0);
+		
+		/*
+		 * Begin 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;
+		  }
+		
+
+		/* 
+		 * 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,
&nalloc, rekeying);
+		/* End SD Mod */
+		
 		if (child_terminated) {
-			while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
-				session_close_by_pid(pid, status);
-			child_terminated = 0;
+		  while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+		    session_close_by_pid(pid, status);
+		  child_terminated = 0;
 		}
 		if (!rekeying)
-			channel_after_select(readset, writeset);
+		  channel_after_select(readset, writeset);
 		process_input(readset);
 		if (connection_closed)
-			break;
+		  break;
 		process_output(writeset);
 	}
 	if (readset)
-		xfree(readset);
+	  xfree(readset);
 	if (writeset)
-		xfree(writeset);
+	  xfree(writeset);
 
 	mysignal(SIGCHLD, SIG_DFL);
-
+	
 	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
 		session_close_by_pid(pid, status);
 	/*
@@ -894,6 +1004,17 @@
 			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);
--- session.c	Sun Sep 16 15:17:15 2001
+++ session.new.c	Tue Oct 23 12:15:57 2001
@@ -20,6 +20,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/13/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.
@@ -1726,6 +1752,24 @@
 	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 */
+
 static int
 session_exec_req(Session *s)
 {
@@ -1795,6 +1839,14 @@
 		} 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 */
 	}
 	if (strcmp(rtype, "window-change") == 0) {
 		success = session_window_change_req(s);
--- ssh.c	Mon Sep 24 15:04:03 2001
+++ ssh.new.c	Tue Oct 23 12:15:57 2001
@@ -26,6 +26,31 @@
  *    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.
@@ -205,6 +230,8 @@
 	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");
 	fprintf(stderr, "  -b addr     Local IP address.\n");
+	/* SD Mod: */
+	fprintf(stderr, "  -S          Don't use stenographic timing
manipulation\n");
 	exit(1);
 }
 
@@ -319,8 +346,9 @@
 	host = NULL;
 
 again:
+	/* SD Mod: add s option to getopt() call */
 	while ((opt = getopt(ac, av,
-	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
+	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:STVX")) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -525,6 +553,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 */
 		case 'b':
 			options.bind_address = optarg;
 			break;
@@ -1080,6 +1116,20 @@
 		channel_request_start(id, "auth-agent-req at 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) {
--- sshd.c	Mon Sep 17 21:03:04 2001
+++ sshd.new.c	Tue Oct 23 12:15:57 2001
@@ -26,6 +26,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
@@ -563,6 +588,7 @@
 	initialize_server_options(&options);
 
 	/* Parse command-line arguments. */
+	/* SD Mod: add s option to getopt() call */
 	while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqtQ46")) != -1) {
 		switch (opt) {
 		case '4':
@@ -645,6 +671,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);
@@ -665,6 +699,9 @@
 			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);
 		}
 	}




+--                                             --+
|        C. Jason Coit Programmer/Analyst          |
| *Silicon Defense - Technical Support for Snort* |
|        http://www.silicondefense.com/           |
+--                                              -+



More information about the openssh-unix-dev mailing list