4 * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: lfsr.c,v 1.20 2007/06/19 23:47:17 tbox Exp */
29 #include <isc/assertions.h>
33 #define VALID_LFSR(x) (x != NULL)
36 isc_lfsr_init(isc_lfsr_t
*lfsr
, isc_uint32_t state
, unsigned int bits
,
37 isc_uint32_t tap
, unsigned int count
,
38 isc_lfsrreseed_t reseed
, void *arg
)
40 REQUIRE(VALID_LFSR(lfsr
));
41 REQUIRE(8 <= bits
&& bits
<= 32);
48 lfsr
->reseed
= reseed
;
51 if (count
== 0 && reseed
!= NULL
)
54 lfsr
->state
= 0xffffffffU
>> (32 - lfsr
->bits
);
58 * Return the next state of the lfsr.
60 static inline isc_uint32_t
61 lfsr_generate(isc_lfsr_t
*lfsr
)
65 * If the previous state is zero, we must fill it with something
66 * here, or we will begin to generate an extremely predictable output.
68 * First, give the reseed function a crack at it. If the state is
69 * still 0, set it to all ones.
71 if (lfsr
->state
== 0) {
72 if (lfsr
->reseed
!= NULL
)
73 lfsr
->reseed(lfsr
, lfsr
->arg
);
75 lfsr
->state
= 0xffffffffU
>> (32 - lfsr
->bits
);
78 if (lfsr
->state
& 0x01) {
79 lfsr
->state
= (lfsr
->state
>> 1) ^ lfsr
->tap
;
88 isc_lfsr_generate(isc_lfsr_t
*lfsr
, void *data
, unsigned int count
)
94 REQUIRE(VALID_LFSR(lfsr
));
95 REQUIRE(data
!= NULL
);
103 for (bit
= 0; bit
< 7; bit
++) {
104 *p
|= lfsr_generate(lfsr
);
107 *p
|= lfsr_generate(lfsr
);
111 if (lfsr
->count
!= 0 && lfsr
->reseed
!= NULL
) {
112 if (lfsr
->count
<= count
* 8)
113 lfsr
->reseed(lfsr
, lfsr
->arg
);
115 lfsr
->count
-= (count
* 8);
119 static inline isc_uint32_t
120 lfsr_skipgenerate(isc_lfsr_t
*lfsr
, unsigned int skip
)
123 (void)lfsr_generate(lfsr
);
125 (void)lfsr_generate(lfsr
);
127 return (lfsr
->state
);
131 * Skip "skip" states in "lfsr".
134 isc_lfsr_skip(isc_lfsr_t
*lfsr
, unsigned int skip
)
136 REQUIRE(VALID_LFSR(lfsr
));
139 (void)lfsr_generate(lfsr
);
143 * Skip states in lfsr1 and lfsr2 using the other's current state.
144 * Return the final state of lfsr1 ^ lfsr2.
147 isc_lfsr_generate32(isc_lfsr_t
*lfsr1
, isc_lfsr_t
*lfsr2
)
149 isc_uint32_t state1
, state2
;
150 isc_uint32_t skip1
, skip2
;
152 REQUIRE(VALID_LFSR(lfsr1
));
153 REQUIRE(VALID_LFSR(lfsr2
));
155 skip1
= lfsr1
->state
& 0x01;
156 skip2
= lfsr2
->state
& 0x01;
159 state1
= lfsr_skipgenerate(lfsr1
, skip2
);
160 state2
= lfsr_skipgenerate(lfsr2
, skip1
);
162 return (state1
^ state2
);