1use ExtUtils::MakeMaker; 2 3# Big thanks to David Oswald for configuration ideas. 4test_and_config(); 5 6WriteMakefile1( 7 NAME => 'Crypt::Random::TESHA2', 8 ABSTRACT => "Random numbers using timer/schedule entropy, aka userspace voodoo entropy", 9 VERSION_FROM => 'lib/Crypt/Random/TESHA2.pm', # finds $VERSION 10 LICENSE => 'perl', 11 AUTHOR => 'Dana A Jacobsen <dana@acm.org>', 12 13 BUILD_REQUIRES=>{ 14 'Test::More' => '0.45', 15 }, 16 PREREQ_PM => { 17 'Exporter' => '5.562', 18 'Digest::SHA' => '5.22', 19 'Time::HiRes' => '1.9711', 20 'base' => 0, 21 'Carp' => 0, 22 }, 23 24 META_MERGE => { 25 resources => { 26 homepage => 'https://github.com/danaj/Crypt-Random-TESHA2', 27 repository => 'https://github.com/danaj/Crypt-Random-TESHA2', 28 }, 29 }, 30 MIN_PERL_VERSION => 5.006002, 31); 32 33sub WriteMakefile1 { # Cribbed from eumm-upgrade by Alexandr Ciornii 34 my %params = @_; 35 my $eumm_version = $ExtUtils::MakeMaker::VERSION; 36 $eumm_version = eval $eumm_version; 37 38 if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { 39 #EUMM 6.5502 has problems with BUILD_REQUIRES 40 $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; 41 delete $params{BUILD_REQUIRES}; 42 } 43 delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; 44 delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; 45 delete $params{META_MERGE} if $eumm_version < 6.46; 46 delete $params{META_ADD} if $eumm_version < 6.46; 47 delete $params{LICENSE} if $eumm_version < 6.31; 48 delete $params{AUTHOR} if $] < 5.005; 49 delete $params{ABSTRACT_FROM} if $] < 5.005; 50 delete $params{BINARY_LOCATION} if $] < 5.005; 51 52 WriteMakefile(%params); 53} 54 55sub test_and_config { 56 local $| = 1; 57 print "\n"; 58 print "Config: starting initial configuration.\n"; 59 # Test that we can create enough entropy. 60 eval { 61 require Time::HiRes; Time::HiRes->import(qw/gettimeofday usleep/); 62 require Digest::SHA; Digest::SHA->import(qw/sha256/); 63 1; 64 } or do { 65 print "Config: failed to load prerequisites.\n"; 66 return; 67 }; 68 print "Config: gathering."; 69 70 my @vars; 71 foreach my $byte (1..200) { 72 print "." unless $byte % 4; 73 my ($start, $t1, $t2) = gettimeofday(); 74 my $str = pack("LL", $start, $t1); 75 my %dummy; 76 foreach my $bit (1 .. 8) { 77 usleep(2+3*$bit); 78 (undef, $t2) = gettimeofday(); 79 # Note this has nothing to do with the start time or the hash. 80 my $diff = $t2 >= $t1 ? $t2-$t1 : $t2-$t1+1000000; 81 push @vars, $diff - (2+3*$bit); 82 $str .= pack("L", $t1 ^ $t2); 83 $dummy{$str . $_}++ for 1..8; 84 $t1 = $t2; 85 } 86 } 87 print "done\n"; 88 my $H = calc_entropy(@vars); 89 my $Hstr = sprintf("%.2f", $H); 90 my $Hstr8 = sprintf("%.2f", 8 * $H); 91 print "Config: Raw usleep 0-order entropy: $Hstr ($Hstr8 bits per byte).\n"; 92 # Be conservative and assume half what we measured. 93 my $Hbyte = (8 * $H) / 2; 94 # Also assume no more than 7 from a single round. 95 $Hbyte = 7.0 if $Hbyte > 7.0; 96 # Round up to two digits. 97 $Hbyte = sprintf("%.02f", $Hbyte + 0.005); 98 if ($Hbyte < 1.0) { 99 print "Config:\n"; 100 print "Config: ONLY $Hbyte BITS PER OUTPUT BYTE!\n"; 101 print "Config:\n"; 102 print "Config: You should use another source.\n"; 103 print "Config: Configuring for weak mode.\n"; 104 print "\n"; 105 $Hbyte = "1.00"; 106 } 107 print "Config: choosing $Hbyte bits per output byte\n"; 108 print "Config: writing configuration.\n"; 109 110 my $config_path = 'lib/Crypt/Random/TESHA2/Config.pm'; 111 # One possibility is to use the DATA fh, allowing us to just append. 112 # Instead, use DAOSWALD's method. It's more work here, but less there. 113 my $fh; 114 open($fh, "<", $config_path) or 115 do { print "Config: Can't open $config_path!\n$!"; return; }; 116 my @lines = <$fh>; 117 close $fh; 118 for (@lines) { 119 s/^(my \$_entropy_per_byte =).*/$1 $Hbyte;/; 120 } 121 open($fh, ">", $config_path) or 122 do { print "Config: Can't open $config_path!\n$!"; return; }; 123 print $fh @lines or 124 do { print "Config: Can't write to $config_path!\n$!"; return; }; 125 close($fh) or 126 do { print "Config: Can't close $config_path!\n$!"; return; }; 127 open(my $fh, ">>", $config_path) or 128 do { print "Config: Can't open $config_path!\n$!"; return; }; 129 130 print "Config: configuration complete.\n"; 131 print "\n"; 132} 133 134# calculate the 0-order entropy of an array. Returns bits per input. 135sub calc_entropy { 136 my @vals = @_; 137 my $total = scalar @vals; 138 # Compute simple entropy H 139 my %freq; 140 $freq{$_}++ for @vals; 141 my $H = 0; 142 foreach my $f (values %freq) { 143 my $p = $f / $total; 144 $H += $p * log($p); 145 } 146 $H = -$H / log(2); 147 return $H; 148} 149