// SPDX-License-Identifier: GPL-2.0
/*
* This is a maximally equidistributed combined Tausworthe generator
* based on code from GNU Scientific Library 1.5 (30 Jun 2004)
*
* lfsr113 version:
*
* x_n = (s1_n ^ s2_n ^ s3_n ^ s4_n)
*
* s1_{n+1} = (((s1_n & 4294967294) << 18) ^ (((s1_n << 6) ^ s1_n) >> 13))
* s2_{n+1} = (((s2_n & 4294967288) << 2) ^ (((s2_n << 2) ^ s2_n) >> 27))
* s3_{n+1} = (((s3_n & 4294967280) << 7) ^ (((s3_n << 13) ^ s3_n) >> 21))
* s4_{n+1} = (((s4_n & 4294967168) << 13) ^ (((s4_n << 3) ^ s4_n) >> 12))
*
* The period of this generator is about 2^113 (see erratum paper).
*
* From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
* Generators", Mathematics of Computation, 65, 213 (1996), 203--213:
* http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
* ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
*
* There is an erratum in the paper "Tables of Maximally Equidistributed
* Combined LFSR Generators", Mathematics of Computation, 68, 225 (1999),
* 261--269: http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
*
* ... the k_j most significant bits of z_j must be non-zero,
* for each j. (Note: this restriction also applies to the
* computer code given in [4], but was mistakenly not mentioned
* in that paper.)
*
* This affects the seeding procedure by imposing the requirement
* s1 > 1, s2 > 7, s3 > 15, s4 > 127.
*/
#include <linux/types.h>
#include <linux/percpu.h>
#include <linux/export.h>
#include <linux/jiffies.h>
#include <linux/prandom.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/slab.h>
#include <linux/unaligned.h>
/**
* prandom_u32_state - seeded pseudo-random number generator.
* @state: pointer to state structure holding seeded state.
*
* This is used for pseudo-randomness with no outside seeding.
* For more random results, use get_random_u32().
*/
u32 prandom_u32_state(
struct rnd_state *state)
{
#define TAUSWORTHE(s, a, b, c, d) ((s & c) << d) ^ (((s << a) ^ s) >> b)
state->s1 = TAUSWORTHE(state->s1,
6 U,
13 U,
4294967294 U,
18 U);
state->s2 = TAUSWORTHE(state->s2,
2 U,
27 U,
4294967288 U,
2 U);
state->s3 = TAUSWORTHE(state->s3,
13 U,
21 U,
4294967280 U,
7 U);
state->s4 = TAUSWORTHE(state->s4,
3 U,
12 U,
4294967168 U,
13 U);
return (state->s1 ^ state->s2 ^ state->s3 ^ state->s4);
}
EXPORT_SYMBOL(prandom_u32_state);
/**
* prandom_bytes_state - get the requested number of pseudo-random bytes
*
* @state: pointer to state structure holding seeded state.
* @buf: where to copy the pseudo-random bytes to
* @bytes: the requested number of bytes
*
* This is used for pseudo-randomness with no outside seeding.
* For more random results, use get_random_bytes().
*/
void prandom_bytes_state(
struct rnd_state *state,
void *buf, size_t bytes)
{
u8 *ptr = buf;
while (bytes >=
sizeof (u32)) {
put_unaligned(prandom_u32_state(state), (u32 *) ptr);
ptr +=
sizeof (u32);
bytes -=
sizeof (u32);
}
if (bytes >
0 ) {
u32 rem = prandom_u32_state(state);
do {
*ptr++ = (u8) rem;
bytes--;
rem >>= BITS_PER_BYTE;
}
while (bytes >
0 );
}
}
EXPORT_SYMBOL(prandom_bytes_state);
static void prandom_warmup(
struct rnd_state *state)
{
/* Calling RNG ten times to satisfy recurrence condition */
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
prandom_u32_state(state);
}
void prandom_seed_full_state(
struct rnd_state __percpu *pcpu_state)
{
int i;
for_each_possible_cpu(i) {
struct rnd_state *state = per_cpu_ptr(pcpu_state, i);
u32 seeds[
4 ];
get_random_bytes(&seeds,
sizeof (seeds));
state->s1 = __seed(seeds[
0 ],
2 U);
state->s2 = __seed(seeds[
1 ],
8 U);
state->s3 = __seed(seeds[
2 ],
16 U);
state->s4 = __seed(seeds[
3 ],
128 U);
prandom_warmup(state);
}
}
EXPORT_SYMBOL(prandom_seed_full_state);
#ifdef CONFIG_RANDOM32_SELFTEST
static struct prandom_test1 {
u32 seed;
u32 result;
} test1[] = {
{
1 U,
3484351685 U },
{
2 U,
2623130059 U },
{
3 U,
3125133893 U },
{
4 U,
984847254 U },
};
static struct prandom_test2 {
u32 seed;
u32 iteration;
u32 result;
} test2[] = {
/* Test cases against taus113 from GSL library. */
{
931557656 U,
959 U,
2975593782 U },
{
1339693295 U,
876 U,
3887776532 U },
{
1545556285 U,
961 U,
1615538833 U },
{
601730776 U,
723 U,
1776162651 U },
{
1027516047 U,
687 U,
511983079 U },
{
416526298 U,
700 U,
916156552 U },
{
1395522032 U,
652 U,
2222063676 U },
{
366221443 U,
617 U,
2992857763 U },
{
1539836965 U,
714 U,
3783265725 U },
{
556206671 U,
994 U,
799626459 U },
{
684907218 U,
799 U,
367789491 U },
{
2121230701 U,
931 U,
2115467001 U },
{
1668516451 U,
644 U,
3620590685 U },
{
768046066 U,
883 U,
2034077390 U },
{
1989159136 U,
833 U,
1195767305 U },
{
536585145 U,
996 U,
3577259204 U },
{
1008129373 U,
642 U,
1478080776 U },
{
1740775604 U,
939 U,
1264980372 U },
{
1967883163 U,
508 U,
10734624 U },
{
1923019697 U,
730 U,
3821419629 U },
{
442079932 U,
560 U,
3440032343 U },
{
1961302714 U,
845 U,
841962572 U },
{
2030205964 U,
962 U,
1325144227 U },
{
1160407529 U,
507 U,
240940858 U },
{
635482502 U,
779 U,
4200489746 U },
{
1252788931 U,
699 U,
867195434 U },
{
1961817131 U,
719 U,
668237657 U },
{
1071468216 U,
983 U,
917876630 U },
{
1281848367 U,
932 U,
1003100039 U },
{
582537119 U,
780 U,
1127273778 U },
{
1973672777 U,
853 U,
1071368872 U },
{
1896756996 U,
762 U,
1127851055 U },
{
847917054 U,
500 U,
1717499075 U },
{
1240520510 U,
951 U,
2849576657 U },
{
1685071682 U,
567 U,
1961810396 U },
{
1516232129 U,
557 U,
3173877 U },
{
1208118903 U,
612 U,
1613145022 U },
{
1817269927 U,
693 U,
4279122573 U },
{
1510091701 U,
717 U,
638191229 U },
{
365916850 U,
807 U,
600424314 U },
{
399324359 U,
702 U,
1803598116 U },
{
1318480274 U,
779 U,
2074237022 U },
{
697758115 U,
840 U,
1483639402 U },
{
1696507773 U,
840 U,
577415447 U },
{
2081979121 U,
981 U,
3041486449 U },
{
955646687 U,
742 U,
3846494357 U },
{
1250683506 U,
749 U,
836419859 U },
{
595003102 U,
534 U,
366794109 U },
{
47485338 U,
558 U,
3521120834 U },
{
619433479 U,
610 U,
3991783875 U },
{
704096520 U,
518 U,
4139493852 U },
{
1712224984 U,
606 U,
2393312003 U },
{
1318233152 U,
922 U,
3880361134 U },
{
855572992 U,
761 U,
1472974787 U },
{
64721421 U,
703 U,
683860550 U },
{
678931758 U,
840 U,
380616043 U },
{
692711973 U,
778 U,
1382361947 U },
{
677703619 U,
530 U,
2826914161 U },
{
92393223 U,
586 U,
1522128471 U },
{
1222592920 U,
743 U,
3466726667 U },
{
358288986 U,
695 U,
1091956998 U },
{
1935056945 U,
958 U,
514864477 U },
{
735675993 U,
990 U,
1294239989 U },
{
1560089402 U,
897 U,
2238551287 U },
{
70616361 U,
829 U,
22483098 U },
{
368234700 U,
731 U,
2913875084 U },
{
20221190 U,
879 U,
1564152970 U },
{
539444654 U,
682 U,
1835141259 U },
{
1314987297 U,
840 U,
1801114136 U },
{
2019295544 U,
645 U,
3286438930 U },
{
469023838 U,
716 U,
1637918202 U },
{
1843754496 U,
653 U,
2562092152 U },
{
400672036 U,
809 U,
4264212785 U },
{
404722249 U,
965 U,
2704116999 U },
{
600702209 U,
758 U,
584979986 U },
{
519953954 U,
667 U,
2574436237 U },
{
1658071126 U,
694 U,
2214569490 U },
{
420480037 U,
749 U,
3430010866 U },
{
690103647 U,
969 U,
3700758083 U },
{
1029424799 U,
937 U,
3787746841 U },
{
2012608669 U,
506 U,
3362628973 U },
{
1535432887 U,
998 U,
42610943 U },
{
1330635533 U,
857 U,
3040806504 U },
{
1223800550 U,
539 U,
3954229517 U },
{
1322411537 U,
680 U,
3223250324 U },
{
1877847898 U,
945 U,
2915147143 U },
{
1646356099 U,
874 U,
965988280 U },
{
805687536 U,
744 U,
4032277920 U },
{
1948093210 U,
633 U,
1346597684 U },
{
392609744 U,
783 U,
1636083295 U },
{
690241304 U,
770 U,
1201031298 U },
{
1360302965 U,
696 U,
1665394461 U },
{
1220090946 U,
780 U,
1316922812 U },
{
447092251 U,
500 U,
3438743375 U },
{
1613868791 U,
592 U,
828546883 U },
{
523430951 U,
548 U,
2552392304 U },
{
726692899 U,
810 U,
1656872867 U },
{
1364340021 U,
836 U,
3710513486 U },
{
1986257729 U,
931 U,
935013962 U },
{
407983964 U,
921 U,
728767059 U },
};
static void prandom_state_selftest_seed(
struct rnd_state *state, u32 seed)
{
#define LCG(x) ((x) *
69069 U)
/* super-duper LCG */
state->s1 = __seed(LCG(seed),
2 U);
state->s2 = __seed(LCG(state->s1),
8 U);
state->s3 = __seed(LCG(state->s2),
16 U);
state->s4 = __seed(LCG(state->s3),
128 U);
}
static int __init prandom_state_selftest(
void )
{
int i, j, errors =
0 , runs =
0 ;
bool error =
false ;
for (i =
0 ; i < ARRAY_SIZE(test1); i++) {
struct rnd_state state;
prandom_state_selftest_seed(&state, test1[i].seed);
prandom_warmup(&state);
if (test1[i].result != prandom_u32_state(&state))
error =
true ;
}
if (error)
pr_warn(
"prandom: seed boundary self test failed\n" );
else
pr_info(
"prandom: seed boundary self test passed\n" );
for (i =
0 ; i < ARRAY_SIZE(test2); i++) {
struct rnd_state state;
prandom_state_selftest_seed(&state, test2[i].seed);
prandom_warmup(&state);
for (j =
0 ; j < test2[i].iteration -
1 ; j++)
prandom_u32_state(&state);
if (test2[i].result != prandom_u32_state(&state))
errors++;
runs++;
cond_resched();
}
if (errors)
pr_warn(
"prandom: %d/%d self tests failed\n" , errors, runs);
else
pr_info(
"prandom: %d self tests passed\n" , runs);
return 0 ;
}
core_initcall(prandom_state_selftest);
#endif
Messung V0.5 in Prozent C=98 H=74 G=86
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland