From f505644be64cd4844742b361a8ff411d70f4aa88 Mon Sep 17 00:00:00 2001
From: Niclas Eklund
Date: Fri, 15 Apr 2011 15:49:42 +0200
Subject: Adds NIFs for cryptographically strong random number generation. Also
adds documentation and unit tests.
Thanks to Geoff Cant.
---
lib/crypto/c_src/crypto.c | 60 ++++++++++++++++++++++++++++++++++
lib/crypto/doc/src/crypto.xml | 36 ++++++++++++++++++++
lib/crypto/src/crypto.erl | 15 +++++++++
lib/crypto/test/crypto_SUITE.erl | 31 +++++++++++++++++-
lib/ssh/src/ssh_bits.erl | 54 +++---------------------------
lib/ssh/src/ssh_connection_handler.erl | 2 --
6 files changed, 146 insertions(+), 52 deletions(-)
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index b8786f6f94..d4139f0dfa 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -134,7 +134,9 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(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_uniform_3(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[]);
@@ -204,7 +206,9 @@ static ErlNifFunc nif_funcs[] = {
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
{"rand_bytes", 1, rand_bytes_1},
+ {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
+ {"strong_rand_uniform", 3, strong_rand_uniform_3},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
@@ -704,6 +708,22 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
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;
@@ -724,6 +744,46 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
return ret;
}
+static ERL_NIF_TERM strong_rand_uniform_3(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) ) {
+ return enif_make_badarg(env);
+ }
+
+ /* 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)
{
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index c407350c47..087e9ac00c 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -614,6 +614,19 @@ Mpint() = >]]>
number generator.
+
+ strong_rand_bytes(N) -> binary()
+ Generate a binary of random bytes
+
+ N = integer()
+
+
+ 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 RAND_bytes method from OpenSSL.
+
+
rand_uniform(Lo, Hi) -> N
Generate a random number
@@ -628,6 +641,29 @@ Mpint() = >]]>
multi-precision integers.
+
+ strong_rand_uniform(N, Top, Bottom) -> Mpint
+ Generate an N bit random number
+
+ N = non_neg_integer()
+ Top = -1 | 0 | 1
+ Bottom = 0 | 1
+ Mpint = binary()
+
+
+ Generate an N bit random number using OpenSSL's
+ cryptographically strong pseudo random number generator
+ BN_rand.
+ The parameter Top places constraints on the most
+ significant bits of the generated number. If Top is 1, then the
+ two most significant bits will be set to 1, if Top is 0, the
+ most significant bit will be 1, and if Top is -1 then no
+ constraints are applied and thus the generated number may be less than
+ N bits long.
+ If Bottom is 1, then the generated number is
+ constrained to be odd.
+
+
mod_exp(N, P, M) -> Result
Perform N ^ P mod M
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index d6e2e033c0..153c7833a9 100644
--- a/lib/crypto/src/crypto.erl
+++ b/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_uniform/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]).
@@ -68,6 +69,8 @@
des_ede3_cbc_encrypt, des_ede3_cbc_decrypt,
aes_cfb_128_encrypt, aes_cfb_128_decrypt,
rand_bytes,
+ strong_rand_bytes,
+ strong_rand_uniform,
rand_uniform,
mod_exp,
dss_verify,dss_sign,
@@ -361,11 +364,23 @@ aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
%% 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_uniform(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_uniform(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
rand_uniform(From,To) when is_binary(From), is_binary(To) ->
case rand_uniform_nif(From,To) of
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index fe8f8e69a0..1946d01489 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -46,6 +46,7 @@
aes_ctr/1,
mod_exp_test/1,
rand_uniform_test/1,
+ strong_rand_uniform_test/1,
rsa_verify_test/1,
dsa_verify_test/1,
rsa_sign_test/1,
@@ -68,7 +69,8 @@ all() ->
md5_mac_io, sha, sha_update,
%% sha256, sha256_update, sha512,sha512_update,
des_cbc, aes_cfb, aes_cbc,
- aes_cbc_iter, aes_ctr, des_cbc_iter, des_ecb, rand_uniform_test,
+ aes_cbc_iter, aes_ctr, des_cbc_iter, des_ecb,
+ rand_uniform_test, strong_rand_uniform_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
dsa_sign_test, rsa_encrypt_decrypt, dh, exor_test,
rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64,
@@ -708,6 +710,33 @@ rand_uniform_aux_test(N) ->
?line t(R1 < H),
?line rand_uniform_aux_test(N-1).
+%%
+%%
+strong_rand_uniform_test(doc) ->
+ "strong_rand_uniform and strong_random_bytes testing";
+strong_rand_uniform_test(suite) ->
+ [];
+strong_rand_uniform_test(Config) when is_list(Config) ->
+ strong_rand_uniform_aux_test(180),
+ ?line 10 = byte_size(crypto:strong_rand_bytes(10)).
+
+strong_rand_uniform_aux_test(0) ->
+ ?line t(crypto:strong_rand_uniform(0,0,0) =:= <<0,0,0,0>>),
+ ok;
+strong_rand_uniform_aux_test(1) ->
+ ?line t(crypto:erlint(crypto:strong_rand_uniform(1,0,1)) =:= 1),
+ ?line rand_uniform_aux_test(0);
+strong_rand_uniform_aux_test(N) ->
+ ?line t(sru_length(crypto:strong_rand_uniform(N,-1,0)) =< N),
+ ?line t(sru_length(crypto:strong_rand_uniform(N,0,0)) =:= N),
+ ?line t(crypto:erlint(crypto:strong_rand_uniform(N,0,1)) band 1 =:= 1),
+ ?line t(crypto:erlint(crypto:strong_rand_uniform(N,1,0)) bsr (N - 2) =:= 2#11),
+ ?line rand_uniform_aux_test(N-1).
+
+sru_length(Mpint) ->
+ I = crypto:erlint(Mpint),
+ length(erlang:integer_to_list(I, 2)).
+
%%
%%
%%
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 399581a0fd..50bde83cdb 100755
--- a/lib/ssh/src/ssh_bits.erl
+++ b/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 @@ xor_bits(XBits, YBits) ->
irandom(Bits) ->
irandom(Bits, 1, 0).
-%% irandom_odd(Bits) ->
-%% irandom(Bits, 1, 1).
-
%%
%% irandom(N, Top, Bottom)
%%
@@ -414,57 +411,16 @@ irandom(Bits) ->
%% 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,
- <> = random(Bytes, TMask, BMask),
- X.
+irandom(Bits, Top, Bottom) when is_integer(Top),
+ 0 =< Top, Top =< 2 ->
+ crypto:erlint(crypto:strong_rand_uniform(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
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index 0ba11b0a26..a7340b280c 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -106,8 +106,6 @@ peer_address(ConnectionHandler) ->
%% 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} =
--
cgit v1.2.3
From c31065c750e37d5368398e9e2a741a1d4ec0588c Mon Sep 17 00:00:00 2001
From: Niclas Eklund
Date: Mon, 18 Apr 2011 14:58:18 +0200
Subject: Fixed SSH appup, copyright headers SSH vsn and SSH release note.
---
lib/crypto/src/crypto.erl | 2 +-
lib/ssh/doc/src/notes.xml | 13 +++++++++++++
lib/ssh/src/ssh.appup.src | 26 ++++++++++++++++++--------
lib/ssh/src/ssh_bits.erl | 2 +-
lib/ssh/src/ssh_connection_handler.erl | 2 +-
lib/ssh/vsn.mk | 2 +-
6 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 153c7833a9..99b683fce2 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1999-2010. All Rights Reserved.
+%% Copyright Ericsson AB 1999-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/doc/src/notes.xml b/lib/ssh/doc/src/notes.xml
index af667b1a71..224b9d4af7 100644
--- a/lib/ssh/doc/src/notes.xml
+++ b/lib/ssh/doc/src/notes.xml
@@ -29,6 +29,19 @@
notes.xml
+Ssh 2.0.5
+ Improvements and New Features
+
+ -
+
+ Strengthened random number generation. (Thanks to Geoff Cant)
+
+ Own Id: OTP-9225
+
+
+
+
+
Ssh 2.0.4
Fixed Bugs and Malfunctions
diff --git a/lib/ssh/src/ssh.appup.src b/lib/ssh/src/ssh.appup.src
index 501da8ceb9..9be8c3c7d5 100644
--- a/lib/ssh/src/ssh.appup.src
+++ b/lib/ssh/src/ssh.appup.src
@@ -19,34 +19,44 @@
{"%VSN%",
[
- {"2.0.3", [{load_module, ssh_file, soft_purge, soft_purge, []},
+ {"2.0.4", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+ {load_module, ssh_connection_handler, 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_file, 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.1", [{restart_application, ssh}]}
+ {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]}
],
[
- {"2.0.3", [{load_module, ssh_file, soft_purge, soft_purge, []},
+ {"2.0.4", [{load_module, ssh_bits, soft_purge, soft_purge, []},
+ {load_module, ssh_connection_handler, 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_file, 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.1", [{restart_application, ssh}]}
+ {load_module, ssh_connection_manager, soft_purge, soft_purge, []}]}
]
}.
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index 50bde83cdb..ae89f31355 100755
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2005-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/src/ssh_connection_handler.erl b/lib/ssh/src/ssh_connection_handler.erl
index a7340b280c..2d82e6d77d 100644
--- a/lib/ssh/src/ssh_connection_handler.erl
+++ b/lib/ssh/src/ssh_connection_handler.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2010. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
diff --git a/lib/ssh/vsn.mk b/lib/ssh/vsn.mk
index 51f9f47446..8c9f671fd5 100644
--- a/lib/ssh/vsn.mk
+++ b/lib/ssh/vsn.mk
@@ -1,5 +1,5 @@
#-*-makefile-*- ; force emacs to enter makefile-mode
-SSH_VSN = 2.0.4
+SSH_VSN = 2.0.5
APP_VSN = "ssh-$(SSH_VSN)"
--
cgit v1.2.3
From afe36b58bb77012f94b19213ed9602c2eb9fd420 Mon Sep 17 00:00:00 2001
From: Niclas Eklund
Date: Tue, 19 Apr 2011 13:35:29 +0200
Subject: Renamed the function strong_rand_uniform to strong_rand_mpint. Added
some checks in crypto.erl and crypto.c. Changed ssh_bits to use
strong_rand_mpint.
---
lib/crypto/c_src/crypto.c | 25 +++++++++++++------------
lib/crypto/doc/src/crypto.xml | 8 ++++++--
lib/crypto/doc/src/notes.xml | 17 ++++++++++++++++-
lib/crypto/src/crypto.erl | 20 ++++++++++++++------
lib/crypto/test/crypto_SUITE.erl | 38 +++++++++++++++++++-------------------
lib/crypto/vsn.mk | 2 +-
lib/ssh/src/ssh_bits.erl | 2 +-
7 files changed, 70 insertions(+), 42 deletions(-)
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index d4139f0dfa..3ebf62d87c 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -136,7 +136,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
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_uniform_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[]);
@@ -208,7 +208,7 @@ static ErlNifFunc nif_funcs[] = {
{"rand_bytes", 1, rand_bytes_1},
{"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
- {"strong_rand_uniform", 3, strong_rand_uniform_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},
@@ -744,7 +744,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
return ret;
}
-static ERL_NIF_TERM strong_rand_uniform_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[])
{/* (Bytes, TopMask, BottomMask) */
unsigned bits;
BIGNUM *bn_rand;
@@ -770,16 +770,17 @@ static ERL_NIF_TERM strong_rand_uniform_3(ErlNifEnv* env, int argc, const ERL_NI
}
/* Get a (bits) bit random number */
- if (! BN_rand(bn_rand, bits, top, bottom) ) {
- return enif_make_badarg(env);
+ 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);
}
-
- /* 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;
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 087e9ac00c..dd40378f29 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -4,7 +4,7 @@
@@ -642,7 +644,7 @@ Mpint() = >]]>
- strong_rand_uniform(N, Top, Bottom) -> Mpint
+ strong_rand_mpint(N, Top, Bottom) -> Mpint
Generate an N bit random number
N = non_neg_integer()
@@ -662,6 +664,8 @@ Mpint() = >]]>
N bits long.
If Bottom is 1, then the generated number is
constrained to be odd.
+ May throw exception low_entropy in case the random generator
+ failed due to lack of secure "randomness".
diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml
index 5e9bda3920..ab1ffa9e5c 100644
--- a/lib/crypto/doc/src/notes.xml
+++ b/lib/crypto/doc/src/notes.xml
@@ -4,7 +4,7 @@
- 19992010
+ 19992011
Ericsson AB. All Rights Reserved.
@@ -30,6 +30,21 @@
This document describes the changes made to the Crypto application.
+Crypto 2.0.2.2
+
+ Improvements and New Features
+
+ -
+
+ Strengthened random number generation. (Thanks to Geoff Cant)
+
+ Own Id: OTP-9225
+
+
+
+
+
+
Crypto 2.0.2.1
Improvements and New Features
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 99b683fce2..cc7b3acc9c 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -46,7 +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_uniform/3]).
+-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]).
@@ -70,7 +70,7 @@
aes_cfb_128_encrypt, aes_cfb_128_decrypt,
rand_bytes,
strong_rand_bytes,
- strong_rand_uniform,
+ strong_rand_mpint,
rand_uniform,
mod_exp,
dss_verify,dss_sign,
@@ -367,11 +367,12 @@ aes_cfb_128_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
-spec strong_rand_bytes(non_neg_integer()) -> binary().
-spec rand_uniform(crypto_integer(), crypto_integer()) ->
crypto_integer().
--spec strong_rand_uniform(Bits::non_neg_integer(),
- Top::-1..1,
- Bottom::0..1) -> binary().
+-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);
@@ -380,7 +381,14 @@ strong_rand_bytes(Bytes) ->
strong_rand_bytes_nif(_Bytes) -> ?nif_stub.
rand_bytes(_Bytes, _Topmask, _Bottommask) -> ?nif_stub.
-strong_rand_uniform(_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
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 1946d01489..854a8b4485 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -46,7 +46,7 @@
aes_ctr/1,
mod_exp_test/1,
rand_uniform_test/1,
- strong_rand_uniform_test/1,
+ strong_rand_test/1,
rsa_verify_test/1,
dsa_verify_test/1,
rsa_sign_test/1,
@@ -70,7 +70,7 @@ all() ->
%% sha256, sha256_update, sha512,sha512_update,
des_cbc, aes_cfb, aes_cbc,
aes_cbc_iter, aes_ctr, des_cbc_iter, des_ecb,
- rand_uniform_test, strong_rand_uniform_test,
+ rand_uniform_test, strong_rand_test,
rsa_verify_test, dsa_verify_test, rsa_sign_test,
dsa_sign_test, rsa_encrypt_decrypt, dh, exor_test,
rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64,
@@ -712,26 +712,26 @@ rand_uniform_aux_test(N) ->
%%
%%
-strong_rand_uniform_test(doc) ->
- "strong_rand_uniform and strong_random_bytes testing";
-strong_rand_uniform_test(suite) ->
+strong_rand_test(doc) ->
+ "strong_rand_mpint and strong_random_bytes testing";
+strong_rand_test(suite) ->
[];
-strong_rand_uniform_test(Config) when is_list(Config) ->
- strong_rand_uniform_aux_test(180),
+strong_rand_test(Config) when is_list(Config) ->
+ strong_rand_aux_test(180),
?line 10 = byte_size(crypto:strong_rand_bytes(10)).
-strong_rand_uniform_aux_test(0) ->
- ?line t(crypto:strong_rand_uniform(0,0,0) =:= <<0,0,0,0>>),
+strong_rand_aux_test(0) ->
+ ?line t(crypto:strong_rand_mpint(0,0,0) =:= <<0,0,0,0>>),
ok;
-strong_rand_uniform_aux_test(1) ->
- ?line t(crypto:erlint(crypto:strong_rand_uniform(1,0,1)) =:= 1),
- ?line rand_uniform_aux_test(0);
-strong_rand_uniform_aux_test(N) ->
- ?line t(sru_length(crypto:strong_rand_uniform(N,-1,0)) =< N),
- ?line t(sru_length(crypto:strong_rand_uniform(N,0,0)) =:= N),
- ?line t(crypto:erlint(crypto:strong_rand_uniform(N,0,1)) band 1 =:= 1),
- ?line t(crypto:erlint(crypto:strong_rand_uniform(N,1,0)) bsr (N - 2) =:= 2#11),
- ?line rand_uniform_aux_test(N-1).
+strong_rand_aux_test(1) ->
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(1,0,1)) =:= 1),
+ ?line strong_rand_aux_test(0);
+strong_rand_aux_test(N) ->
+ ?line t(sru_length(crypto:strong_rand_mpint(N,-1,0)) =< N),
+ ?line t(sru_length(crypto:strong_rand_mpint(N,0,0)) =:= N),
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(N,0,1)) band 1 =:= 1),
+ ?line t(crypto:erlint(crypto:strong_rand_mpint(N,1,0)) bsr (N - 2) =:= 2#11),
+ ?line strong_rand_aux_test(N-1).
sru_length(Mpint) ->
I = crypto:erlint(Mpint),
@@ -1126,7 +1126,7 @@ worker_loop(0, _) ->
ok;
worker_loop(N, Config) ->
Funcs = { md5, md5_update, md5_mac, md5_mac_io, sha, sha_update, des_cbc,
- aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test,
+ aes_cfb, aes_cbc, des_cbc_iter, rand_uniform_test, strong_rand_test,
rsa_verify_test, exor_test, rc4_test, rc4_stream_test, mod_exp_test },
F = element(random:uniform(size(Funcs)),Funcs),
diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk
index e2d6fd0b37..740c68d8fa 100644
--- a/lib/crypto/vsn.mk
+++ b/lib/crypto/vsn.mk
@@ -1 +1 @@
-CRYPTO_VSN = 2.0.2.1
+CRYPTO_VSN = 2.0.2.2
diff --git a/lib/ssh/src/ssh_bits.erl b/lib/ssh/src/ssh_bits.erl
index ae89f31355..3f0a06575c 100755
--- a/lib/ssh/src/ssh_bits.erl
+++ b/lib/ssh/src/ssh_bits.erl
@@ -413,7 +413,7 @@ irandom(Bits) ->
%%
irandom(Bits, Top, Bottom) when is_integer(Top),
0 =< Top, Top =< 2 ->
- crypto:erlint(crypto:strong_rand_uniform(Bits, Top - 1, Bottom)).
+ crypto:erlint(crypto:strong_rand_mpint(Bits, Top - 1, Bottom)).
%%
%% random/1
--
cgit v1.2.3