Do not include a timestamp in the Client/ServerHello Random field.
authorNick Mathewson <nickm@torproject.org>
Sun, 20 Oct 2013 22:03:24 +0000 (15:03 -0700)
committerNick Mathewson <nickm@torproject.org>
Sun, 20 Oct 2013 22:03:24 +0000 (15:03 -0700)
Instead, send random bytes, unless SSL_SEND_{CLIENT,SERVER}RANDOM_MODE
is set.

This is a forward-port of commits:
  4af793036f6ef4f0a1078e5d7155426a98d50e37
  f4c93b46edb51da71f09eda99e83eaf193a33c08
  3da721dac9382c48812c8eba455528fd59af2eef
  2583270191a8b27eed303c03ece1da97b9b69fd3

While the gmt_unix_time record was added in an ostensible attempt to
mitigate the dangers of a bad RNG, its presence leaks the host's view
of the current time in the clear.  This minor leak can help
fingerprint TLS instances across networks and protocols... and what's
worse, it's doubtful thet the gmt_unix_time record does any good at
all for its intended purpose, since:

    * It's quite possible to open two TLS connections in one second.

    * If the PRNG output is prone to repeat itself, ephemeral
      handshakes (and who knows what else besides) are broken.

ssl/s23_clnt.c
ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/ssl_locl.h

index 15da654bf195e50d55b62c78fade8e282f0fefb1..ad4145b5876475d215481d6b4fc78a791aa645a5 100644 (file)
@@ -269,6 +269,28 @@ static int ssl23_no_ssl2_ciphers(SSL *s)
        return 1;
        }
 
+/* Fill a ClientRandom or ServerRandom field of length len. Returns <= 0
+ * on failure, 1 on success. */
+int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
+       {
+               int send_time = 0;
+               if (len < 4)
+                       return 0;
+               if (server)
+                       send_time = (s->mode & SSL_MODE_SEND_SERVERHELLO_TIME) != 0;
+               else
+                       send_time = (s->mode & SSL_MODE_SEND_CLIENTHELLO_TIME) != 0;
+               if (send_time)
+                       {
+                       unsigned long Time = time(NULL);
+                       unsigned char *p = result;
+                       l2n(Time, p);
+                       return RAND_pseudo_bytes(p, len-4);
+                       }
+               else
+                       return RAND_pseudo_bytes(result, len);
+       }
+
 static int ssl23_client_hello(SSL *s)
        {
        unsigned char *buf;
@@ -359,9 +381,7 @@ static int ssl23_client_hello(SSL *s)
 #endif
 
                p=s->s3->client_random;
-               Time=(unsigned long)time(NULL);         /* Time */
-               l2n(Time,p);
-               if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0)
+               if (ssl_fill_hello_random(s, 0, p, SSL3_RANDOM_SIZE) <= 0)
                        return -1;
 
                if (version == TLS1_2_VERSION)
index 57259c630c067da95fc528e0be797f29de3a2c49..6aeab442e1166ccc9d21f0864501878043073bc7 100644 (file)
@@ -672,7 +672,7 @@ int ssl3_client_hello(SSL *s)
        unsigned char *buf;
        unsigned char *p,*d;
        int i;
-       unsigned long Time,l;
+       unsigned long l;
 #ifndef OPENSSL_NO_COMP
        int j;
        SSL_COMP *comp;
@@ -752,12 +752,8 @@ int ssl3_client_hello(SSL *s)
                        i = 1;
 
                if (i)
-                       {
-                       Time=(unsigned long)time(NULL); /* Time */
-                       l2n(Time,p);
-                       RAND_pseudo_bytes(p,sizeof(s->s3->client_random)-4);
-                                       
-                       }
+                       ssl_fill_hello_random(s, 0, p,
+                                             sizeof(s->s3->client_random));
 
                /* Do the message type and length last */
                d=p= ssl_handshake_start(s);
index 09af9ae1cf4c044cfc2b8377c29560c49505bc30..06e90dcd52758a9e8be41e874fa83a14ba176d45 100644 (file)
@@ -1236,12 +1236,9 @@ int ssl3_get_client_hello(SSL *s)
         * server_random before calling tls_session_secret_cb in order to allow
         * SessionTicket processing to use it in key derivation. */
        {
-               unsigned long Time;
                unsigned char *pos;
-               Time=(unsigned long)time(NULL);                 /* Time */
                pos=s->s3->server_random;
-               l2n(Time,pos);
-               if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0)
+               if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0)
                        {
                        goto f_err;
                        }
index fd13f70ca93c215e5959f8b4a98e36cb2d0cb238..e4a0ff1f7e996e8302e560c30a2cc1d0fbd06f07 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -707,6 +707,12 @@ struct ssl_session_st
  * TLS only.)  "Released" buffers are put onto a free-list in the context
  * or just freed (depending on the context's setting for freelist_max_len). */
 #define SSL_MODE_RELEASE_BUFFERS 0x00000010L
+/* Send the current time in the Random fields of the ClientHello and
+ * ServerHello records for compatibility with hypothetical implementations
+ * that require it.
+ */
+#define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020L
+#define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040L
 
 /* Cert related flags */
 /* Many implementations ignore some aspects of the TLS standards such as
index 0fedf4d56d37e55b34bd3efb23ad186d95108bcb..52e93e23e03e98379837d48c9558cd67a308c44f 100644 (file)
@@ -1021,6 +1021,7 @@ void ssl_set_cert_masks(CERT *c, const SSL_CIPHER *cipher);
 STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
 int ssl_verify_alarm_type(long type);
 void ssl_load_ciphers(void);
+int ssl_fill_hello_random(SSL *s, int server, unsigned char *field, int len);
 
 int ssl2_enc_init(SSL *s, int client);
 int ssl2_generate_key_material(SSL *s);