Re: Linux entropy pool / random number benchmark

2014-11-29 Thread David Christensen

debian-user:

I found some more information on Intel's Secure Key:


https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide

As shown in Figure 3, the DRNG can be thought of as three logical
components forming an asynchronous production pipeline: an entropy
source (ES) that produces random bits from a nondeterministic
hardware process at around 3 Gbps, a conditioner that uses AES (4)
in CBC-MAC (5) mode to distill the entropy into high-quality
nondeterministic random numbers, and two parallel outputs:

A deterministic random bit generator (DRBG) seeded from the
conditioner.

An enhanced, nondeterministic random number generator (ENRNG)
that provides seeds from the entropy conditioner.


I've improved my Linux entropy pool / random number benchmark script 
(see below):


1.  Waits for enough entropy before starting.

2.  Runs at maximum speed until entropy pool gets low.

3.  Continues running only as fast as the entropy pool is refilled.

4.  Added more columns of information, notably cost (entropy bits per 
random number) and efficiency (random number bytes per entropy bit).


5.  Tuned the script parameters for my Wheezy 7.7 i386 machine with a 
Pentium 4 3.4E GHz HT processor (no Secure Key).  (Note that I needed to 
wiggle the mouse for stages #1 and #3.)


6.  Added statistics to help measure random number generation rates for 
stages #2 and #3.



I invite other people to run the script and post the results.


David



$ cat entropy-random-bench
#!/usr/bin/perl
# $Id: entropy-random-bench,v 1.11 2014/11/30 02:25:20 dpchrist Exp $
###
# Argument defaults -- edit to suit:

my $entropy = '/proc/sys/kernel/random/entropy_avail';
my $random  = '/dev/urandom';
my $start_entropy   = 0.8 * 4096;   # bits
my $continue_entropy= 0.2 * 4096;   # bits
my $min_cost= 64;   # bits
my $length  =  8;   # bytes
my $max_trials  = 80;   # each

###
# The rest of the script should not be edited:

use strict;
use warnings;

use Data::Dumper;
use Getopt::Longqw( :config
auto_help
auto_version );
use List::Util  qw( min max sum );
use Pod::Usage;
use Time::HiRes qw( sleep time );

$| = 1;

our $VERSION= sprintf(%d.%03d, q$Revision: 1.11 $ =~ /(\d+)/g);
my $debug   = 0;

sub get_random
{
open(my $fh, $random)  or die error opening $random: $!;
my $buf;
my $n = sysread($fh, $buf, $length);
die nor reading $fh: $! unless defined $n  $n;
return $buf;
}

sub get_entropy
{
open(my $fh, $entropy) or die error opening $entropy: $!;
my $e = $fh;
chomp $e;
return $e;
}

sub print_header
{
print trial   e1  length  timeratecost 
   efficiency\n,
	  -   bitsbytes   seconds bytes/secondbits 
bytes/bit\n,
	  ==  ==  ==  ==  ==  == 
==\n;

}

sub print_row
{
my $trial = shift;
printf %6i  %6i  %6i  %14e  %14e  %6i  %14e\n,
$trial-{trial},
$trial-{e1},
$trial-{length},
$trial-{time},
$trial-{rate},
$trial-{cost},
$trial-{efficiency},
@_;
}

sub lower
{
my @a = sort @_;
my $n = scalar @a;
pop @a for ( 1 .. $n/2 );
return @a;
}

sub middle
{
my @a = sort @_;
my $n = scalar @a;
shift @a for ( 1 .. $n/4 );
pop   @a for ( 1 .. $n/4 );
return @a;
}

sub upper
{
my @a = sort @_;
my $n = scalar @a;
shift @a for ( 1 .. $n/2 );
return @a;
}

sub mean
{
return sum(@_) / scalar @_;
}

sub print_statistics
{
my $trials = shift;
my %stats;

my @rates = map { $_-{rate} } @$trials;
$stats{n_rates} = scalar @rates;

$stats{max_rate}= max  @rates;
$stats{mean_rate}   = mean @rates;
$stats{min_rate}= min  @rates;

$stats{max_middle_rate} = max  middle @rates;
$stats{mean_middle_rate}= mean middle @rates;
$stats{min_middle_rate} = min  middle @rates;

$stats{max_middle_upper_rate}   = max  middle upper @rates;
$stats{mean_middle_upper_rate}  = mean middle upper @rates;
$stats{min_middle_upper_rate}   = min  middle upper @rates;

$stats{max_middle_lower_rate}   = max  middle lower @rates;
$stats{mean_middle_lower_rate}  = mean middle lower @rates;
$stats{min_middle_lower_rate}   = min  middle lower @rates;

print \n;
for my $k (sort keys %stats) {
printf %32s = %s\n, $k, $stats{$k};
}
}

### main
{
my

Linux entropy pool / random number benchmark

2014-11-27 Thread David Christensen

debian-user:

I found some informative articles about Linux and the Intel Secure Key 
processor feature:



https://software.intel.com/en-us/articles/performance-impact-of-intel-secure-key-on-openssl


http://blog.cloudflare.com/ensuring-randomness-with-linuxs-random-number-generator/


It appears that openssl gives you direct access to Secure Key, while the 
Linux kernel uses Secure Key to stir an entropy pool that is fed into 
SHA-1 to produce random numbers.  So, openssl and /dev/random should 
show speed improvements on a processor with Secure Key, and /dev/urandom 
should have better entropy.



Below please find a Perl script for benchmarking the Linux entropy pool 
and random numbers, and two sample runs on a Wheezy 7.7 i386 machine 
with a Pentium 4 3.4E GHz HT processor (does not have Secure Key):


1.  The first run was with an idling machine and a low entropy pool to 
begin with.


2.  The second run was started after rapidly typing random garbage into 
another terminal and continuing to type during the run.



Could somebody with a Secure Key processor please run the script and 
post the results?



David


$ cat `which entropy-random-bench `
#!/usr/bin/perl

eval 'exec /usr/bin/perl  -S $0 ${1+$@}'
if 0; # not running under some shell
# $Id: entropy-random-bench,v 1.7 2014/11/27 21:58:22 dpchrist Exp $
###
# Argument defaults -- edit to suit:

my $entropy = '/proc/sys/kernel/random/entropy_avail';
my $random  = '/dev/urandom';
my $duration=   60.0;   # seconds
my $entropy_upper   = 4095; # bits
my $entropy_lower   =0; # bits
my $nap_upper   =   10.0;   # seconds
my $nap_lower   =1.0E-06;   # seconds
my $gain=   10.0;   # seconds / bit

###
# The rest of the script should not be edited:

use strict;
use warnings;

use Getopt::Longqw(
:config
auto_help
auto_version
);
use Pod::Usage;
use Time::HiRes qw( sleep time );

$| = 1;

our $VERSION= sprintf(%d.%03d, q$Revision: 1.7 $ =~ /(\d+)/g);
my $man;

GetOptions(
entropy=s   = \$entropy,
random=s= \$random,
duration=f  = \$duration,
entropy-upper=f = \$entropy_upper,
entropy-lower=f = \$entropy_lower,
nap-upper=f = \$nap_upper,
nap-lower=f = \$nap_lower,
gain=f  = \$gain,
man = \$man,
) or pod2usage(2);
pod2usage(-exitstatus = 0, -verbose = 2) if $man;

my $entropy_span= $entropy_upper - $entropy_lower;
my $entropy_setpoint= $entropy_upper / 2;
my $nap_span= $nap_upper - $nap_lower;
my $nap_offset  = $nap_upper / 2;

my $err;
my $buf;
my $e1;
my $e2;
my $t1;
my $t2;
my $rate;
my $dt;
my $signal;
my $nap = $nap_lower;
my $lastprint;

open(my $random_fh, $random) or die error opening $random: $!;
$err = sysread($random_fh, $buf, 1);
die error reading $random: $! unless defined $err  $err;

### /proc/sys/kernel/random/entropy_avail is not world-readable, but
### 'cat' can read it (?)
$e1 = `cat $entropy`;
chomp $e1;

print time (seconds)  entropy (bits)  random (bytes/second)\n,
  ==  ==  ==\n;
my $begin = $lastprint = $t1 = time();
my $end = $begin + $duration;
do {
sleep($nap);

$err = sysread($random_fh, $buf, 1);
die error reading $random: $! unless defined $err;

$e2 = `cat $entropy`;
chomp $e2;

$t2 = time();
$dt = $t2 - $t1;
$rate = 1.0 / $dt;
if ($dt  ($lastprint + 1  $t2)) {
$lastprint = $t2;
printf %14.06f  %14i  %22.6f\n,
$t2 - $begin,
$e2,
$rate;
}
$signal = ($e2 - $entropy_setpoint) / $entropy_span;
$nap = -1.0 * $gain * $signal * $nap_span + $nap_offset;
$nap = $nap_lower if $nap$nap_lower;
$nap = $nap_upper if $nap_upper  $nap;
$e1 = $e2;
$t1 = $t2;
} while ($t2  $end);
DONE:

__END__

=head1 NAME

entropy-random-bench - Linux entropy pool / random number benchmark

=head1 SYNOPSIS

 entropy-random-bench.pl [options]

  Options:
   --entropypath to entropy availble file
   --random path to random number file
   --duration   duration of benchmark
   --entropy-upper  upper range value of entropy available
   --entropy-lower  lower range value of entropy available
   --nap-upper  upper range value for sleep() calls
   --nap-lower  upper range value for sleep() calls
   --gain   timing loop proportional gain
   --manprint manual page and exit
   --help