Defeating Timing Attacks Patch for OpenSSH 2.9.9p2 and 2.9p2

C. Jason Coit jasonc at silicondefense.com
Wed Oct 17 05:21:00 EST 2001


Hello,

In response to the timing analysis attacks presented by Dawn Song et.
al. in her paper http://paris.cs.berkeley.edu/~dawnsong/ssh-timing.html
we
at Silicon Defense developed a patch for openssh to avoid such
measures.  

Timing Analysis Evasion changes were developed by C. Jason Coit and Roel
Jonkman of Silicon Defense.

These changes cause SSH to send packets unless request 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 second after the last keystroke.  This both increases the
difficulty of determining exact password lengths and conserves bandwidth
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 able to do so with large packets and without the 50 ms timing
constraint).  

We currently have patches and modified distributions for OpenSSH 2.9p2
and 2.9.9p2.  
The files for OpenSSH 2.9p2 are available at
http://www.silicondefense.com/software/ssh/ssh-2.9p2-diffs
http://www.silicondefense.com/software/ssh/opens3h-2.9p2.tar.gz

These files for OpenSSH 2.9.9p2 are available at
http://www.silicondefense.com/software/ssh/ssh-2.9.9p2-diffs
http://www.silicondefense.com/software/ssh/opens3h-2.9.9p2.tar.gz

The patch for 2.9.9p2 is available below:

--- channels.c  Mon Sep 17 22:53:12 2001
+++ channels.new.c      Mon Oct 15 14:28:43 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,9 +1616,12 @@
 
 
 /* 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;
@@ -1649,11 +1678,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");
                        /*
--- channels.h  Mon Sep 17 22:51:14 2001
+++ channels.new.h      Mon Oct 15 14:28:43 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    Mon Oct 15 14:28:43 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/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.
@@ -315,16 +342,25 @@
  * 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 */
+        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, 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 +378,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 +393,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 +431,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 +843,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 +940,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 +964,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 +1310,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      Mon Oct 15 14:28:43 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      Mon Oct 15 14:28:43 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      Mon Oct 15 14:28:43 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      Mon Oct 15 14:28:43 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    Mon Oct 15 14:28:43 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/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
@@ -167,15 +192,24 @@
  * 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;
+       /* 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.
@@ -183,11 +217,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 +233,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 +285,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 +307,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 +332,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 +516,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 +624,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 +661,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 +758,14 @@
        int rekeying = 0, max_fd, status, nalloc = 0;
        pid_t pid;
 
+       /* 
+        * Begin SD Mod: 
+        * NOT USED only here for compatibility with
channel_output_poll().
+        */
+       int bogus_send_count = 0 ;
+       int time_out = 0;
+       /* End SD Mod */
+
        debug("Entering interactive session for SSH2.");
 
        mysignal(SIGCHLD, sigchld_handler);
@@ -692,30 +782,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 +998,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       Mon Oct 15 14:28:43 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   Mon Oct 15 14:28:43 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  Mon Oct 15 14:28:43 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);
                }
        }




--
regards,

Jason Coit

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



More information about the openssh-unix-dev mailing list