Do nothing special for arc4random_addrandom(), arc4random_pushb(), arc4random_pushk(), arc4random_stir(), they are not implemented in OpenBSD libc. Replace the pure Perl arc4random_bytes(), arc4random_uniform() implementation with arc4random_buf(3), arc4random_uniform(3) Perl XS wrapper for OpenBSD libc functions. --- lib/BSD/arc4random.pm.orig Mon Jun 6 01:19:28 2011 +++ lib/BSD/arc4random.pm Wed Oct 12 17:34:11 2016 @@ -1,5 +1,6 @@ # $MirOS: contrib/hosted/tg/code/BSD::arc4random/lib/BSD/arc4random.pm,v 1.10 2011/06/05 23:19:04 tg Exp $ #- +# Copyright (c) 2016 Alexander Bluhm # Copyright (c) 2008, 2009, 2010, 2011 # Thorsten Glaser # Copyright (c) 2009 @@ -73,35 +74,24 @@ arc4random() sub arc4random_addrandom($) { - my $buf = shift; - - lock($arcfour_lock) if $have_threadlock; - return &arc4random_addrandom_xs($buf); + goto &arc4random; } sub arc4random_pushb($) { - my $buf = shift; - - lock($arcfour_lock) if $have_threadlock; - return &arc4random_pushb_xs($buf); + goto &arc4random; } sub arc4random_pushk($) { - my $buf = shift; - - lock($arcfour_lock) if $have_threadlock; - return &arc4random_pushk_xs($buf); + goto &arc4random; } sub arc4random_stir() { - lock($arcfour_lock) if $have_threadlock; - &arc4random_stir_xs(); return; } @@ -109,80 +99,18 @@ sub arc4random_bytes($;$) { my ($len, $buf) = @_; - my $val; - my $vleft = 0; - my $rv = ''; - my $idx = 0; - if (defined($buf)) { - $val = arc4random_pushb($buf); - $vleft = 4; - } - while (($len - $idx) >= 4) { - if ($vleft < 4) { - $val = arc4random(); - $vleft = 4; - } - vec($rv, $idx / 4, 32) = $val; - $idx += 4; - $vleft = 0; - } - while ($idx < $len) { - if ($vleft == 0) { - $val = arc4random(); - $vleft = 4; - } - vec($rv, $idx, 8) = $val & 0xFF; - $idx++; - $val >>= 8; - $vleft--; - } - return $rv; + lock($arcfour_lock) if $have_threadlock; + return &arc4random_buf_xs($len); } -# Perl implementation of arc4random_uniform(3) -# C implementation contributed by djm@openbsd.org, Jinmei_Tatuya@isc.org -# -# Calculate a uniformly distributed random number less than upper_bound -# avoiding "modulo bias". -# -# Uniformity is achieved by generating new random numbers until the one -# returned is outside the range [0, 2**32 % upper_bound). This -# guarantees the selected random number will be inside -# [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound) -# after reduction modulo upper_bound. - sub arc4random_uniform($) { my $upper_bound = shift; - my $r; - my $min; - return 0 unless defined($upper_bound); - # convert upper_bound to 32-bit UV (unsigned integer value) - $upper_bound &= 0xFFFFFFFF; - return 0 if $upper_bound < 2 || $upper_bound > 0xFFFFFFFF; - - # Calculate (2**32 % upper_bound) avoiding 64-bit math - if ($upper_bound > 0x80000000) { - # 2**32 - upper_bound (only one "value area") - $min = 1 + (~$upper_bound & 0xFFFFFFFF); - } else { - # (2**32 - x) % x == 2**32 % x when x <= 2**31 - $min = (0xFFFFFFFF - $upper_bound + 1) % $upper_bound; - } - - # This could theoretically loop forever but each retry has - # p > 0.5 (worst case, usually far better) of selecting a - # number inside the range we need, so it should rarely need - # to re-roll. - while (1) { - $r = arc4random(); - last if $r >= $min; - } - - return ($r % $upper_bound); + lock($arcfour_lock) if $have_threadlock; + return &arc4random_uniform_xs($upper_bound); } # private implementation for a tied $RANDOM variable