Description: Patch fixes CVE-2011-0766 (cryptographic weakness) vulnerability
 in Erlang SSH application. It is taken from upstream git repository
 https://github.com/erlang/otp/commit/f228601de45c5
Author: Upstream
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=628456
Last-Updated: Tue, 03 Jan 2012 14:05:07 +0400

--- erlang-14.a-dfsg.orig/lib/crypto/c_src/crypto.c
+++ erlang-14.a-dfsg/lib/crypto/c_src/crypto.c
@@ -127,7 +127,9 @@
 static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
 static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -195,7 +197,9 @@
     {"des_ede3_cbc_crypt", 6, des_ede3_cbc_crypt},
     {"aes_cfb_128_crypt", 4, aes_cfb_128_crypt},
     {"rand_bytes", 1, rand_bytes_1},
+    {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
     {"rand_bytes", 3, rand_bytes_3},
+    {"strong_rand_mpint_nif", 3, strong_rand_mpint_nif},
     {"rand_uniform_nif", 2, rand_uniform_nif},
     {"mod_exp_nif", 3, mod_exp_nif},
     {"dss_verify", 4, dss_verify},
@@ -667,6 +671,22 @@
     ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
     return ret;
 }
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes) */     
+    unsigned bytes;
+    unsigned char* data;
+    ERL_NIF_TERM ret;
+    if (!enif_get_uint(env, argv[0], &bytes)) {
+        return enif_make_badarg(env);
+    }
+    data = enif_make_new_binary(env, bytes, &ret);
+    if ( RAND_bytes(data, bytes) != 1) {
+        return atom_false;
+    }
+    ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
+    return ret;
+}
+
 static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
 {/* (Bytes, TopMask, BottomMask) */    
     unsigned bytes;
@@ -687,6 +707,47 @@
     }
     return ret;
 }
+static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes, TopMask, BottomMask) */    
+    unsigned bits;
+    BIGNUM *bn_rand;
+    int top, bottom;
+    unsigned char* data;
+    unsigned dlen;
+    ERL_NIF_TERM ret;
+    if (!enif_get_uint(env, argv[0], &bits)
+        || !enif_get_int(env, argv[1], &top)
+        || !enif_get_int(env, argv[2], &bottom)) {
+        return enif_make_badarg(env);
+    }
+    if (! (top == -1 || top == 0 || top == 1) ) {
+        return enif_make_badarg(env);
+    }
+    if (! (bottom == 0 || bottom == 1) ) {
+        return enif_make_badarg(env);
+    }
+
+    bn_rand = BN_new();
+    if (! bn_rand ) {
+        return enif_make_badarg(env);
+    }
+
+    /* Get a (bits) bit random number */
+    if (!BN_rand(bn_rand, bits, top, bottom)) {
+        ret = atom_false;
+    }
+    else {
+        /* Copy the bignum into an erlang mpint binary. */
+        dlen = BN_num_bytes(bn_rand);
+        data = enif_make_new_binary(env, dlen+4, &ret);
+        put_int32(data, dlen);
+        BN_bn2bin(bn_rand, data+4);
+        ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen);
+    }
+    BN_free(bn_rand);
+
+    return ret;
+}
 
 static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
 {
--- erlang-14.a-dfsg.orig/lib/crypto/doc/src/crypto.xml
+++ erlang-14.a-dfsg/lib/crypto/doc/src/crypto.xml
@@ -587,6 +587,21 @@
       </desc>
     </func>
     <func>
+      <name>strong_rand_bytes(N) -> binary()</name>
+      <fsummary>Generate a binary of random bytes</fsummary>
+      <type>
+        <v>N = integer()</v>
+      </type>
+      <desc>
+        <p>Generates N bytes randomly uniform 0..255, and returns the
+        result in a binary. Uses a cryptographically secure prng seeded and
+        periodically mixed with operating system provided entropy. By default
+        this is the <c>RAND_bytes</c> method from OpenSSL.</p>
+        <p>May throw exception <c>low_entropy</c> in case the random generator
+        failed due to lack of secure "randomness".</p>
+      </desc>
+    </func>
+    <func>
       <name>rand_uniform(Lo, Hi) -> N</name>
       <fsummary>Generate a random number</fsummary>
       <type>
@@ -601,6 +616,31 @@
       </desc>
     </func>
     <func>
+      <name>strong_rand_mpint(N, Top, Bottom) -> Mpint</name>
+      <fsummary>Generate an N bit random number</fsummary>
+      <type>
+        <v>N = non_neg_integer()</v>
+        <v>Top = -1 | 0 | 1</v>
+        <v>Bottom = 0 | 1</v>
+        <v>Mpint = binary()</v>
+      </type>
+      <desc>
+        <p>Generate an N bit random number using OpenSSL's
+        cryptographically strong pseudo random number generator
+        <c>BN_rand</c>.</p>
+        <p>The parameter <c>Top</c> places constraints on the most
+        significant bits of the generated number. If <c>Top</c> is 1, then the
+        two most significant bits will be set to 1, if <c>Top</c> is 0, the
+        most significant bit will be 1, and if <c>Top</c> is -1 then no
+        constraints are applied and thus the generated number may be less than
+        N bits long.</p>
+        <p>If <c>Bottom</c> is 1, then the generated number is
+        constrained to be odd.</p>
+        <p>May throw exception <c>low_entropy</c> in case the random generator
+        failed due to lack of secure "randomness".</p>
+      </desc>
+    </func>
+    <func>
       <name>mod_exp(N, P, M) -> Result</name>
       <fsummary>Perform N ^ P mod M</fsummary>
       <type>
--- erlang-14.a-dfsg.orig/lib/crypto/src/crypto.erl
+++ erlang-14.a-dfsg/lib/crypto/src/crypto.erl
@@ -46,6 +46,7 @@
 -export([rsa_private_encrypt/3, rsa_public_decrypt/3]).
 -export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]).
 -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]).
+-export([strong_rand_bytes/1, strong_rand_mpint/3]).
 -export([mod_exp/3, mpint/1, erlint/1]).
 %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]).
 -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]).
@@ -67,6 +68,8 @@
 		    des_ede3_cbc_encrypt, des_ede3_cbc_decrypt,
 		    aes_cfb_128_encrypt, aes_cfb_128_decrypt,
 		    rand_bytes,
+		    strong_rand_bytes,
+		    strong_rand_mpint,
 		    rand_uniform,
 		    mod_exp,
 		    dss_verify,dss_sign,
@@ -340,12 +343,32 @@
 %% RAND - pseudo random numbers using RN_ functions in crypto lib
 %%
 -spec rand_bytes(non_neg_integer()) -> binary().
+-spec strong_rand_bytes(non_neg_integer()) -> binary().
 -spec rand_uniform(crypto_integer(), crypto_integer()) ->
 			  crypto_integer().
+-spec strong_rand_mpint(Bits::non_neg_integer(),
+      Top::-1..1,
+      Bottom::0..1) -> binary().
 
 rand_bytes(_Bytes) -> ?nif_stub.
+
+strong_rand_bytes(Bytes) ->
+    case strong_rand_bytes_nif(Bytes) of
+        false -> erlang:error(low_entropy);
+        Bin -> Bin
+    end.
+strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
+
 rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
 
+strong_rand_mpint(Bits, Top, Bottom) -> 
+    case strong_rand_mpint_nif(Bits,Top,Bottom) of
+        false -> erlang:error(low_entropy);
+        Bin -> Bin
+    end.
+strong_rand_mpint_nif(_Bits, _Top, _Bottom) -> ?nif_stub.
+
+
 rand_uniform(From,To) when is_binary(From), is_binary(To) ->
     case rand_uniform_nif(From,To) of
 	<<Len:32/integer, MSB, Rest/binary>> when MSB > 127 ->
--- erlang-14.a-dfsg.orig/lib/ssh/src/ssh.appup.src
+++ erlang-14.a-dfsg/lib/ssh/src/ssh.appup.src
@@ -19,8 +19,40 @@
 
 {"%VSN%",	
  [
+  {"2.0.3", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
+             {load_module, ssh_file, soft_purge, soft_purge, []},
+             {load_module, ssh, soft_purge, soft_purge, []},
+             {load_module, ssh_rsa, soft_purge, soft_purge, []},
+             {load_module, ssh_acceptor, soft_purge, soft_purge, []},
+             {load_module, ssh_transport, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
+  {"2.0.2", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
+             {load_module, ssh_file, soft_purge, soft_purge, []},
+             {load_module, ssh, soft_purge, soft_purge, []},
+             {load_module, ssh_rsa, soft_purge, soft_purge, []},
+             {load_module, ssh_acceptor, soft_purge, soft_purge, []},
+             {load_module, ssh_transport, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]}
  ],
  [
+  {"2.0.3", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
+             {load_module, ssh_file, soft_purge, soft_purge, []},
+             {load_module, ssh, soft_purge, soft_purge, []},
+             {load_module, ssh_rsa, soft_purge, soft_purge, []},
+             {load_module, ssh_acceptor, soft_purge, soft_purge, []},
+             {load_module, ssh_transport, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]},
+  {"2.0.2", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_handler, soft_purge, soft_purge, []},
+             {load_module, ssh_file, soft_purge, soft_purge, []},
+             {load_module, ssh, soft_purge, soft_purge, []},
+             {load_module, ssh_rsa, soft_purge, soft_purge, []},
+             {load_module, ssh_acceptor, soft_purge, soft_purge, []},
+             {load_module, ssh_transport, soft_purge, soft_purge, []},
+             {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]}
  ] 
 }.
 
--- erlang-14.a-dfsg.orig/lib/ssh/src/ssh_bits.erl
+++ erlang-14.a-dfsg/lib/ssh/src/ssh_bits.erl
@@ -34,7 +34,7 @@
 %% integer utils
 -export([isize/1]).
 -export([irandom/1, irandom/3]).
--export([random/1, random/3]).
+-export([random/1]).
 -export([xor_bits/2, fill_bits/2]).
 -export([i2bin/2, bin2i/1]).
 
@@ -401,9 +401,6 @@
 irandom(Bits) ->
     irandom(Bits, 1, 0).
 
-%% irandom_odd(Bits) ->
-%%     irandom(Bits, 1, 1).
-
 %%
 %% irandom(N, Top, Bottom)
 %%
@@ -414,57 +411,16 @@
 %%       Bot = 0 - do not set the least signifcant bit
 %%       Bot = 1 - set the least signifcant bit (i.e always odd)
 %%
-irandom(0, _Top, _Bottom) -> 
-    0;
-irandom(Bits, Top, Bottom) ->
-    Bytes = (Bits+7) div 8,
-    Skip  = (8-(Bits rem 8)) rem 8,
-    TMask = case Top of
-		  0 -> 0;
-		  1 -> 16#80;
-		  2 -> 16#c0
-	      end,
-    BMask = case Bottom of
-		0 -> 0;
-		1 -> (1 bsl Skip)
-	    end,
-    <<X:Bits/big-unsigned-integer, _:Skip>> = random(Bytes, TMask, BMask),
-    X.
+irandom(Bits, Top, Bottom) when is_integer(Top),
+                                0 =< Top, Top =< 2 ->
+    crypto:erlint(crypto:strong_rand_mpint(Bits, Top - 1, Bottom)).
 
 %%
 %% random/1
 %%   Generate N random bytes
 %%
 random(N) ->
-    random(N, 0, 0).
-
-random(N, TMask, BMask) ->
-    list_to_binary(rnd(N, TMask, BMask)).
-
-%% random/3
-%%   random(Bytes, TopMask, BotMask)
-%% where 
-%% Bytes is the number of bytes to generate
-%% TopMask is bitwised or'ed to the first byte
-%% BotMask is bitwised or'ed to the last byte
-%%
-rnd(0, _TMask, _BMask) ->
-    [];
-rnd(1, TMask, BMask) ->
-    [(rand8() bor TMask) bor BMask];
-rnd(N, TMask, BMask) ->
-    [(rand8() bor TMask) | rnd_n(N-1, BMask)].
-
-rnd_n(1, BMask) ->
-    [rand8() bor BMask];
-rnd_n(I, BMask) ->
-    [rand8() | rnd_n(I-1, BMask)].
-
-rand8() ->
-    (rand32() bsr 8) band 16#ff.
-
-rand32() ->
-    random:uniform(16#100000000) -1.
+    crypto:strong_rand_bytes(N).
 
 %%
 %% Base 64 encode/decode
--- erlang-14.a-dfsg.orig/lib/ssh/src/ssh_connection_handler.erl
+++ erlang-14.a-dfsg/lib/ssh/src/ssh_connection_handler.erl
@@ -106,8 +106,6 @@
 %% initialize. 
 %%--------------------------------------------------------------------
 init([Role, Manager, Socket, SshOpts]) ->
-    {A,B,C} = erlang:now(),
-    random:seed(A, B, C),
     {NumVsn, StrVsn} = ssh_transport:versions(Role, SshOpts),
     ssh_bits:install_messages(ssh_transport:transport_messages(NumVsn)),
     {Protocol, Callback, CloseTag} = 
