Add security patch and create release. OpenSSL_0_9_6b
authorRichard Levitte <levitte@openssl.org>
Mon, 9 Jul 2001 14:36:30 +0000 (14:36 +0000)
committerRichard Levitte <levitte@openssl.org>
Mon, 9 Jul 2001 14:36:30 +0000 (14:36 +0000)
Tags will be OpenSSL_0_9_6b and OpenSSL-engine-0_9_6b

CHANGES
FAQ
NEWS
README
crypto/opensslv.h
crypto/rand/md_rand.c
doc/crypto/rand.pod

diff --git a/CHANGES b/CHANGES
index 0a4d18cbea9501ae7a5cec0284200cd2e1cc7c0c..f88867b065eefa06273f1cb2ad20ba522b42ccc1 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,7 +2,32 @@
  OpenSSL CHANGES
  _______________
 
- Changes between 0.9.6a and 0.9.6b  [XX xxx XXXX]
+ Changes between 0.9.6a and 0.9.6b  [9 Jul 2001]
+
+  *) Change ssleay_rand_bytes (crypto/rand/md_rand.c)
+     to avoid a SSLeay/OpenSSL PRNG weakness pointed out by
+     Markku-Juhani O. Saarinen <markku-juhani.saarinen@nokia.com>:
+     PRNG state recovery was possible based on the output of
+     one PRNG request appropriately sized to gain knowledge on
+     'md' followed by enough consecutive 1-byte PRNG requests
+     to traverse all of 'state'.
+
+     1. When updating 'md_local' (the current thread's copy of 'md')
+        during PRNG output generation, hash all of the previous
+        'md_local' value, not just the half used for PRNG output.
+
+     2. Make the number of bytes from 'state' included into the hash
+        independent from the number of PRNG bytes requested.
+
+     The first measure alone would be sufficient to avoid
+     Markku-Juhani's attack.  (Actually it had never occurred
+     to me that the half of 'md_local' used for chaining was the
+     half from which PRNG output bytes were taken -- I had always
+     assumed that the secret half would be used.)  The second
+     measure makes sure that additional data from 'state' is never
+     mixed into 'md_local' in small portions; this heuristically
+     further strengthens the PRNG.
+     [Bodo Moeller]
 
   *) Fix crypto/bn/asm/mips3.s.
      [Andy Polyakov]
diff --git a/FAQ b/FAQ
index 8b3d5403352a0848ed08995299ea645db3caa637..23e212fb4e85687733ebf93410ed04ac84668a63 100644 (file)
--- a/FAQ
+++ b/FAQ
@@ -57,7 +57,7 @@ OpenSSL  -  Frequently Asked Questions
 * Which is the current version of OpenSSL?
 
 The current version is available from <URL: http://www.openssl.org>.
-OpenSSL 0.9.6a was released on April 5th, 2001.
+OpenSSL 0.9.6b was released on July 9th, 2001.
 
 In addition to the current stable release, you can also access daily
 snapshots of the OpenSSL development version at <URL:
diff --git a/NEWS b/NEWS
index b9ea61239f09c20ac0d866e1acefd43d62cf0011..f45d8e5ced8b8dab65ad67d09b1b87022fd598e7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,23 @@
   This file gives a brief overview of the major changes between each OpenSSL
   release. For more details please read the CHANGES file.
 
+  Changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b:
+
+      o Security fix: PRNG improvements.
+      o Security fix: RSA OAEP check.
+      o Security fix: Reinsert and fix countermeasure to Bleichbacher's
+        attack.
+      o MIPS bug fix in BIGNUM.
+      o Bug fix in "openssl enc".
+      o Bug fix in X.509 printing routine.
+      o Bug fix in DSA verification routine and DSA S/MIME verification.
+      o Bug fix to make PRNG thread-safe.
+      o Bug fix in RAND_file_name().
+      o Bug fix in compatibility mode trust settings.
+      o Bug fix in blowfish EVP.
+      o Increase default size for BIO buffering filter.
+      o Compatibility fixes in some scripts.
+
   Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a:
 
       o Security fix: change behavior of OpenSSL to avoid using
diff --git a/README b/README
index 1c2f1111798eb429c2f162dc4d6ba89cc3e07e80..a31932b1c82a324cf69224f3c2388b40271a54f4 100644 (file)
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
 
- OpenSSL 0.9.6b-dev XX xxx XXXX
+ OpenSSL 0.9.6b  9 Jul 2001
 
- Copyright (c) 1998-2000 The OpenSSL Project
+ Copyright (c) 1998-2001 The OpenSSL Project
  Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
  All rights reserved.
 
index 7f2a6c039e3b256a5ed3d66c4de7bd5dbc282d76..45c7dc88ca20be987ea4379957caac2d31ee6289 100644 (file)
@@ -2,7 +2,7 @@
 #define HEADER_OPENSSLV_H
 
 /* Numeric release version identifier:
- * MMNNFFPPS: major minor fix patch status
+ * MNNFFPPS: major minor fix patch status
  * The status nibble has one of the values 0 for development, 1 to e for betas
  * 1 to 14, and f for release.  The patch level is exactly that.
  * For example:
@@ -25,8 +25,8 @@
  * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
  *  major minor fix final patch/beta)
  */
-#define OPENSSL_VERSION_NUMBER 0x00906020L
-#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.6b-dev XX xxx XXXX"
+#define OPENSSL_VERSION_NUMBER 0x0090602fL
+#define OPENSSL_VERSION_TEXT   "OpenSSL 0.9.6b 9 Jul 2001"
 #define OPENSSL_VERSION_PTEXT  " part of " OPENSSL_VERSION_TEXT
 
 
index 534899bbce0ecae541e534c4079e4faeedf12ae7..04b9d695b0d67f9ec5e869341c68db6397779750 100644 (file)
@@ -313,6 +313,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
        {
        static volatile int stirred_pool = 0;
        int i,j,k,st_num,st_idx;
+       int num_ceil;
        int ok;
        long md_c[2];
        unsigned char local_md[MD_DIGEST_LENGTH];
@@ -333,19 +334,24 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
                }
 #endif
 
+       if (num <= 0)
+               return 1;
+       
+       /* round upwards to multiple of MD_DIGEST_LENGTH/2 */
+       num_ceil = (1 + (num-1)/(MD_DIGEST_LENGTH/2)) * (MD_DIGEST_LENGTH/2);
+
        /*
         * (Based on the rand(3) manpage:)
         *
         * For each group of 10 bytes (or less), we do the following:
         *
-        * Input into the hash function the top 10 bytes from the
-        * local 'md' (which is initialized from the global 'md'
-        * before any bytes are generated), the bytes that are
-        * to be overwritten by the random bytes, and bytes from the
-        * 'state' (incrementing looping index).  From this digest output
-        * (which is kept in 'md'), the top (up to) 10 bytes are
-        * returned to the caller and the bottom (up to) 10 bytes are xored
-        * into the 'state'.
+        * Input into the hash function the local 'md' (which is initialized from
+        * the global 'md' before any bytes are generated), the bytes that are to
+        * be overwritten by the random bytes, and bytes from the 'state'
+        * (incrementing looping index). From this digest output (which is kept
+        * in 'md'), the top (up to) 10 bytes are returned to the caller and the
+        * bottom 10 bytes are xored into the 'state'.
+        * 
         * Finally, after we have finished 'num' random bytes for the
         * caller, 'count' (which is incremented) and the local and global 'md'
         * are fed into the hash function and the results are kept in the
@@ -389,11 +395,11 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
 
        if (do_stir_pool)
                {
-               /* Our output function chains only half of 'md', so we better
-                * make sure that the required entropy gets 'evenly distributed'
-                * through 'state', our randomness pool.  The input function
-                * (ssleay_rand_add) chains all of 'md', which makes it more
-                * suitable for this purpose.
+               /* In the output function only half of 'md' remains secret,
+                * so we better make sure that the required entropy gets
+                * 'evenly distributed' through 'state', our randomness pool.
+                * The input function (ssleay_rand_add) chains all of 'md',
+                * which makes it more suitable for this purpose.
                 */
 
                int n = STATE_SIZE; /* so that the complete pool gets accessed */
@@ -418,11 +424,11 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
        md_c[1] = md_count[1];
        memcpy(local_md, md, sizeof md);
 
-       state_index+=num;
+       state_index+=num_ceil;
        if (state_index > state_num)
                state_index %= state_num;
 
-       /* state[st_idx], ..., state[(st_idx + num - 1) % st_num]
+       /* state[st_idx], ..., state[(st_idx + num_ceil - 1) % st_num]
         * are now ours (but other threads may use them too) */
 
        md_count[0] += 1;
@@ -434,6 +440,7 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
 
        while (num > 0)
                {
+               /* num_ceil -= MD_DIGEST_LENGTH/2 */
                j=(num >= MD_DIGEST_LENGTH/2)?MD_DIGEST_LENGTH/2:num;
                num-=j;
                MD_Init(&m);
@@ -444,27 +451,28 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
                        curr_pid = 0;
                        }
 #endif
-               MD_Update(&m,&(local_md[MD_DIGEST_LENGTH/2]),MD_DIGEST_LENGTH/2);
+               MD_Update(&m,local_md,MD_DIGEST_LENGTH);
                MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
 #ifndef PURIFY
                MD_Update(&m,buf,j); /* purify complains */
 #endif
-               k=(st_idx+j)-st_num;
+               k=(st_idx+MD_DIGEST_LENGTH/2)-st_num;
                if (k > 0)
                        {
-                       MD_Update(&m,&(state[st_idx]),j-k);
+                       MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2-k);
                        MD_Update(&m,&(state[0]),k);
                        }
                else
-                       MD_Update(&m,&(state[st_idx]),j);
+                       MD_Update(&m,&(state[st_idx]),MD_DIGEST_LENGTH/2);
                MD_Final(local_md,&m);
 
-               for (i=0; i<j; i++)
+               for (i=0; i<MD_DIGEST_LENGTH/2; i++)
                        {
                        state[st_idx++]^=local_md[i]; /* may compete with other threads */
-                       *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
                        if (st_idx >= st_num)
                                st_idx=0;
+                       if (i < j)
+                               *(buf++)=local_md[i+MD_DIGEST_LENGTH/2];
                        }
                }
 
index 9545f0e1095977e7e4319e57582270149304dd6b..96901f109e64e3cdbd461684c02ff063663ce378 100644 (file)
@@ -127,13 +127,12 @@ function and xor).
 When bytes are extracted from the RNG, the following process is used.
 For each group of 10 bytes (or less), we do the following:
 
-Input into the hash function the top 10 bytes from the local 'md'
-(which is initialized from the global 'md' before any bytes are
-generated), the bytes that are to be overwritten by the random bytes,
-and bytes from the 'state' (incrementing looping index). From this
-digest output (which is kept in 'md'), the top (up to) 10 bytes are
-returned to the caller and the bottom (up to) 10 bytes are xored into
-the 'state'.
+Input into the hash function the local 'md' (which is initialized from
+the global 'md' before any bytes are generated), the bytes that are to
+be overwritten by the random bytes, and bytes from the 'state'
+(incrementing looping index). From this digest output (which is kept
+in 'md'), the top (up to) 10 bytes are returned to the caller and the
+bottom 10 bytes are xored into the 'state'.
 
 Finally, after we have finished 'num' random bytes for the caller,
 'count' (which is incremented) and the local and global 'md' are fed