2 * THE BEER-WARE LICENSE
4 * <dan@FreeBSD.ORG> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you
6 * think this stuff is worth it, you can buy me a beer in return.
10 * $FreeBSD: src/sys/libkern/arc4random.c,v 1.3.2.2 2001/09/17 07:06:50 silby Exp $
13 #include <sys/types.h>
14 #include <sys/systm.h>
15 #include <sys/random.h>
16 #include <sys/libkern.h>
19 #include <vm/vm_extern.h>
21 #define ARC4_MAXRUNS 16384
22 #define ARC4_RESEED_SECONDS 300
23 #define ARC4_KEYBYTES 32 /* 256 bit key */
29 time_t arc4_nextreseed
;
30 uint8_t arc4_sbox
[256];
33 static struct arc4_data
*arc4_data_pcpu
[MAXCPU
];
35 static uint8_t arc4_randbyte(struct arc4_data
*);
38 arc4_swap(uint8_t *a
, uint8_t *b
)
51 arc4_randomstir(struct arc4_data
*d
)
57 * XXX read_random() returns unsafe numbers if the entropy
58 * device is not loaded -- MarkM.
60 r
= read_random(key
, ARC4_KEYBYTES
, 1);
61 /* If r == 0 || -1, just use what was on the stack. */
63 for (n
= r
; n
< sizeof(key
); n
++)
67 for (n
= 0; n
< 256; n
++) {
68 d
->arc4_j
= (d
->arc4_j
+ d
->arc4_sbox
[n
] + key
[n
]) % 256;
69 arc4_swap(&d
->arc4_sbox
[n
], &d
->arc4_sbox
[d
->arc4_j
]);
73 * Discard early keystream, as per recommendations in:
74 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
76 for (n
= 0; n
< 768 * 4; n
++)
79 /* Reset for next reseed cycle. */
80 d
->arc4_nextreseed
= time_uptime
+ ARC4_RESEED_SECONDS
;
85 * Generate a random byte.
88 arc4_randbyte(struct arc4_data
*d
)
92 d
->arc4_i
= (d
->arc4_i
+ 1) % 256;
93 d
->arc4_j
= (d
->arc4_j
+ d
->arc4_sbox
[d
->arc4_i
]) % 256;
95 arc4_swap(&d
->arc4_sbox
[d
->arc4_i
], &d
->arc4_sbox
[d
->arc4_j
]);
97 arc4_t
= (d
->arc4_sbox
[d
->arc4_i
] + d
->arc4_sbox
[d
->arc4_j
]) % 256;
98 return d
->arc4_sbox
[arc4_t
];
104 struct arc4_data
*d
= arc4_data_pcpu
[mycpuid
];
107 if (++(d
->arc4_numruns
) > ARC4_MAXRUNS
||
108 time_uptime
> d
->arc4_nextreseed
)
111 ret
= arc4_randbyte(d
);
112 ret
|= arc4_randbyte(d
) << 8;
113 ret
|= arc4_randbyte(d
) << 16;
114 ret
|= arc4_randbyte(d
) << 24;
122 struct arc4_data
*d
= arc4_data_pcpu
[mycpuid
];
125 if (++(d
->arc4_numruns
) > ARC4_MAXRUNS
||
126 time_uptime
> d
->arc4_nextreseed
)
129 ret
= arc4_randbyte(d
);
130 ret
|= arc4_randbyte(d
) << 8;
131 ret
|= arc4_randbyte(d
) << 16;
132 ret
|= arc4_randbyte(d
) << 24;
133 ret
|= (uint64_t)arc4_randbyte(d
) << 32;
134 ret
|= (uint64_t)arc4_randbyte(d
) << 40;
135 ret
|= (uint64_t)arc4_randbyte(d
) << 48;
136 ret
|= (uint64_t)arc4_randbyte(d
) << 56;
142 karc4random_buf(void *ptr
, size_t len
)
144 struct arc4_data
*d
= arc4_data_pcpu
[mycpuid
];
148 /* No one call this function in ISR/ithread. */
152 if (++(d
->arc4_numruns
) > ARC4_MAXRUNS
||
153 time_uptime
> d
->arc4_nextreseed
)
157 *p
++ = arc4_randbyte(d
);
165 * Initialize our S-box to its beginning defaults.
168 arc4_init_pcpu(int cpuid
)
173 KASSERT(arc4_data_pcpu
[cpuid
] == NULL
,
174 ("arc4 was initialized on cpu%d", cpuid
));
176 d
= (void *)kmem_alloc3(kernel_map
, sizeof(*d
), VM_SUBSYS_GD
,
178 memset(d
, 0, sizeof(*d
));
180 for (n
= 0; n
< 256; n
++)
181 d
->arc4_sbox
[n
] = (uint8_t)n
;
186 * Discard early keystream, as per recommendations in:
187 * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
189 for (n
= 0; n
< 768 * 4; n
++)
192 arc4_data_pcpu
[cpuid
] = d
;