1/*	$NetBSD: lfsr.h,v 1.1 2024/02/18 20:57:53 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0.  If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16#ifndef ISC_LFSR_H
17#define ISC_LFSR_H 1
18
19/*! \file isc/lfsr.h */
20
21#include <inttypes.h>
22
23#include <isc/lang.h>
24#include <isc/types.h>
25
26typedef struct isc_lfsr isc_lfsr_t;
27
28/*%
29 * This function is called when reseeding is needed.  It is allowed to
30 * modify any state in the LFSR in any way it sees fit OTHER THAN "bits".
31 *
32 * It MUST set "count" to a new value or the lfsr will never reseed again.
33 *
34 * Also, a reseed will never occur in the middle of an extraction.  This
35 * is purely an optimization, and is probably what one would want.
36 */
37typedef void (*isc_lfsrreseed_t)(isc_lfsr_t *, void *);
38
39/*%
40 * The members of this structure can be used by the application, but care
41 * needs to be taken to not change state once the lfsr is in operation.
42 */
43struct isc_lfsr {
44	uint32_t	 state;	 /*%< previous state */
45	unsigned int	 bits;	 /*%< length */
46	uint32_t	 tap;	 /*%< bit taps */
47	unsigned int	 count;	 /*%< reseed count (in BITS!) */
48	isc_lfsrreseed_t reseed; /*%< reseed function */
49	void		*arg;	 /*%< reseed function argument */
50};
51
52ISC_LANG_BEGINDECLS
53
54void
55isc_lfsr_init(isc_lfsr_t *lfsr, uint32_t state, unsigned int bits, uint32_t tap,
56	      unsigned int count, isc_lfsrreseed_t reseed, void *arg);
57/*%<
58 * Initialize an LFSR.
59 *
60 * Note:
61 *
62 *\li	Putting untrusted values into this function will cause the LFSR to
63 *	generate (perhaps) non-maximal length sequences.
64 *
65 * Requires:
66 *
67 *\li	lfsr != NULL
68 *
69 *\li	8 <= bits <= 32
70 *
71 *\li	tap != 0
72 */
73
74void
75isc_lfsr_generate(isc_lfsr_t *lfsr, void *data, unsigned int count);
76/*%<
77 * Returns "count" bytes of data from the LFSR.
78 *
79 * Requires:
80 *
81 *\li	lfsr be valid.
82 *
83 *\li	data != NULL.
84 *
85 *\li	count > 0.
86 */
87
88void
89isc_lfsr_skip(isc_lfsr_t *lfsr, unsigned int skip);
90/*%<
91 * Skip "skip" states.
92 *
93 * Requires:
94 *
95 *\li	lfsr be valid.
96 */
97
98uint32_t
99isc_lfsr_generate32(isc_lfsr_t *lfsr1, isc_lfsr_t *lfsr2);
100/*%<
101 * Given two LFSRs, use the current state from each to skip entries in the
102 * other.  The next states are then xor'd together and returned.
103 *
104 * WARNING:
105 *
106 *\li	This function is used only for very, very low security data, such
107 *	as DNS message IDs where it is desired to have an unpredictable
108 *	stream of bytes that are harder to predict than a simple flooding
109 *	attack.
110 *
111 * Notes:
112 *
113 *\li	Since the current state from each of the LFSRs is used to skip
114 *	state in the other, it is important that no state be leaked
115 *	from either LFSR.
116 *
117 * Requires:
118 *
119 *\li	lfsr1 and lfsr2 be valid.
120 *
121 *\li	1 <= skipbits <= 31
122 */
123
124ISC_LANG_ENDDECLS
125
126#endif /* ISC_LFSR_H */
127