Separate /dev/random pseudodevice implemenation from kernel entropy pool implementation. Rewrite pseudodevice code to use cprng_strong(9). The new pseudodevice is cloning, so each caller gets bits from a stream generated with its own key. Users of /dev/urandom get their generators keyed on a "best effort" basis -- the kernel will rekey generators whenever the entropy pool hits the high water mark -- while users of /dev/random get their generators rekeyed every time key-length bits are output. The underlying cprng_strong API can use AES-256 or AES-128, but we use AES-128 because of concerns about related-key attacks on AES-256. This improves performance (and reduces entropy pool depletion) significantly for users of /dev/urandom but does cause users of /dev/random to rekey twice as often. Also fixes various bugs (including some missing locking and a reseed-counter overflow in the CTR_DRBG code) found while testing this. For long reads, this generator is approximately 20 times as fast as the old generator (dd with bs=64K yields 53MB/sec on 2Ghz Core2 instead of 2.5MB/sec) and also uses a separate mutex per instance so concurrency is greatly improved. For reads of typical key sizes for modern cryptosystems (16-32 bytes) performance is about the same as the old code: a little better for 32 bytes, a little worse for 16 bytes.diff -r1.16 -r1.17 src/share/man/man4/rnd.4
(tls)
--- src/share/man/man4/rnd.4 2010/03/22 18:58:31 1.16
+++ src/share/man/man4/rnd.4 2011/12/17 20:05:38 1.17
--- src/share/man/man9/cprng.9 2011/11/28 23:29:45 1.3
+++ src/share/man/man9/cprng.9 2011/12/17 20:05:38 1.4
--- src/share/man/man9/rnd.9 2011/11/28 20:19:28 1.18
+++ src/share/man/man9/rnd.9 2011/12/17 20:05:38 1.19
--- src/sys/conf/files 2011/11/19 22:51:21 1.1032
+++ src/sys/conf/files 2011/12/17 20:05:38 1.1033
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | # $NetBSD: files,v 1.1032 2011/11/19 22:51:21 tls Exp $ | 1 | # $NetBSD: files,v 1.1033 2011/12/17 20:05:38 tls Exp $ | |
2 | # @(#)files.newconf 7.5 (Berkeley) 5/10/93 | 2 | # @(#)files.newconf 7.5 (Berkeley) 5/10/93 | |
3 | 3 | |||
4 | version 20100430 | 4 | version 20100430 | |
5 | 5 | |||
6 | # | 6 | # | |
7 | # device classes | 7 | # device classes | |
8 | # | 8 | # | |
9 | devclass disk | 9 | devclass disk | |
10 | devclass tape | 10 | devclass tape | |
11 | devclass ifnet | 11 | devclass ifnet | |
12 | devclass tty | 12 | devclass tty | |
13 | devclass audiodev | 13 | devclass audiodev | |
14 | devclass displaydev | 14 | devclass displaydev | |
@@ -1429,28 +1429,29 @@ file dev/dkwedge/dkwedge_gpt.c dkwedge_m | @@ -1429,28 +1429,29 @@ file dev/dkwedge/dkwedge_gpt.c dkwedge_m | |||
1429 | file dev/dkwedge/dkwedge_mbr.c dkwedge_method_mbr | 1429 | file dev/dkwedge/dkwedge_mbr.c dkwedge_method_mbr | |
1430 | file dev/firmload.c firmload | 1430 | file dev/firmload.c firmload | |
1431 | file dev/fss.c fss | 1431 | file dev/fss.c fss | |
1432 | file dev/keylock.c keylock | 1432 | file dev/keylock.c keylock | |
1433 | file dev/lockstat.c lockstat needs-flag | 1433 | file dev/lockstat.c lockstat needs-flag | |
1434 | file dev/md.c md | 1434 | file dev/md.c md | |
1435 | file dev/midi.c midi | midibus needs-flag | 1435 | file dev/midi.c midi | midibus needs-flag | |
1436 | file dev/midictl.c midisyn | 1436 | file dev/midictl.c midisyn | |
1437 | file dev/midisyn.c midisyn | 1437 | file dev/midisyn.c midisyn | |
1438 | file dev/mm.c | 1438 | file dev/mm.c | |
1439 | file dev/mulaw.c mulaw needs-flag | 1439 | file dev/mulaw.c mulaw needs-flag | |
1440 | file dev/nullcons_subr.c nullcons needs-flag | 1440 | file dev/nullcons_subr.c nullcons needs-flag | |
1441 | file dev/radio.c radio needs-flag | 1441 | file dev/radio.c radio needs-flag | |
1442 | file dev/rnd.c rnd needs-flag | 1442 | file dev/rnd.c | |
1443 | file dev/rndpool.c rnd needs-flag | 1443 | file dev/rndpool.c | |
1444 | file dev/rndpseudo.c rnd needs-flag | |||
1444 | file dev/sequencer.c sequencer needs-flag | 1445 | file dev/sequencer.c sequencer needs-flag | |
1445 | file dev/video.c video needs-flag | 1446 | file dev/video.c video needs-flag | |
1446 | file dev/vnd.c vnd needs-flag | 1447 | file dev/vnd.c vnd needs-flag | |
1447 | file kern/bufq_disksort.c bufq_disksort | 1448 | file kern/bufq_disksort.c bufq_disksort | |
1448 | file kern/bufq_fcfs.c bufq_fcfs | 1449 | file kern/bufq_fcfs.c bufq_fcfs | |
1449 | file kern/bufq_priocscan.c bufq_priocscan | 1450 | file kern/bufq_priocscan.c bufq_priocscan | |
1450 | file kern/bufq_readprio.c bufq_readprio | new_bufq_strategy | 1451 | file kern/bufq_readprio.c bufq_readprio | new_bufq_strategy | |
1451 | file kern/core_elf32.c exec_elf32 | 1452 | file kern/core_elf32.c exec_elf32 | |
1452 | file kern/core_elf64.c exec_elf64 | 1453 | file kern/core_elf64.c exec_elf64 | |
1453 | file kern/core_netbsd.c exec_aout | exec_coff | exec_ecoff | 1454 | file kern/core_netbsd.c exec_aout | exec_coff | exec_ecoff | |
1454 | file kern/cnmagic.c | 1455 | file kern/cnmagic.c | |
1455 | file kern/exec_aout.c exec_aout | 1456 | file kern/exec_aout.c exec_aout | |
1456 | file kern/exec_ecoff.c exec_ecoff | 1457 | file kern/exec_ecoff.c exec_ecoff |
--- src/sys/crypto/nist_ctr_drbg/Attic/nist_ctr_drbg_aes128.h 2011/11/19 22:51:22 1.1
+++ src/sys/crypto/nist_ctr_drbg/Attic/nist_ctr_drbg_aes128.h 2011/12/17 20:05:38 1.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: nist_ctr_drbg_aes128.h,v 1.1 2011/11/19 22:51:22 tls Exp $ */ | 1 | /* $NetBSD: nist_ctr_drbg_aes128.h,v 1.2 2011/12/17 20:05:38 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -63,18 +63,18 @@ | @@ -63,18 +63,18 @@ | |||
63 | #define NIST_BLOCK_OUTLEN_LONGS (NIST_BLOCK_OUTLEN_BYTES / sizeof(long)) | 63 | #define NIST_BLOCK_OUTLEN_LONGS (NIST_BLOCK_OUTLEN_BYTES / sizeof(long)) | |
64 | 64 | |||
65 | typedef NIST_AES_ENCRYPT_CTX NIST_Key; | 65 | typedef NIST_AES_ENCRYPT_CTX NIST_Key; | |
66 | 66 | |||
67 | #define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst) | 67 | #define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst) | |
68 | #define Block_Schedule_Encryption(ctx, key) \ | 68 | #define Block_Schedule_Encryption(ctx, key) \ | |
69 | NIST_AES_Schedule_Encryption(ctx, key, NIST_BLOCK_KEYLEN) | 69 | NIST_AES_Schedule_Encryption(ctx, key, NIST_BLOCK_KEYLEN) | |
70 | 70 | |||
71 | /* | 71 | /* | |
72 | * NIST SP 800-90 March 2007 | 72 | * NIST SP 800-90 March 2007 | |
73 | * 10.2 DRBG Mechanism Based on Block Ciphers | 73 | * 10.2 DRBG Mechanism Based on Block Ciphers | |
74 | * | 74 | * | |
75 | * Table 3 specifies the reseed interval as | 75 | * Table 3 specifies the reseed interval as | |
76 | * <= 2^48. We use 2^32 so we can always be sure it'll fit in an int. | 76 | * <= 2^48. We use 2^31 so we can always be sure it'll fit in an int. | |
77 | */ | 77 | */ | |
78 | #define NIST_CTR_DRBG_RESEED_INTERVAL (0xffffffffU) | 78 | #define NIST_CTR_DRBG_RESEED_INTERVAL (0x7fffffffU) | |
79 | 79 | |||
80 | #endif /* NIST_CTR_DRBG_AES128_H */ | 80 | #endif /* NIST_CTR_DRBG_AES128_H */ |
--- src/sys/crypto/nist_ctr_drbg/Attic/nist_ctr_drbg_aes256.h 2011/11/19 22:51:22 1.1
+++ src/sys/crypto/nist_ctr_drbg/Attic/nist_ctr_drbg_aes256.h 2011/12/17 20:05:38 1.2
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: nist_ctr_drbg_aes256.h,v 1.1 2011/11/19 22:51:22 tls Exp $ */ | 1 | /* $NetBSD: nist_ctr_drbg_aes256.h,v 1.2 2011/12/17 20:05:38 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -63,18 +63,18 @@ | @@ -63,18 +63,18 @@ | |||
63 | #define NIST_BLOCK_OUTLEN_LONGS (NIST_BLOCK_OUTLEN_BYTES / sizeof(long)) | 63 | #define NIST_BLOCK_OUTLEN_LONGS (NIST_BLOCK_OUTLEN_BYTES / sizeof(long)) | |
64 | 64 | |||
65 | typedef NIST_AES_ENCRYPT_CTX NIST_Key; | 65 | typedef NIST_AES_ENCRYPT_CTX NIST_Key; | |
66 | 66 | |||
67 | #define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst) | 67 | #define Block_Encrypt(ctx, src, dst) NIST_AES_ECB_Encrypt(ctx, src, dst) | |
68 | #define Block_Schedule_Encryption(ctx, key) \ | 68 | #define Block_Schedule_Encryption(ctx, key) \ | |
69 | NIST_AES_Schedule_Encryption(ctx, key, NIST_BLOCK_KEYLEN) | 69 | NIST_AES_Schedule_Encryption(ctx, key, NIST_BLOCK_KEYLEN) | |
70 | 70 | |||
71 | /* | 71 | /* | |
72 | * NIST SP 800-90 March 2007 | 72 | * NIST SP 800-90 March 2007 | |
73 | * 10.2 DRBG Mechanism Based on Block Ciphers | 73 | * 10.2 DRBG Mechanism Based on Block Ciphers | |
74 | * | 74 | * | |
75 | * Table 3 specifies the reseed interval as | 75 | * Table 3 specifies the reseed interval as | |
76 | * <= 2^48. We use 2^32 so we can always be sure it'll fit in an int. | 76 | * <= 2^48. We use 2^31 so we can always be sure it'll fit in an int. | |
77 | */ | 77 | */ | |
78 | #define NIST_CTR_DRBG_RESEED_INTERVAL (0xffffffffU) | 78 | #define NIST_CTR_DRBG_RESEED_INTERVAL (0x7fffffffU) | |
79 | 79 | |||
80 | #endif /* NIST_CTR_DRBG_AES256_H */ | 80 | #endif /* NIST_CTR_DRBG_AES256_H */ |
--- src/sys/dev/Attic/rnd.c 2011/11/29 03:50:31 1.88
+++ src/sys/dev/Attic/rnd.c 2011/12/17 20:05:38 1.89
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rnd.c,v 1.88 2011/11/29 03:50:31 tls Exp $ */ | 1 | /* $NetBSD: rnd.c,v 1.89 2011/12/17 20:05:38 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | 8 | * by Michael Graff <explorer@flame.org> and Thor Lancelot Simon. | |
9 | * This code uses ideas and algorithms from the Linux driver written by | 9 | * This code uses ideas and algorithms from the Linux driver written by | |
10 | * Ted Ts'o. | 10 | * Ted Ts'o. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -22,27 +22,27 @@ | @@ -22,27 +22,27 @@ | |||
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 23 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 24 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 25 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
31 | * POSSIBILITY OF SUCH DAMAGE. | 31 | * POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #include <sys/cdefs.h> | 34 | #include <sys/cdefs.h> | |
35 | __KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.88 2011/11/29 03:50:31 tls Exp $"); | 35 | __KERNEL_RCSID(0, "$NetBSD: rnd.c,v 1.89 2011/12/17 20:05:38 tls Exp $"); | |
36 | 36 | |||
37 | #include <sys/param.h> | 37 | #include <sys/param.h> | |
38 | #include <sys/ioctl.h> | 38 | #include <sys/ioctl.h> | |
39 | #include <sys/fcntl.h> | 39 | #include <sys/fcntl.h> | |
40 | #include <sys/select.h> | 40 | #include <sys/select.h> | |
41 | #include <sys/poll.h> | 41 | #include <sys/poll.h> | |
42 | #include <sys/kmem.h> | 42 | #include <sys/kmem.h> | |
43 | #include <sys/mutex.h> | 43 | #include <sys/mutex.h> | |
44 | #include <sys/proc.h> | 44 | #include <sys/proc.h> | |
45 | #include <sys/kernel.h> | 45 | #include <sys/kernel.h> | |
46 | #include <sys/conf.h> | 46 | #include <sys/conf.h> | |
47 | #include <sys/systm.h> | 47 | #include <sys/systm.h> | |
48 | #include <sys/callout.h> | 48 | #include <sys/callout.h> | |
@@ -108,34 +108,29 @@ typedef struct _rnd_sample_t { | @@ -108,34 +108,29 @@ typedef struct _rnd_sample_t { | |||
108 | volatile int rnd_timeout_pending; | 108 | volatile int rnd_timeout_pending; | |
109 | SIMPLEQ_HEAD(, _rnd_sample_t) rnd_samples; | 109 | SIMPLEQ_HEAD(, _rnd_sample_t) rnd_samples; | |
110 | kmutex_t rnd_mtx; | 110 | kmutex_t rnd_mtx; | |
111 | 111 | |||
112 | /* | 112 | /* | |
113 | * Entropy sinks: usually other generators waiting to be rekeyed. | 113 | * Entropy sinks: usually other generators waiting to be rekeyed. | |
114 | * | 114 | * | |
115 | * A sink's callback MUST NOT re-add the sink to the list, or | 115 | * A sink's callback MUST NOT re-add the sink to the list, or | |
116 | * list corruption will occur. | 116 | * list corruption will occur. | |
117 | */ | 117 | */ | |
118 | TAILQ_HEAD(, rndsink) rnd_sinks; | 118 | TAILQ_HEAD(, rndsink) rnd_sinks; | |
119 | 119 | |||
120 | /* | 120 | /* | |
121 | * our select/poll queue | |||
122 | */ | |||
123 | struct selinfo rnd_selq; | |||
124 | ||||
125 | /* | |||
126 | * Memory pool for sample buffers | 121 | * Memory pool for sample buffers | |
127 | */ | 122 | */ | |
128 | static struct pool rnd_mempool; | 123 | static pool_cache_t rnd_mempc; | |
129 | 124 | |||
130 | /* | 125 | /* | |
131 | * Our random pool. This is defined here rather than using the general | 126 | * Our random pool. This is defined here rather than using the general | |
132 | * purpose one defined in rndpool.c. | 127 | * purpose one defined in rndpool.c. | |
133 | * | 128 | * | |
134 | * Samples are collected and queued into a separate mutex-protected queue | 129 | * Samples are collected and queued into a separate mutex-protected queue | |
135 | * (rnd_samples, see above), and processed in a timeout routine; therefore, | 130 | * (rnd_samples, see above), and processed in a timeout routine; therefore, | |
136 | * the mutex protecting the random pool is at IPL_SOFTCLOCK() as well. | 131 | * the mutex protecting the random pool is at IPL_SOFTCLOCK() as well. | |
137 | */ | 132 | */ | |
138 | rndpool_t rnd_pool; | 133 | rndpool_t rnd_pool; | |
139 | kmutex_t rndpool_mtx; | 134 | kmutex_t rndpool_mtx; | |
140 | kcondvar_t rndpool_cv; | 135 | kcondvar_t rndpool_cv; | |
141 | 136 | |||
@@ -149,79 +144,70 @@ static krndsource_t rnd_source_no_collec | @@ -149,79 +144,70 @@ static krndsource_t rnd_source_no_collec | |||
149 | 0, 0, 0, 0, 0, 0, 0 }, | 144 | 0, 0, 0, 0, 0, 0, 0 }, | |
150 | .last_time = 0, .last_delta = 0, .last_delta2 = 0, .total = 0, | 145 | .last_time = 0, .last_delta = 0, .last_delta2 = 0, .total = 0, | |
151 | .type = RND_TYPE_UNKNOWN, | 146 | .type = RND_TYPE_UNKNOWN, | |
152 | .flags = (RND_FLAG_NO_COLLECT | | 147 | .flags = (RND_FLAG_NO_COLLECT | | |
153 | RND_FLAG_NO_ESTIMATE | | 148 | RND_FLAG_NO_ESTIMATE | | |
154 | RND_TYPE_UNKNOWN), | 149 | RND_TYPE_UNKNOWN), | |
155 | .state = NULL, | 150 | .state = NULL, | |
156 | .test_cnt = 0, | 151 | .test_cnt = 0, | |
157 | .test = NULL | 152 | .test = NULL | |
158 | }; | 153 | }; | |
159 | 154 | |||
160 | struct callout rnd_callout; | 155 | struct callout rnd_callout; | |
161 | 156 | |||
162 | void rndattach(int); | 157 | void rnd_wakeup_readers(void); | |
163 | ||||
164 | dev_type_open(rndopen); | |||
165 | dev_type_read(rndread); | |||
166 | dev_type_write(rndwrite); | |||
167 | dev_type_ioctl(rndioctl); | |||
168 | dev_type_poll(rndpoll); | |||
169 | dev_type_kqfilter(rndkqfilter); | |||
170 | ||||
171 | const struct cdevsw rnd_cdevsw = { | |||
172 | rndopen, nullclose, rndread, rndwrite, rndioctl, | |||
173 | nostop, notty, rndpoll, nommap, rndkqfilter, D_OTHER|D_MPSAFE, | |||
174 | }; | |||
175 | ||||
176 | static inline void rnd_wakeup_readers(void); | |||
177 | static inline u_int32_t rnd_estimate_entropy(krndsource_t *, u_int32_t); | 158 | static inline u_int32_t rnd_estimate_entropy(krndsource_t *, u_int32_t); | |
178 | static inline u_int32_t rnd_counter(void); | 159 | static inline u_int32_t rnd_counter(void); | |
179 | static void rnd_timeout(void *); | 160 | static void rnd_timeout(void *); | |
180 | static void rnd_process_events(void *); | 161 | static void rnd_process_events(void *); | |
181 | static u_int32_t rnd_extract_data_locked(void *, u_int32_t, u_int32_t); | 162 | u_int32_t rnd_extract_data_locked(void *, u_int32_t, u_int32_t); /* XXX */ | |
182 | 163 | |||
183 | static int rnd_ready = 0; | 164 | int rnd_ready = 0; | |
184 | static int rnd_have_entropy = 0; | 165 | static int rnd_have_entropy = 0; | |
166 | ||||
167 | #ifdef DIAGNOSTIC | |||
185 | static int rnd_tested = 0; | 168 | static int rnd_tested = 0; | |
169 | static rngtest_t rnd_rt; | |||
170 | static uint8_t rnd_testbits[sizeof(rnd_rt.rt_b)]; | |||
171 | #endif | |||
186 | 172 | |||
187 | LIST_HEAD(, krndsource) rnd_sources; | 173 | LIST_HEAD(, krndsource) rnd_sources; | |
188 | 174 | |||
189 | static rndsave_t *boot_rsp; | 175 | rndsave_t *boot_rsp; | |
190 | /* | 176 | /* | |
191 | * Generate a 32-bit counter. This should be more machine dependent, | 177 | * Generate a 32-bit counter. This should be more machine dependent, | |
192 | * using cycle counters and the like when possible. | 178 | * using cycle counters and the like when possible. | |
193 | */ | 179 | */ | |
194 | static inline u_int32_t | 180 | static inline u_int32_t | |
195 | rnd_counter(void) | 181 | rnd_counter(void) | |
196 | { | 182 | { | |
197 | struct timeval tv; | 183 | struct timeval tv; | |
198 | 184 | |||
199 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | 185 | #if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */ | |
200 | if (cpu_hascounter()) | 186 | if (cpu_hascounter()) | |
201 | return (cpu_counter32()); | 187 | return (cpu_counter32()); | |
202 | #endif | 188 | #endif | |
203 | if (rnd_ready) { | 189 | if (rnd_ready) { | |
204 | microtime(&tv); | 190 | microtime(&tv); | |
205 | return (tv.tv_sec * 1000000 + tv.tv_usec); | 191 | return (tv.tv_sec * 1000000 + tv.tv_usec); | |
206 | } | 192 | } | |
207 | /* when called from rnd_init, its too early to call microtime safely */ | 193 | /* when called from rnd_init, its too early to call microtime safely */ | |
208 | return (0); | 194 | return (0); | |
209 | } | 195 | } | |
210 | 196 | |||
211 | /* | 197 | /* | |
212 | * Check to see if there are readers waiting on us. If so, kick them. | 198 | * Check to see if there are readers waiting on us. If so, kick them. | |
213 | */ | 199 | */ | |
214 | static inline void | 200 | void | |
215 | rnd_wakeup_readers(void) | 201 | rnd_wakeup_readers(void) | |
216 | { | 202 | { | |
217 | rndsink_t *sink, *tsink; | 203 | rndsink_t *sink, *tsink; | |
218 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | 204 | TAILQ_HEAD(, rndsink) sunk = TAILQ_HEAD_INITIALIZER(sunk); | |
219 | 205 | |||
220 | mutex_spin_enter(&rndpool_mtx); | 206 | mutex_spin_enter(&rndpool_mtx); | |
221 | if (rndpool_get_entropy_count(&rnd_pool) < RND_ENTROPY_THRESHOLD * 8) { | 207 | if (rndpool_get_entropy_count(&rnd_pool) < RND_ENTROPY_THRESHOLD * 8) { | |
222 | mutex_spin_exit(&rndpool_mtx); | 208 | mutex_spin_exit(&rndpool_mtx); | |
223 | return; | 209 | return; | |
224 | } | 210 | } | |
225 | 211 | |||
226 | /* | 212 | /* | |
227 | * First, take care of in-kernel consumers needing rekeying. | 213 | * First, take care of in-kernel consumers needing rekeying. | |
@@ -242,29 +228,27 @@ rnd_wakeup_readers(void) | @@ -242,29 +228,27 @@ rnd_wakeup_readers(void) | |||
242 | } | 228 | } | |
243 | } | 229 | } | |
244 | 230 | |||
245 | /* | 231 | /* | |
246 | * If we still have enough new bits to do something, feed userspace. | 232 | * If we still have enough new bits to do something, feed userspace. | |
247 | */ | 233 | */ | |
248 | if (rndpool_get_entropy_count(&rnd_pool) > RND_ENTROPY_THRESHOLD * 8) { | 234 | if (rndpool_get_entropy_count(&rnd_pool) > RND_ENTROPY_THRESHOLD * 8) { | |
249 | #ifdef RND_VERBOSE | 235 | #ifdef RND_VERBOSE | |
250 | if (!rnd_have_entropy) | 236 | if (!rnd_have_entropy) | |
251 | printf("rnd: have initial entropy (%u)\n", | 237 | printf("rnd: have initial entropy (%u)\n", | |
252 | rndpool_get_entropy_count(&rnd_pool)); | 238 | rndpool_get_entropy_count(&rnd_pool)); | |
253 | #endif | 239 | #endif | |
254 | rnd_have_entropy = 1; | 240 | rnd_have_entropy = 1; | |
255 | cv_broadcast(&rndpool_cv); | |||
256 | mutex_spin_exit(&rndpool_mtx); | 241 | mutex_spin_exit(&rndpool_mtx); | |
257 | selnotify(&rnd_selq, 0, 0); | |||
258 | } else { | 242 | } else { | |
259 | mutex_spin_exit(&rndpool_mtx); | 243 | mutex_spin_exit(&rndpool_mtx); | |
260 | } | 244 | } | |
261 | 245 | |||
262 | /* | 246 | /* | |
263 | * Now that we have dropped the mutex, we can run sinks' callbacks. | 247 | * Now that we have dropped the mutex, we can run sinks' callbacks. | |
264 | * Since we have reused the "tailq" member of the sink structure for | 248 | * Since we have reused the "tailq" member of the sink structure for | |
265 | * this temporary on-stack queue, the callback must NEVER re-add | 249 | * this temporary on-stack queue, the callback must NEVER re-add | |
266 | * the sink to the main queue, or our on-stack queue will become | 250 | * the sink to the main queue, or our on-stack queue will become | |
267 | * corrupt. | 251 | * corrupt. | |
268 | */ | 252 | */ | |
269 | while ((sink = TAILQ_FIRST(&sunk))) { | 253 | while ((sink = TAILQ_FIRST(&sunk))) { | |
270 | #ifdef RND_VERBOSE | 254 | #ifdef RND_VERBOSE | |
@@ -314,59 +298,26 @@ rnd_estimate_entropy(krndsource_t *rs, u | @@ -314,59 +298,26 @@ rnd_estimate_entropy(krndsource_t *rs, u | |||
314 | rs->last_delta = delta; | 298 | rs->last_delta = delta; | |
315 | rs->last_delta2 = delta2; | 299 | rs->last_delta2 = delta2; | |
316 | 300 | |||
317 | /* | 301 | /* | |
318 | * If any delta is 0, we got no entropy. If all are non-zero, we | 302 | * If any delta is 0, we got no entropy. If all are non-zero, we | |
319 | * might have something. | 303 | * might have something. | |
320 | */ | 304 | */ | |
321 | if (delta == 0 || delta2 == 0 || delta3 == 0) | 305 | if (delta == 0 || delta2 == 0 || delta3 == 0) | |
322 | return (0); | 306 | return (0); | |
323 | 307 | |||
324 | return (1); | 308 | return (1); | |
325 | } | 309 | } | |
326 | 310 | |||
327 | static int | |||
328 | rnd_mempool_init(void) | |||
329 | { | |||
330 | ||||
331 | pool_init(&rnd_mempool, sizeof(rnd_sample_t), 0, 0, 0, "rndsample", | |||
332 | NULL, IPL_VM); | |||
333 | return 0; | |||
334 | } | |||
335 | static ONCE_DECL(rnd_mempoolinit_ctrl); | |||
336 | ||||
337 | /* | |||
338 | * "Attach" the random device. This is an (almost) empty stub, since | |||
339 | * pseudo-devices don't get attached until after config, after the | |||
340 | * entropy sources will attach. We just use the timing of this event | |||
341 | * as another potential source of initial entropy. | |||
342 | */ | |||
343 | void | |||
344 | rndattach(int num) | |||
345 | { | |||
346 | u_int32_t c; | |||
347 | ||||
348 | RUN_ONCE(&rnd_mempoolinit_ctrl, rnd_mempool_init); | |||
349 | ||||
350 | /* Trap unwary players who don't call rnd_init() early */ | |||
351 | KASSERT(rnd_ready); | |||
352 | ||||
353 | /* mix in another counter */ | |||
354 | c = rnd_counter(); | |||
355 | mutex_spin_enter(&rndpool_mtx); | |||
356 | rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1); | |||
357 | mutex_spin_exit(&rndpool_mtx); | |||
358 | } | |||
359 | ||||
360 | /* | 311 | /* | |
361 | * initialize the global random pool for our use. | 312 | * initialize the global random pool for our use. | |
362 | * rnd_init() must be called very early on in the boot process, so | 313 | * rnd_init() must be called very early on in the boot process, so | |
363 | * the pool is ready for other devices to attach as sources. | 314 | * the pool is ready for other devices to attach as sources. | |
364 | */ | 315 | */ | |
365 | void | 316 | void | |
366 | rnd_init(void) | 317 | rnd_init(void) | |
367 | { | 318 | { | |
368 | u_int32_t c; | 319 | u_int32_t c; | |
369 | 320 | |||
370 | if (rnd_ready) | 321 | if (rnd_ready) | |
371 | return; | 322 | return; | |
372 | 323 | |||
@@ -374,32 +325,34 @@ rnd_init(void) | @@ -374,32 +325,34 @@ rnd_init(void) | |||
374 | 325 | |||
375 | callout_init(&rnd_callout, CALLOUT_MPSAFE); | 326 | callout_init(&rnd_callout, CALLOUT_MPSAFE); | |
376 | callout_setfunc(&rnd_callout, rnd_timeout, NULL); | 327 | callout_setfunc(&rnd_callout, rnd_timeout, NULL); | |
377 | 328 | |||
378 | /* | 329 | /* | |
379 | * take a counter early, hoping that there's some variance in | 330 | * take a counter early, hoping that there's some variance in | |
380 | * the following operations | 331 | * the following operations | |
381 | */ | 332 | */ | |
382 | c = rnd_counter(); | 333 | c = rnd_counter(); | |
383 | 334 | |||
384 | LIST_INIT(&rnd_sources); | 335 | LIST_INIT(&rnd_sources); | |
385 | SIMPLEQ_INIT(&rnd_samples); | 336 | SIMPLEQ_INIT(&rnd_samples); | |
386 | TAILQ_INIT(&rnd_sinks); | 337 | TAILQ_INIT(&rnd_sinks); | |
387 | selinit(&rnd_selq); | |||
388 | 338 | |||
389 | rndpool_init(&rnd_pool); | 339 | rndpool_init(&rnd_pool); | |
390 | mutex_init(&rndpool_mtx, MUTEX_DEFAULT, IPL_VM); | 340 | mutex_init(&rndpool_mtx, MUTEX_DEFAULT, IPL_VM); | |
391 | cv_init(&rndpool_cv, "rndread"); | 341 | cv_init(&rndpool_cv, "rndread"); | |
392 | 342 | |||
343 | rnd_mempc = pool_cache_init(sizeof(rnd_sample_t), 0, 0, 0, | |||
344 | "rndsample", NULL, IPL_VM, | |||
345 | NULL, NULL, NULL); | |||
393 | /* Mix *something*, *anything* into the pool to help it get started. | 346 | /* Mix *something*, *anything* into the pool to help it get started. | |
394 | * However, it's not safe for rnd_counter() to call microtime() yet, | 347 | * However, it's not safe for rnd_counter() to call microtime() yet, | |
395 | * so on some platforms we might just end up with zeros anyway. | 348 | * so on some platforms we might just end up with zeros anyway. | |
396 | * XXX more things to add would be nice. | 349 | * XXX more things to add would be nice. | |
397 | */ | 350 | */ | |
398 | if (c) { | 351 | if (c) { | |
399 | mutex_spin_enter(&rndpool_mtx); | 352 | mutex_spin_enter(&rndpool_mtx); | |
400 | rndpool_add_data(&rnd_pool, &c, sizeof(c), 1); | 353 | rndpool_add_data(&rnd_pool, &c, sizeof(c), 1); | |
401 | c = rnd_counter(); | 354 | c = rnd_counter(); | |
402 | rndpool_add_data(&rnd_pool, &c, sizeof(c), 1); | 355 | rndpool_add_data(&rnd_pool, &c, sizeof(c), 1); | |
403 | mutex_spin_exit(&rndpool_mtx); | 356 | mutex_spin_exit(&rndpool_mtx); | |
404 | } | 357 | } | |
405 | 358 | |||
@@ -418,563 +371,77 @@ rnd_init(void) | @@ -418,563 +371,77 @@ rnd_init(void) | |||
418 | if (rndpool_get_entropy_count(&rnd_pool) > | 371 | if (rndpool_get_entropy_count(&rnd_pool) > | |
419 | RND_ENTROPY_THRESHOLD * 8) { | 372 | RND_ENTROPY_THRESHOLD * 8) { | |
420 | rnd_have_entropy = 1; | 373 | rnd_have_entropy = 1; | |
421 | } | 374 | } | |
422 | mutex_spin_exit(&rndpool_mtx); | 375 | mutex_spin_exit(&rndpool_mtx); | |
423 | #ifdef RND_VERBOSE | 376 | #ifdef RND_VERBOSE | |
424 | printf("rnd: seeded with %d bits\n", | 377 | printf("rnd: seeded with %d bits\n", | |
425 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); | 378 | MIN(boot_rsp->entropy, RND_POOLBITS / 2)); | |
426 | #endif | 379 | #endif | |
427 | memset(boot_rsp, 0, sizeof(*boot_rsp)); | 380 | memset(boot_rsp, 0, sizeof(*boot_rsp)); | |
428 | } | 381 | } | |
429 | } | 382 | } | |
430 | 383 | |||
431 | int | |||
432 | rndopen(dev_t dev, int flags, int ifmt, | |||
433 | struct lwp *l) | |||
434 | { | |||
435 | ||||
436 | if (rnd_ready == 0) | |||
437 | return (ENXIO); | |||
438 | ||||
439 | if (minor(dev) == RND_DEV_URANDOM || minor(dev) == RND_DEV_RANDOM) | |||
440 | return (0); | |||
441 | ||||
442 | return (ENXIO); | |||
443 | } | |||
444 | ||||
445 | int | |||
446 | rndread(dev_t dev, struct uio *uio, int ioflag) | |||
447 | { | |||
448 | u_int8_t *bf; | |||
449 | u_int32_t entcnt, mode, n, nread; | |||
450 | int ret; | |||
451 | ||||
452 | DPRINTF(RND_DEBUG_READ, | |||
453 | ("Random: Read of %zu requested, flags 0x%08x\n", | |||
454 | uio->uio_resid, ioflag)); | |||
455 | ||||
456 | if (uio->uio_resid == 0) | |||
457 | return (0); | |||
458 | ||||
459 | switch (minor(dev)) { | |||
460 | case RND_DEV_RANDOM: | |||
461 | mode = RND_EXTRACT_GOOD; | |||
462 | break; | |||
463 | case RND_DEV_URANDOM: | |||
464 | mode = RND_EXTRACT_ANY; | |||
465 | break; | |||
466 | default: | |||
467 | /* Can't happen, but this is cheap */ | |||
468 | return (ENXIO); | |||
469 | } | |||
470 | ||||
471 | ret = 0; | |||
472 | bf = kmem_alloc(RND_TEMP_BUFFER_SIZE, KM_SLEEP); | |||
473 | while (uio->uio_resid > 0) { | |||
474 | n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid); | |||
475 | ||||
476 | /* | |||
477 | * Make certain there is data available. If there | |||
478 | * is, do the I/O even if it is partial. If not, | |||
479 | * sleep unless the user has requested non-blocking | |||
480 | * I/O. | |||
481 | * | |||
482 | * If not requesting strong randomness, we can always read. | |||
483 | */ | |||
484 | mutex_spin_enter(&rndpool_mtx); | |||
485 | if (mode != RND_EXTRACT_ANY) { | |||
486 | for (;;) { | |||
487 | /* | |||
488 | * How much entropy do we have? | |||
489 | * If it is enough for one hash, we can read. | |||
490 | */ | |||
491 | entcnt = rndpool_get_entropy_count(&rnd_pool); | |||
492 | if (entcnt >= RND_ENTROPY_THRESHOLD * 8) | |||
493 | break; | |||
494 | ||||
495 | /* | |||
496 | * Data is not available. | |||
497 | */ | |||
498 | if (ioflag & IO_NDELAY) { | |||
499 | mutex_spin_exit(&rndpool_mtx); | |||
500 | ret = EWOULDBLOCK; | |||
501 | goto out; | |||
502 | } | |||
503 | ret = cv_wait_sig(&rndpool_cv, &rndpool_mtx); | |||
504 | if (ret) { | |||
505 | mutex_spin_exit(&rndpool_mtx); | |||
506 | goto out; | |||
507 | } | |||
508 | } | |||
509 | } | |||
510 | nread = rnd_extract_data_locked(bf, n, mode); | |||
511 | mutex_spin_exit(&rndpool_mtx); | |||
512 | ||||
513 | /* | |||
514 | * Copy (possibly partial) data to the user. | |||
515 | * If an error occurs, or this is a partial | |||
516 | * read, bail out. | |||
517 | */ | |||
518 | ret = uiomove((void *)bf, nread, uio); | |||
519 | if (ret != 0 || nread != n) | |||
520 | goto out; | |||
521 | } | |||
522 | ||||
523 | out: | |||
524 | kmem_free(bf, RND_TEMP_BUFFER_SIZE); | |||
525 | return (ret); | |||
526 | } | |||
527 | ||||
528 | int | |||
529 | rndwrite(dev_t dev, struct uio *uio, int ioflag) | |||
530 | { | |||
531 | u_int8_t *bf; | |||
532 | int n, ret = 0, estimate_ok = 0, estimate = 0, added = 0; | |||
533 | ||||
534 | ret = kauth_authorize_device(curlwp->l_cred, | |||
535 | KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL); | |||
536 | if (ret) { | |||
537 | return (ret); | |||
538 | } | |||
539 | estimate_ok = !kauth_authorize_device(curlwp->l_cred, | |||
540 | KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL); | |||
541 | ||||
542 | DPRINTF(RND_DEBUG_WRITE, | |||
543 | ("Random: Write of %zu requested\n", uio->uio_resid)); | |||
544 | ||||
545 | if (uio->uio_resid == 0) | |||
546 | return (0); | |||
547 | ret = 0; | |||
548 | bf = kmem_alloc(RND_TEMP_BUFFER_SIZE, KM_SLEEP); | |||
549 | while (uio->uio_resid > 0) { | |||
550 | /* | |||
551 | * Don't flood the pool. | |||
552 | */ | |||
553 | if (added > RND_POOLWORDS * sizeof(int)) { | |||
554 | printf("rnd: added %d already, adding no more.\n", | |||
555 | added); | |||
556 | break; | |||
557 | } | |||
558 | n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid); | |||
559 | ||||
560 | ret = uiomove((void *)bf, n, uio); | |||
561 | if (ret != 0) | |||
562 | break; | |||
563 | ||||
564 | if (estimate_ok) { | |||
565 | /* | |||
566 | * Don't cause samples to be discarded by taking | |||
567 | * the pool's entropy estimate to the max. | |||
568 | */ | |||
569 | if (added > RND_POOLWORDS / 2) | |||
570 | estimate = 0; | |||
571 | else | |||
572 | estimate = n * NBBY / 2; | |||
573 | printf("rnd: adding on write, %d bytes, estimate %d\n", | |||
574 | n, estimate); | |||
575 | } else { | |||
576 | printf("rnd: kauth says no entropy.\n"); | |||
577 | } | |||
578 | ||||
579 | /* | |||
580 | * Mix in the bytes. | |||
581 | */ | |||
582 | mutex_spin_enter(&rndpool_mtx); | |||
583 | rndpool_add_data(&rnd_pool, bf, n, estimate); | |||
584 | mutex_spin_exit(&rndpool_mtx); | |||
585 | ||||
586 | added += n; | |||
587 | DPRINTF(RND_DEBUG_WRITE, ("Random: Copied in %d bytes\n", n)); | |||
588 | } | |||
589 | kmem_free(bf, RND_TEMP_BUFFER_SIZE); | |||
590 | return (ret); | |||
591 | } | |||
592 | ||||
593 | static void | |||
594 | krndsource_to_rndsource(krndsource_t *kr, rndsource_t *r) | |||
595 | { | |||
596 | memset(r, 0, sizeof(*r)); | |||
597 | strlcpy(r->name, kr->name, sizeof(r->name)); | |||
598 | r->total = kr->total; | |||
599 | r->type = kr->type; | |||
600 | r->flags = kr->flags; | |||
601 | } | |||
602 | ||||
603 | int | |||
604 | rndioctl(dev_t dev, u_long cmd, void *addr, int flag, | |||
605 | struct lwp *l) | |||
606 | { | |||
607 | krndsource_t *kr; | |||
608 | rndstat_t *rst; | |||
609 | rndstat_name_t *rstnm; | |||
610 | rndctl_t *rctl; | |||
611 | rnddata_t *rnddata; | |||
612 | u_int32_t count, start; | |||
613 | int ret = 0; | |||
614 | int estimate_ok = 0, estimate = 0; | |||
615 | ||||
616 | switch (cmd) { | |||
617 | case FIONBIO: | |||
618 | case FIOASYNC: | |||
619 | case RNDGETENTCNT: | |||
620 | break; | |||
621 | ||||
622 | case RNDGETPOOLSTAT: | |||
623 | case RNDGETSRCNUM: | |||
624 | case RNDGETSRCNAME: | |||
625 | ret = kauth_authorize_device(l->l_cred, | |||
626 | KAUTH_DEVICE_RND_GETPRIV, NULL, NULL, NULL, NULL); | |||
627 | if (ret) | |||
628 | return (ret); | |||
629 | break; | |||
630 | ||||
631 | case RNDCTL: | |||
632 | ret = kauth_authorize_device(l->l_cred, | |||
633 | KAUTH_DEVICE_RND_SETPRIV, NULL, NULL, NULL, NULL); | |||
634 | if (ret) | |||
635 | return (ret); | |||
636 | break; | |||
637 | ||||
638 | case RNDADDDATA: | |||
639 | ret = kauth_authorize_device(l->l_cred, | |||
640 | KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL); | |||
641 | if (ret) | |||
642 | return (ret); | |||
643 | estimate_ok = !kauth_authorize_device(l->l_cred, | |||
644 | KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL); | |||
645 | break; | |||
646 | ||||
647 | default: | |||
648 | return (EINVAL); | |||
649 | } | |||
650 | ||||
651 | switch (cmd) { | |||
652 | ||||
653 | /* | |||
654 | * Handled in upper layer really, but we have to return zero | |||
655 | * for it to be accepted by the upper layer. | |||
656 | */ | |||
657 | case FIONBIO: | |||
658 | case FIOASYNC: | |||
659 | break; | |||
660 | ||||
661 | case RNDGETENTCNT: | |||
662 | mutex_spin_enter(&rndpool_mtx); | |||
663 | *(u_int32_t *)addr = rndpool_get_entropy_count(&rnd_pool); | |||
664 | mutex_spin_exit(&rndpool_mtx); | |||
665 | break; | |||
666 | ||||
667 | case RNDGETPOOLSTAT: | |||
668 | mutex_spin_enter(&rndpool_mtx); | |||
669 | rndpool_get_stats(&rnd_pool, addr, sizeof(rndpoolstat_t)); | |||
670 | mutex_spin_exit(&rndpool_mtx); | |||
671 | break; | |||
672 | ||||
673 | case RNDGETSRCNUM: | |||
674 | rst = (rndstat_t *)addr; | |||
675 | ||||
676 | if (rst->count == 0) | |||
677 | break; | |||
678 | ||||
679 | if (rst->count > RND_MAXSTATCOUNT) | |||
680 | return (EINVAL); | |||
681 | ||||
682 | /* | |||
683 | * Find the starting source by running through the | |||
684 | * list of sources. | |||
685 | */ | |||
686 | kr = rnd_sources.lh_first; | |||
687 | start = rst->start; | |||
688 | while (kr != NULL && start >= 1) { | |||
689 | kr = kr->list.le_next; | |||
690 | start--; | |||
691 | } | |||
692 | ||||
693 | /* | |||
694 | * Return up to as many structures as the user asked | |||
695 | * for. If we run out of sources, a count of zero | |||
696 | * will be returned, without an error. | |||
697 | */ | |||
698 | for (count = 0; count < rst->count && kr != NULL; count++) { | |||
699 | krndsource_to_rndsource(kr, &rst->source[count]); | |||
700 | kr = kr->list.le_next; | |||
701 | } | |||
702 | ||||
703 | rst->count = count; | |||
704 | ||||
705 | break; | |||
706 | ||||
707 | case RNDGETSRCNAME: | |||
708 | /* | |||
709 | * Scan through the list, trying to find the name. | |||
710 | */ | |||
711 | rstnm = (rndstat_name_t *)addr; | |||
712 | kr = rnd_sources.lh_first; | |||
713 | while (kr != NULL) { | |||
714 | if (strncmp(kr->name, rstnm->name, | |||
715 | MIN(sizeof(kr->name), | |||
716 | sizeof(*rstnm))) == 0) { | |||
717 | krndsource_to_rndsource(kr, &rstnm->source); | |||
718 | return (0); | |||
719 | } | |||
720 | kr = kr->list.le_next; | |||
721 | } | |||
722 | ||||
723 | ret = ENOENT; /* name not found */ | |||
724 | ||||
725 | break; | |||
726 | ||||
727 | case RNDCTL: | |||
728 | /* | |||
729 | * Set flags to enable/disable entropy counting and/or | |||
730 | * collection. | |||
731 | */ | |||
732 | rctl = (rndctl_t *)addr; | |||
733 | kr = rnd_sources.lh_first; | |||
734 | ||||
735 | /* | |||
736 | * Flags set apply to all sources of this type. | |||
737 | */ | |||
738 | if (rctl->type != 0xff) { | |||
739 | while (kr != NULL) { | |||
740 | if (kr->type == rctl->type) { | |||
741 | kr->flags &= ~rctl->mask; | |||
742 | kr->flags |= | |||
743 | (rctl->flags & rctl->mask); | |||
744 | } | |||
745 | kr = kr->list.le_next; | |||
746 | } | |||
747 | ||||
748 | return (0); | |||
749 | } | |||
750 | ||||
751 | /* | |||
752 | * scan through the list, trying to find the name | |||
753 | */ | |||
754 | while (kr != NULL) { | |||
755 | if (strncmp(kr->name, rctl->name, | |||
756 | MIN(sizeof(kr->name), | |||
757 | sizeof(rctl->name))) == 0) { | |||
758 | kr->flags &= ~rctl->mask; | |||
759 | kr->flags |= (rctl->flags & rctl->mask); | |||
760 | ||||
761 | return (0); | |||
762 | } | |||
763 | kr = kr->list.le_next; | |||
764 | } | |||
765 | ||||
766 | ret = ENOENT; /* name not found */ | |||
767 | ||||
768 | break; | |||
769 | ||||
770 | case RNDADDDATA: | |||
771 | /* | |||
772 | * Don't seed twice if our bootloader has | |||
773 | * seed loading support. | |||
774 | */ | |||
775 | if (!boot_rsp) { | |||
776 | rnddata = (rnddata_t *)addr; | |||
777 | ||||
778 | if (rnddata->len > sizeof(rnddata->data)) | |||
779 | return EINVAL; | |||
780 | ||||
781 | if (estimate_ok) { | |||
782 | /* | |||
783 | * Do not accept absurd entropy estimates, and | |||
784 | * do not flood the pool with entropy such that | |||
785 | * new samples are discarded henceforth. | |||
786 | */ | |||
787 | estimate = MIN((rnddata->len * NBBY) / 2, | |||
788 | MIN(rnddata->entropy, | |||
789 | RND_POOLBITS / 2)); | |||
790 | } else { | |||
791 | estimate = 0; | |||
792 | } | |||
793 | ||||
794 | mutex_spin_enter(&rndpool_mtx); | |||
795 | rndpool_add_data(&rnd_pool, rnddata->data, | |||
796 | rnddata->len, estimate); | |||
797 | mutex_spin_exit(&rndpool_mtx); | |||
798 | ||||
799 | rnd_wakeup_readers(); | |||
800 | } | |||
801 | #ifdef RND_VERBOSE | |||
802 | else { | |||
803 | printf("rnd: already seeded by boot loader\n"); | |||
804 | } | |||
805 | #endif | |||
806 | break; | |||
807 | ||||
808 | default: | |||
809 | return (EINVAL); | |||
810 | } | |||
811 | ||||
812 | return (ret); | |||
813 | } | |||
814 | ||||
815 | int | |||
816 | rndpoll(dev_t dev, int events, struct lwp *l) | |||
817 | { | |||
818 | u_int32_t entcnt; | |||
819 | int revents; | |||
820 | ||||
821 | /* | |||
822 | * We are always writable. | |||
823 | */ | |||
824 | revents = events & (POLLOUT | POLLWRNORM); | |||
825 | ||||
826 | /* | |||
827 | * Save some work if not checking for reads. | |||
828 | */ | |||
829 | if ((events & (POLLIN | POLLRDNORM)) == 0) | |||
830 | return (revents); | |||
831 | ||||
832 | /* | |||
833 | * If the minor device is not /dev/random, we are always readable. | |||
834 | */ | |||
835 | if (minor(dev) != RND_DEV_RANDOM) { | |||
836 | revents |= events & (POLLIN | POLLRDNORM); | |||
837 | return (revents); | |||
838 | } | |||
839 | ||||
840 | /* | |||
841 | * Make certain we have enough entropy to be readable. | |||
842 | */ | |||
843 | mutex_spin_enter(&rndpool_mtx); | |||
844 | entcnt = rndpool_get_entropy_count(&rnd_pool); | |||
845 | mutex_spin_exit(&rndpool_mtx); | |||
846 | if (entcnt >= RND_ENTROPY_THRESHOLD * 8) | |||
847 | revents |= events & (POLLIN | POLLRDNORM); | |||
848 | else | |||
849 | selrecord(l, &rnd_selq); | |||
850 | ||||
851 | return (revents); | |||
852 | } | |||
853 | ||||
854 | static void | |||
855 | filt_rnddetach(struct knote *kn) | |||
856 | { | |||
857 | mutex_spin_enter(&rndpool_mtx); | |||
858 | SLIST_REMOVE(&rnd_selq.sel_klist, kn, knote, kn_selnext); | |||
859 | mutex_spin_exit(&rndpool_mtx); | |||
860 | } | |||
861 | ||||
862 | static int | |||
863 | filt_rndread(struct knote *kn, long hint) | |||
864 | { | |||
865 | uint32_t entcnt; | |||
866 | ||||
867 | mutex_spin_enter(&rndpool_mtx); | |||
868 | entcnt = rndpool_get_entropy_count(&rnd_pool); | |||
869 | mutex_spin_exit(&rndpool_mtx); | |||
870 | if (entcnt >= RND_ENTROPY_THRESHOLD * 8) { | |||
871 | kn->kn_data = RND_TEMP_BUFFER_SIZE; | |||
872 | return (1); | |||
873 | } | |||
874 | return (0); | |||
875 | } | |||
876 | ||||
877 | static const struct filterops rnd_seltrue_filtops = | |||
878 | { 1, NULL, filt_rnddetach, filt_seltrue }; | |||
879 | ||||
880 | static const struct filterops rndread_filtops = | |||
881 | { 1, NULL, filt_rnddetach, filt_rndread }; | |||
882 | ||||
883 | int | |||
884 | rndkqfilter(dev_t dev, struct knote *kn) | |||
885 | { | |||
886 | struct klist *klist; | |||
887 | ||||
888 | switch (kn->kn_filter) { | |||
889 | case EVFILT_READ: | |||
890 | klist = &rnd_selq.sel_klist; | |||
891 | if (minor(dev) == RND_DEV_URANDOM) | |||
892 | kn->kn_fop = &rnd_seltrue_filtops; | |||
893 | else | |||
894 | kn->kn_fop = &rndread_filtops; | |||
895 | break; | |||
896 | ||||
897 | case EVFILT_WRITE: | |||
898 | klist = &rnd_selq.sel_klist; | |||
899 | kn->kn_fop = &rnd_seltrue_filtops; | |||
900 | break; | |||
901 | ||||
902 | default: | |||
903 | return (EINVAL); | |||
904 | } | |||
905 | ||||
906 | kn->kn_hook = NULL; | |||
907 | ||||
908 | mutex_spin_enter(&rndpool_mtx); | |||
909 | SLIST_INSERT_HEAD(klist, kn, kn_selnext); | |||
910 | mutex_spin_exit(&rndpool_mtx); | |||
911 | ||||
912 | return (0); | |||
913 | } | |||
914 | ||||
915 | static rnd_sample_t * | 384 | static rnd_sample_t * | |
916 | rnd_sample_allocate(krndsource_t *source) | 385 | rnd_sample_allocate(krndsource_t *source) | |
917 | { | 386 | { | |
918 | rnd_sample_t *c; | 387 | rnd_sample_t *c; | |
919 | 388 | |||
920 | c = pool_get(&rnd_mempool, PR_WAITOK); | 389 | c = pool_cache_get(rnd_mempc, PR_WAITOK); | |
921 | if (c == NULL) | 390 | if (c == NULL) | |
922 | return (NULL); | 391 | return (NULL); | |
923 | 392 | |||
924 | c->source = source; | 393 | c->source = source; | |
925 | c->cursor = 0; | 394 | c->cursor = 0; | |
926 | c->entropy = 0; | 395 | c->entropy = 0; | |
927 | 396 | |||
928 | return (c); | 397 | return (c); | |
929 | } | 398 | } | |
930 | 399 | |||
931 | /* | 400 | /* | |
932 | * Don't wait on allocation. To be used in an interrupt context. | 401 | * Don't wait on allocation. To be used in an interrupt context. | |
933 | */ | 402 | */ | |
934 | static rnd_sample_t * | 403 | static rnd_sample_t * | |
935 | rnd_sample_allocate_isr(krndsource_t *source) | 404 | rnd_sample_allocate_isr(krndsource_t *source) | |
936 | { | 405 | { | |
937 | rnd_sample_t *c; | 406 | rnd_sample_t *c; | |
938 | 407 | |||
939 | c = pool_get(&rnd_mempool, PR_NOWAIT); | 408 | c = pool_cache_get(rnd_mempc, PR_NOWAIT); | |
940 | if (c == NULL) | 409 | if (c == NULL) | |
941 | return (NULL); | 410 | return (NULL); | |
942 | 411 | |||
943 | c->source = source; | 412 | c->source = source; | |
944 | c->cursor = 0; | 413 | c->cursor = 0; | |
945 | c->entropy = 0; | 414 | c->entropy = 0; | |
946 | 415 | |||
947 | return (c); | 416 | return (c); | |
948 | } | 417 | } | |
949 | 418 | |||
950 | static void | 419 | static void | |
951 | rnd_sample_free(rnd_sample_t *c) | 420 | rnd_sample_free(rnd_sample_t *c) | |
952 | { | 421 | { | |
953 | memset(c, 0, sizeof(*c)); | 422 | memset(c, 0, sizeof(*c)); | |
954 | pool_put(&rnd_mempool, c); | 423 | pool_cache_put(rnd_mempc, c); | |
955 | } | 424 | } | |
956 | 425 | |||
957 | /* | 426 | /* | |
958 | * Add a source to our list of sources. | 427 | * Add a source to our list of sources. | |
959 | */ | 428 | */ | |
960 | void | 429 | void | |
961 | rnd_attach_source(krndsource_t *rs, const char *name, u_int32_t type, | 430 | rnd_attach_source(krndsource_t *rs, const char *name, u_int32_t type, | |
962 | u_int32_t flags) | 431 | u_int32_t flags) | |
963 | { | 432 | { | |
964 | u_int32_t ts; | 433 | u_int32_t ts; | |
965 | 434 | |||
966 | RUN_ONCE(&rnd_mempoolinit_ctrl, rnd_mempool_init); | |||
967 | ||||
968 | ts = rnd_counter(); | 435 | ts = rnd_counter(); | |
969 | 436 | |||
970 | strlcpy(rs->name, name, sizeof(rs->name)); | 437 | strlcpy(rs->name, name, sizeof(rs->name)); | |
971 | rs->last_time = ts; | 438 | rs->last_time = ts; | |
972 | rs->last_delta = 0; | 439 | rs->last_delta = 0; | |
973 | rs->last_delta2 = 0; | 440 | rs->last_delta2 = 0; | |
974 | rs->total = 0; | 441 | rs->total = 0; | |
975 | 442 | |||
976 | /* | 443 | /* | |
977 | * Force network devices to not collect any entropy by | 444 | * Force network devices to not collect any entropy by | |
978 | * default. | 445 | * default. | |
979 | */ | 446 | */ | |
980 | if (type == RND_TYPE_NET) | 447 | if (type == RND_TYPE_NET) | |
@@ -1204,36 +671,28 @@ rnd_hwrng_test(rnd_sample_t *sample) | @@ -1204,36 +671,28 @@ rnd_hwrng_test(rnd_sample_t *sample) | |||
1204 | 671 | |||
1205 | /* | 672 | /* | |
1206 | * Continuous-output test: compare two halves of the | 673 | * Continuous-output test: compare two halves of the | |
1207 | * sample buffer to each other. The sample buffer (64 ints, | 674 | * sample buffer to each other. The sample buffer (64 ints, | |
1208 | * so either 256 or 512 bytes on any modern machine) should be | 675 | * so either 256 or 512 bytes on any modern machine) should be | |
1209 | * much larger than a typical hardware RNG output, so this seems | 676 | * much larger than a typical hardware RNG output, so this seems | |
1210 | * a reasonable way to do it without retaining extra data. | 677 | * a reasonable way to do it without retaining extra data. | |
1211 | */ | 678 | */ | |
1212 | cmplen = sizeof(sample->values) / 2; | 679 | cmplen = sizeof(sample->values) / 2; | |
1213 | v1 = (uint8_t *)sample->values; | 680 | v1 = (uint8_t *)sample->values; | |
1214 | v2 = (uint8_t *)sample->values + cmplen; | 681 | v2 = (uint8_t *)sample->values + cmplen; | |
1215 | 682 | |||
1216 | if (__predict_false(!memcmp(v1, v2, cmplen))) { | 683 | if (__predict_false(!memcmp(v1, v2, cmplen))) { | |
1217 | int *dump; | |||
1218 | printf("rnd: source \"%s\" failed continuous-output test.\n", | 684 | printf("rnd: source \"%s\" failed continuous-output test.\n", | |
1219 | source->name); | 685 | source->name); | |
1220 | printf("rnd: bad buffer: "); | |||
1221 | for (dump = (int *)sample->values; | |||
1222 | dump < (int *)((uint8_t *)sample->values + | |||
1223 | sizeof(sample->values)); dump += sizeof(int)) { | |||
1224 | printf("%x ", *dump); | |||
1225 | } | |||
1226 | printf("\n"); | |||
1227 | return 1; | 686 | return 1; | |
1228 | } | 687 | } | |
1229 | 688 | |||
1230 | /* | 689 | /* | |
1231 | * FIPS 140 statistical RNG test. We must accumulate 20,000 bits. | 690 | * FIPS 140 statistical RNG test. We must accumulate 20,000 bits. | |
1232 | */ | 691 | */ | |
1233 | if (__predict_true(source->test_cnt == -1)) { | 692 | if (__predict_true(source->test_cnt == -1)) { | |
1234 | /* already passed the test */ | 693 | /* already passed the test */ | |
1235 | return 0; | 694 | return 0; | |
1236 | } | 695 | } | |
1237 | resid = FIPS140_RNG_TEST_BYTES - source->test_cnt; | 696 | resid = FIPS140_RNG_TEST_BYTES - source->test_cnt; | |
1238 | totest = MIN(RND_SAMPLE_COUNT * 4, resid); | 697 | totest = MIN(RND_SAMPLE_COUNT * 4, resid); | |
1239 | memcpy(source->test->rt_b + source->test_cnt, sample->values, totest); | 698 | memcpy(source->test->rt_b + source->test_cnt, sample->values, totest); | |
@@ -1355,84 +814,88 @@ rnd_process_events(void *arg) | @@ -1355,84 +814,88 @@ rnd_process_events(void *arg) | |||
1355 | } | 814 | } | |
1356 | 815 | |||
1357 | /* | 816 | /* | |
1358 | * Timeout, run to process the events in the ring buffer. | 817 | * Timeout, run to process the events in the ring buffer. | |
1359 | */ | 818 | */ | |
1360 | static void | 819 | static void | |
1361 | rnd_timeout(void *arg) | 820 | rnd_timeout(void *arg) | |
1362 | { | 821 | { | |
1363 | mutex_spin_enter(&rnd_mtx); | 822 | mutex_spin_enter(&rnd_mtx); | |
1364 | rnd_timeout_pending = 0; | 823 | rnd_timeout_pending = 0; | |
1365 | rnd_process_events(arg); | 824 | rnd_process_events(arg); | |
1366 | } | 825 | } | |
1367 | 826 | |||
1368 | static u_int32_t | 827 | u_int32_t | |
1369 | rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags) | 828 | rnd_extract_data_locked(void *p, u_int32_t len, u_int32_t flags) | |
1370 | { | 829 | { | |
1371 | 830 | |||
1372 | KASSERT(mutex_owned(&rndpool_mtx)); | 831 | KASSERT(mutex_owned(&rndpool_mtx)); | |
1373 | if (!rnd_have_entropy) { | 832 | if (!rnd_have_entropy) { | |
1374 | u_int32_t c; | 833 | u_int32_t c; | |
1375 | 834 | |||
1376 | #ifdef RND_VERBOSE | 835 | #ifdef RND_VERBOSE | |
1377 | printf("rnd: WARNING! initial entropy low (%u).\n", | 836 | printf("rnd: WARNING! initial entropy low (%u).\n", | |
1378 | rndpool_get_entropy_count(&rnd_pool)); | 837 | rndpool_get_entropy_count(&rnd_pool)); | |
1379 | #endif | 838 | #endif | |
1380 | /* Try once again to put something in the pool */ | 839 | /* Try once again to put something in the pool */ | |
1381 | c = rnd_counter(); | 840 | c = rnd_counter(); | |
1382 | rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1); | 841 | rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1); | |
1383 | } | 842 | } | |
1384 | if (!rnd_tested) { | 843 | ||
1385 | rngtest_t rt; | 844 | #ifdef DIAGNOSTIC | |
1386 | uint8_t testbits[sizeof(rt.rt_b)]; | 845 | while (!rnd_tested) { | |
1387 | int entropy_count; | 846 | int entropy_count; | |
1388 | 847 | |||
1389 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | 848 | entropy_count = rndpool_get_entropy_count(&rnd_pool); | |
1390 | #ifdef RND_VERBOSE | 849 | #ifdef RND_VERBOSE | |
1391 | printf("rnd: starting statistical RNG test, entropy = %d.\n", | 850 | printf("rnd: starting statistical RNG test, entropy = %d.\n", | |
1392 | entropy_count); | 851 | entropy_count); | |
1393 | #endif | 852 | #endif | |
1394 | if (rndpool_extract_data(&rnd_pool, rt.rt_b, | 853 | if (rndpool_extract_data(&rnd_pool, rnd_rt.rt_b, | |
1395 | sizeof(rt.rt_b), RND_EXTRACT_ANY) != sizeof(rt.rt_b)) { | 854 | sizeof(rnd_rt.rt_b), RND_EXTRACT_ANY) | |
855 | != sizeof(rnd_rt.rt_b)) { | |||
1396 | panic("rnd: could not get bits for statistical test"); | 856 | panic("rnd: could not get bits for statistical test"); | |
1397 | } | 857 | } | |
1398 | /* | 858 | /* | |
1399 | * Stash the tested bits so we can put them back in the | 859 | * Stash the tested bits so we can put them back in the | |
1400 | * pool, restoring the entropy count. DO NOT rely on | 860 | * pool, restoring the entropy count. DO NOT rely on | |
1401 | * rngtest to maintain the bits pristine -- we could end | 861 | * rngtest to maintain the bits pristine -- we could end | |
1402 | * up adding back non-random data claiming it were pure | 862 | * up adding back non-random data claiming it were pure | |
1403 | * entropy. | 863 | * entropy. | |
1404 | */ | 864 | */ | |
1405 | memcpy(testbits, rt.rt_b, sizeof(rt.rt_b)); | 865 | memcpy(rnd_testbits, rnd_rt.rt_b, sizeof(rnd_rt.rt_b)); | |
1406 | strlcpy(rt.rt_name, "entropy pool", sizeof(rt.rt_name)); | 866 | strlcpy(rnd_rt.rt_name, "entropy pool", sizeof(rnd_rt.rt_name)); | |
1407 | if (rngtest(&rt)) { | 867 | if (rngtest(&rnd_rt)) { | |
1408 | /* | 868 | /* | |
1409 | * The probabiliity of a Type I error is 3/10000, | 869 | * The probabiliity of a Type I error is 3/10000, | |
1410 | * but note this can only happen at boot time. | 870 | * but note this can only happen at boot time. | |
1411 | * The relevant standard says to reset the module, | 871 | * The relevant standard says to reset the module, | |
1412 | * so that's what we do. | 872 | * but developers objected... | |
1413 | */ | 873 | */ | |
1414 | panic("rnd: entropy pool failed statistical test"); | 874 | printf("rnd: WARNING, ENTROPY POOL FAILED " | |
875 | "STATISTICAL TEST!\n"); | |||
876 | continue; | |||
1415 | } | 877 | } | |
1416 | memset(&rt, 0, sizeof(rt)); | 878 | memset(&rnd_rt, 0, sizeof(rnd_rt)); | |
1417 | rndpool_add_data(&rnd_pool, testbits, sizeof(testbits), | 879 | rndpool_add_data(&rnd_pool, rnd_testbits, sizeof(rnd_testbits), | |
1418 | entropy_count); | 880 | entropy_count); | |
1419 | memset(testbits, 0, sizeof(testbits)); | 881 | memset(rnd_testbits, 0, sizeof(rnd_testbits)); | |
1420 | #ifdef RND_VERBOSE | 882 | #ifdef RND_VERBOSE | |
1421 | printf("rnd: statistical RNG test done, entropy = %d.\n", | 883 | printf("rnd: statistical RNG test done, entropy = %d.\n", | |
1422 | rndpool_get_entropy_count(&rnd_pool)); | 884 | rndpool_get_entropy_count(&rnd_pool)); | |
1423 | #endif | 885 | #endif | |
1424 | rnd_tested++; | 886 | rnd_tested++; | |
1425 | } | 887 | } | |
888 | #endif | |||
1426 | return rndpool_extract_data(&rnd_pool, p, len, flags); | 889 | return rndpool_extract_data(&rnd_pool, p, len, flags); | |
1427 | } | 890 | } | |
1428 | 891 | |||
1429 | u_int32_t | 892 | u_int32_t | |
1430 | rnd_extract_data(void *p, u_int32_t len, u_int32_t flags) | 893 | rnd_extract_data(void *p, u_int32_t len, u_int32_t flags) | |
1431 | { | 894 | { | |
1432 | uint32_t retval; | 895 | uint32_t retval; | |
1433 | 896 | |||
1434 | mutex_spin_enter(&rndpool_mtx); | 897 | mutex_spin_enter(&rndpool_mtx); | |
1435 | retval = rnd_extract_data_locked(p, len, flags); | 898 | retval = rnd_extract_data_locked(p, len, flags); | |
1436 | mutex_spin_exit(&rndpool_mtx); | 899 | mutex_spin_exit(&rndpool_mtx); | |
1437 | return retval; | 900 | return retval; | |
1438 | } | 901 | } |
--- src/sys/dev/Attic/rndpool.c 2011/11/29 03:50:31 1.21
+++ src/sys/dev/Attic/rndpool.c 2011/12/17 20:05:38 1.22
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rndpool.c,v 1.21 2011/11/29 03:50:31 tls Exp $ */ | 1 | /* $NetBSD: rndpool.c,v 1.22 2011/12/17 20:05:38 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | 8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | |
9 | * algorithms from the Linux driver written by Ted Ts'o. | 9 | * algorithms from the Linux driver written by Ted Ts'o. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,44 +21,49 @@ | @@ -21,44 +21,49 @@ | |||
21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 22 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 23 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 24 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
30 | * POSSIBILITY OF SUCH DAMAGE. | 30 | * POSSIBILITY OF SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: rndpool.c,v 1.21 2011/11/29 03:50:31 tls Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: rndpool.c,v 1.22 2011/12/17 20:05:38 tls Exp $"); | |
35 | 35 | |||
36 | #include <sys/param.h> | 36 | #include <sys/param.h> | |
37 | #include <sys/systm.h> | 37 | #include <sys/systm.h> | |
38 | #include <sys/sha1.h> | 38 | #include <sys/sha1.h> | |
39 | 39 | |||
40 | #include <sys/rnd.h> | 40 | #include <sys/rnd.h> | |
41 | #include <dev/rnd_private.h> | 41 | #include <dev/rnd_private.h> | |
42 | 42 | |||
43 | /* | 43 | /* | |
44 | * The random pool "taps" | 44 | * The random pool "taps" | |
45 | */ | 45 | */ | |
46 | #define TAP1 99 | 46 | #define TAP1 99 | |
47 | #define TAP2 59 | 47 | #define TAP2 59 | |
48 | #define TAP3 31 | 48 | #define TAP3 31 | |
49 | #define TAP4 9 | 49 | #define TAP4 9 | |
50 | #define TAP5 7 | 50 | #define TAP5 7 | |
51 | 51 | |||
52 | /* | |||
53 | * Let others know: the pool is full. | |||
54 | */ | |||
55 | int rnd_full; | |||
56 | ||||
52 | static inline void rndpool_add_one_word(rndpool_t *, u_int32_t); | 57 | static inline void rndpool_add_one_word(rndpool_t *, u_int32_t); | |
53 | 58 | |||
54 | void | 59 | void | |
55 | rndpool_init(rndpool_t *rp) | 60 | rndpool_init(rndpool_t *rp) | |
56 | { | 61 | { | |
57 | 62 | |||
58 | rp->cursor = 0; | 63 | rp->cursor = 0; | |
59 | rp->rotate = 1; | 64 | rp->rotate = 1; | |
60 | 65 | |||
61 | memset(&rp->stats, 0, sizeof(rp->stats)); | 66 | memset(&rp->stats, 0, sizeof(rp->stats)); | |
62 | 67 | |||
63 | rp->stats.curentropy = 0; | 68 | rp->stats.curentropy = 0; | |
64 | rp->stats.poolsize = RND_POOLWORDS; | 69 | rp->stats.poolsize = RND_POOLWORDS; | |
@@ -163,45 +168,26 @@ rndpool_add_one_word(rndpool_t *rp, u_in | @@ -163,45 +168,26 @@ rndpool_add_one_word(rndpool_t *rp, u_in | |||
163 | rp->pool[rp->cursor++] ^= val; | 168 | rp->pool[rp->cursor++] ^= val; | |
164 | 169 | |||
165 | /* | 170 | /* | |
166 | * If we have looped around the pool, increment the rotate | 171 | * If we have looped around the pool, increment the rotate | |
167 | * variable so the next value will get xored in rotated to | 172 | * variable so the next value will get xored in rotated to | |
168 | * a different position. | 173 | * a different position. | |
169 | */ | 174 | */ | |
170 | if (rp->cursor == RND_POOLWORDS) { | 175 | if (rp->cursor == RND_POOLWORDS) { | |
171 | rp->cursor = 0; | 176 | rp->cursor = 0; | |
172 | rp->rotate = (rp->rotate + 7) & 31; | 177 | rp->rotate = (rp->rotate + 7) & 31; | |
173 | } | 178 | } | |
174 | } | 179 | } | |
175 | 180 | |||
176 | #if 0 | |||
177 | /* | |||
178 | * Stir a 32-bit value (with possibly less entropy than that) into the pool. | |||
179 | * Update entropy estimate. | |||
180 | */ | |||
181 | void | |||
182 | rndpool_add_uint32(rndpool_t *rp, u_int32_t val, u_int32_t entropy) | |||
183 | { | |||
184 | rndpool_add_one_word(rp, val); | |||
185 | ||||
186 | rp->entropy += entropy; | |||
187 | rp->stats.added += entropy; | |||
188 | if (rp->entropy > RND_POOLBITS) { | |||
189 | rp->stats.discarded += (rp->entropy - RND_POOLBITS); | |||
190 | rp->entropy = RND_POOLBITS; | |||
191 | } | |||
192 | } | |||
193 | #endif | |||
194 | ||||
195 | /* | 181 | /* | |
196 | * Add a buffer's worth of data to the pool. | 182 | * Add a buffer's worth of data to the pool. | |
197 | */ | 183 | */ | |
198 | void | 184 | void | |
199 | rndpool_add_data(rndpool_t *rp, void *p, u_int32_t len, u_int32_t entropy) | 185 | rndpool_add_data(rndpool_t *rp, void *p, u_int32_t len, u_int32_t entropy) | |
200 | { | 186 | { | |
201 | u_int32_t val; | 187 | u_int32_t val; | |
202 | u_int8_t *buf; | 188 | u_int8_t *buf; | |
203 | 189 | |||
204 | buf = p; | 190 | buf = p; | |
205 | 191 | |||
206 | for (; len > 3; len -= 4) { | 192 | for (; len > 3; len -= 4) { | |
207 | val = *((u_int32_t *)buf); | 193 | val = *((u_int32_t *)buf); | |
@@ -220,26 +206,27 @@ rndpool_add_data(rndpool_t *rp, void *p, | @@ -220,26 +206,27 @@ rndpool_add_data(rndpool_t *rp, void *p, | |||
220 | case 1: | 206 | case 1: | |
221 | val = val << 8 | *buf++; | 207 | val = val << 8 | *buf++; | |
222 | } | 208 | } | |
223 | 209 | |||
224 | rndpool_add_one_word(rp, val); | 210 | rndpool_add_one_word(rp, val); | |
225 | } | 211 | } | |
226 | 212 | |||
227 | rp->stats.curentropy += entropy; | 213 | rp->stats.curentropy += entropy; | |
228 | rp->stats.added += entropy; | 214 | rp->stats.added += entropy; | |
229 | 215 | |||
230 | if (rp->stats.curentropy > RND_POOLBITS) { | 216 | if (rp->stats.curentropy > RND_POOLBITS) { | |
231 | rp->stats.discarded += (rp->stats.curentropy - RND_POOLBITS); | 217 | rp->stats.discarded += (rp->stats.curentropy - RND_POOLBITS); | |
232 | rp->stats.curentropy = RND_POOLBITS; | 218 | rp->stats.curentropy = RND_POOLBITS; | |
219 | rnd_full = 1; | |||
233 | } | 220 | } | |
234 | } | 221 | } | |
235 | 222 | |||
236 | /* | 223 | /* | |
237 | * Extract some number of bytes from the random pool, decreasing the | 224 | * Extract some number of bytes from the random pool, decreasing the | |
238 | * estimate of randomness as each byte is extracted. | 225 | * estimate of randomness as each byte is extracted. | |
239 | * | 226 | * | |
240 | * Do this by hashing the pool and returning a part of the hash as | 227 | * Do this by hashing the pool and returning a part of the hash as | |
241 | * randomness. Stir the hash back into the pool. Note that no | 228 | * randomness. Stir the hash back into the pool. Note that no | |
242 | * secrets going back into the pool are given away here since parts of | 229 | * secrets going back into the pool are given away here since parts of | |
243 | * the hash are xored together before being returned. | 230 | * the hash are xored together before being returned. | |
244 | * | 231 | * | |
245 | * Honor the request from the caller to only return good data, any data, | 232 | * Honor the request from the caller to only return good data, any data, | |
@@ -249,26 +236,28 @@ rndpool_add_data(rndpool_t *rp, void *p, | @@ -249,26 +236,28 @@ rndpool_add_data(rndpool_t *rp, void *p, | |||
249 | u_int32_t | 236 | u_int32_t | |
250 | rndpool_extract_data(rndpool_t *rp, void *p, u_int32_t len, u_int32_t mode) | 237 | rndpool_extract_data(rndpool_t *rp, void *p, u_int32_t len, u_int32_t mode) | |
251 | { | 238 | { | |
252 | u_int i; | 239 | u_int i; | |
253 | SHA1_CTX hash; | 240 | SHA1_CTX hash; | |
254 | u_char digest[SHA1_DIGEST_LENGTH]; | 241 | u_char digest[SHA1_DIGEST_LENGTH]; | |
255 | u_int32_t remain, deltae, count; | 242 | u_int32_t remain, deltae, count; | |
256 | u_int8_t *buf; | 243 | u_int8_t *buf; | |
257 | int good; | 244 | int good; | |
258 | 245 | |||
259 | buf = p; | 246 | buf = p; | |
260 | remain = len; | 247 | remain = len; | |
261 | 248 | |||
249 | rnd_full = 0; | |||
250 | ||||
262 | if (mode == RND_EXTRACT_ANY) | 251 | if (mode == RND_EXTRACT_ANY) | |
263 | good = 1; | 252 | good = 1; | |
264 | else | 253 | else | |
265 | good = (rp->stats.curentropy >= (8 * RND_ENTROPY_THRESHOLD)); | 254 | good = (rp->stats.curentropy >= (8 * RND_ENTROPY_THRESHOLD)); | |
266 | 255 | |||
267 | KASSERT(RND_ENTROPY_THRESHOLD * 2 <= sizeof(digest)); | 256 | KASSERT(RND_ENTROPY_THRESHOLD * 2 <= sizeof(digest)); | |
268 | 257 | |||
269 | while (good && (remain != 0)) { | 258 | while (good && (remain != 0)) { | |
270 | /* | 259 | /* | |
271 | * While bytes are requested, compute the hash of the pool, | 260 | * While bytes are requested, compute the hash of the pool, | |
272 | * and then "fold" the hash in half with XOR, keeping the | 261 | * and then "fold" the hash in half with XOR, keeping the | |
273 | * exact hash value secret, as it will be stirred back into | 262 | * exact hash value secret, as it will be stirred back into | |
274 | * the pool. | 263 | * the pool. |
/* $NetBSD: rndpseudo.c,v 1.1 2011/12/17 20:05:39 tls Exp $ */
/*-
* Copyright (c) 1997-2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Michael Graff <explorer@flame.org> and Thor Lancelot Simon.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rndpseudo.c,v 1.1 2011/12/17 20:05:39 tls Exp $");
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/filedesc.h>
#include <sys/select.h>
#include <sys/poll.h>
#include <sys/kmem.h>
#include <sys/atomic.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/systm.h>
#include <sys/rnd.h>
#include <sys/vnode.h>
#include <sys/pool.h>
#include <sys/kauth.h>
#include <sys/cprng.h>
#include <sys/stat.h>
#include <dev/rnd_private.h>
#if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */
#include <machine/cpu_counter.h>
#endif
#ifdef RND_DEBUG
#define DPRINTF(l,x) if (rnd_debug & (l)) printf x
int rnd_debug = 0;
#else
#define DPRINTF(l,x)
#endif
#define RND_DEBUG_WRITE 0x0001
#define RND_DEBUG_READ 0x0002
#define RND_DEBUG_IOCTL 0x0004
#define RND_DEBUG_SNOOZE 0x0008
/*
* list devices attached
*/
#if 0
#define RND_VERBOSE
#endif
/*
* The size of a temporary buffer, kmem_alloc()ed when needed, and used for
* reading and writing data.
*/
#define RND_TEMP_BUFFER_SIZE 512
static pool_cache_t rp_pc;
static pool_cache_t rp_cpc;
/*
* A context. cprng plus a smidge.
*/
typedef struct {
cprng_strong_t *cprng;
int hard;
int bytesonkey;
kmutex_t interlock;
} rp_ctx_t;
/*
* Our random pool. This is defined here rather than using the general
* purpose one defined in rndpool.c.
*
* Samples are collected and queued into a separate mutex-protected queue
* (rnd_samples, see above), and processed in a timeout routine; therefore,
* the mutex protecting the random pool is at IPL_SOFTCLOCK() as well.
*/
extern rndpool_t rnd_pool;
extern kmutex_t rndpool_mtx;
void rndattach(int);
dev_type_open(rndopen);
const struct cdevsw rnd_cdevsw = {
rndopen, noclose, noread, nowrite, noioctl, nostop,
notty, nopoll, nommap, nokqfilter, D_OTHER|D_MPSAFE
};
static int rnd_read(struct file *, off_t *, struct uio *, kauth_cred_t, int);
static int rnd_write(struct file *, off_t *, struct uio *, kauth_cred_t, int);
static int rnd_ioctl(struct file *, u_long, void *);
static int rnd_poll(struct file *, int);
static int rnd_stat(struct file *, struct stat *);
static int rnd_close(struct file *);
static int rnd_kqfilter(struct file *, struct knote *);
const struct fileops rnd_fileops = {
.fo_read = rnd_read,
.fo_write = rnd_write,
.fo_ioctl = rnd_ioctl,
.fo_fcntl = fnullop_fcntl,
.fo_poll = rnd_poll,
.fo_stat = rnd_stat,
.fo_close = rnd_close,
.fo_kqfilter = rnd_kqfilter,
.fo_restart = fnullop_restart
};
void rnd_wakeup_readers(void); /* XXX */
extern int rnd_ready; /* XXX */
extern rndsave_t *boot_rsp; /* XXX */
extern LIST_HEAD(, krndsource) rnd_sources; /* XXX */
/*
* Generate a 32-bit counter. This should be more machine dependent,
* using cycle counters and the like when possible.
*/
static inline u_int32_t
rndpseudo_counter(void)
{
struct timeval tv;
#if defined(__HAVE_CPU_COUNTER) && !defined(_RUMPKERNEL) /* XXX: bad pooka */
if (cpu_hascounter())
return (cpu_counter32());
#endif
microtime(&tv);
return (tv.tv_sec * 1000000 + tv.tv_usec);
}
/*
* "Attach" the random device. This is an (almost) empty stub, since
* pseudo-devices don't get attached until after config, after the
* entropy sources will attach. We just use the timing of this event
* as another potential source of initial entropy.
*/
void
rndattach(int num)
{
u_int32_t c;
/* Trap unwary players who don't call rnd_init() early */
KASSERT(rnd_ready);
rp_pc = pool_cache_init(RND_TEMP_BUFFER_SIZE, 0, 0, 0,
"rndtemp", NULL, IPL_NONE,
NULL, NULL, NULL);
rp_cpc = pool_cache_init(sizeof(rp_ctx_t), 0, 0, 0,
"rndctx", NULL, IPL_NONE,
NULL, NULL, NULL);
/* mix in another counter */
c = rndpseudo_counter();
mutex_spin_enter(&rndpool_mtx);
rndpool_add_data(&rnd_pool, &c, sizeof(u_int32_t), 1);
mutex_spin_exit(&rndpool_mtx);
}
int
rndopen(dev_t dev, int flag, int ifmt,
struct lwp *l)
{
rp_ctx_t *ctx;
file_t *fp;
int fd, hard, error = 0;
switch (minor(dev)) {
case RND_DEV_URANDOM:
hard = 0;
break;
case RND_DEV_RANDOM:
hard = 1;
break;
default:
return ENXIO;
}
ctx = pool_cache_get(rp_cpc, PR_WAITOK);
ctx->cprng = NULL;
ctx->hard = hard;
mutex_init(&ctx->interlock, MUTEX_DEFAULT, IPL_NONE);
if ((error = fd_allocfile(&fp, &fd)) != 0) {
pool_cache_put(rp_cpc, ctx);
return error;
}
return fd_clone(fp, fd, flag, &rnd_fileops, ctx);
}
static void
rnd_alloc_cprng(rp_ctx_t *ctx)
{
char personalization_buf[64];
struct lwp *l = curlwp;
int cflags = ctx->hard ? CPRNG_USE_CV :
CPRNG_INIT_ANY|CPRNG_REKEY_ANY;
mutex_enter(&ctx->interlock);
if (__predict_true(ctx->cprng == NULL)) {
snprintf(personalization_buf,
sizeof(personalization_buf),
"%d%llud%d", l->l_proc->p_pid,
(unsigned long long int)l->l_ncsw, l->l_cpticks);
ctx->cprng = cprng_strong_create(personalization_buf,
IPL_NONE, cflags);
}
membar_sync();
mutex_exit(&ctx->interlock);
}
static int
rnd_read(struct file * fp, off_t *offp, struct uio *uio,
kauth_cred_t cred, int flags)
{
rp_ctx_t *ctx = fp->f_data;
u_int8_t *bf;
int strength, ret;
DPRINTF(RND_DEBUG_READ,
("Random: Read of %zu requested, flags 0x%08x\n",
uio->uio_resid, ioflag));
if (uio->uio_resid == 0)
return (0);
if (ctx->cprng == NULL) {
rnd_alloc_cprng(ctx);
if (__predict_false(ctx->cprng == NULL)) {
return EIO;
}
}
strength = cprng_strong_strength(ctx->cprng);
ret = 0;
bf = pool_cache_get(rp_pc, PR_WAITOK);
while (uio->uio_resid > 0) {
int n, nread, want;
want = MIN(RND_TEMP_BUFFER_SIZE, uio->uio_resid);
/* XXX is this _really_ what's wanted? */
if (ctx->hard) {
n = MIN(want, strength - ctx->bytesonkey);
ctx->bytesonkey += n;
} else {
n = want;
}
nread = cprng_strong(ctx->cprng, bf, n,
(fp->f_flag & FNONBLOCK) ? FNONBLOCK : 0);
if (nread != n) {
if (fp->f_flag & FNONBLOCK) {
ret = EWOULDBLOCK;
} else {
ret = EINTR;
}
goto out;
}
ret = uiomove((void *)bf, nread, uio);
if (ret != 0 || n < want) {
goto out;
}
}
out:
if (ctx->bytesonkey >= strength) {
/* Force reseed of underlying DRBG (prediction resistance) */
cprng_strong_deplete(ctx->cprng);
ctx->bytesonkey = 0;
}
pool_cache_put(rp_pc, bf);
return (ret);
}
static int
rnd_write(struct file *fp, off_t *offp, struct uio *uio,
kauth_cred_t cred, int flags)
{
u_int8_t *bf;
int n, ret = 0, estimate_ok = 0, estimate = 0, added = 0;
ret = kauth_authorize_device(cred,
KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL);
if (ret) {
return (ret);
}
estimate_ok = !kauth_authorize_device(cred,
KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL);
DPRINTF(RND_DEBUG_WRITE,
("Random: Write of %zu requested\n", uio->uio_resid));
if (uio->uio_resid == 0)
return (0);
ret = 0;
bf = pool_cache_get(rp_pc, PR_WAITOK);
while (uio->uio_resid > 0) {
/*
* Don't flood the pool.
*/
if (added > RND_POOLWORDS * sizeof(int)) {
#ifdef RND_VERBOSE
printf("rnd: added %d already, adding no more.\n",
added);
#endif
break;
}
n = min(RND_TEMP_BUFFER_SIZE, uio->uio_resid);
ret = uiomove((void *)bf, n, uio);
if (ret != 0)
break;
if (estimate_ok) {
/*
* Don't cause samples to be discarded by taking
* the pool's entropy estimate to the max.
*/
if (added > RND_POOLWORDS / 2)
estimate = 0;
else
estimate = n * NBBY / 2;
#ifdef RND_VERBOSE
printf("rnd: adding on write, %d bytes, estimate %d\n",
n, estimate);
#endif
} else {
#ifdef RND_VERBOSE
printf("rnd: kauth says no entropy.\n");
#endif
}
/*
* Mix in the bytes.
*/
mutex_spin_enter(&rndpool_mtx);
rndpool_add_data(&rnd_pool, bf, n, estimate);
mutex_spin_exit(&rndpool_mtx);
added += n;
DPRINTF(RND_DEBUG_WRITE, ("Random: Copied in %d bytes\n", n));
}
pool_cache_put(rp_pc, bf);
return (ret);
}
static void
krndsource_to_rndsource(krndsource_t *kr, rndsource_t *r)
{
memset(r, 0, sizeof(*r));
strlcpy(r->name, kr->name, sizeof(r->name));
r->total = kr->total;
r->type = kr->type;
r->flags = kr->flags;
}
int
rnd_ioctl(struct file *fp, u_long cmd, void *addr)
{
krndsource_t *kr;
rndstat_t *rst;
rndstat_name_t *rstnm;
rndctl_t *rctl;
rnddata_t *rnddata;
u_int32_t count, start;
int ret = 0;
int estimate_ok = 0, estimate = 0;
switch (cmd) {
case FIONBIO:
case FIOASYNC:
case RNDGETENTCNT:
break;
case RNDGETPOOLSTAT:
case RNDGETSRCNUM:
case RNDGETSRCNAME:
ret = kauth_authorize_device(curlwp->l_cred,
KAUTH_DEVICE_RND_GETPRIV, NULL, NULL, NULL, NULL);
if (ret)
return (ret);
break;
case RNDCTL:
ret = kauth_authorize_device(curlwp->l_cred,
KAUTH_DEVICE_RND_SETPRIV, NULL, NULL, NULL, NULL);
if (ret)
return (ret);
break;
case RNDADDDATA:
ret = kauth_authorize_device(curlwp->l_cred,
KAUTH_DEVICE_RND_ADDDATA, NULL, NULL, NULL, NULL);
if (ret)
return (ret);
estimate_ok = !kauth_authorize_device(curlwp->l_cred,
KAUTH_DEVICE_RND_ADDDATA_ESTIMATE, NULL, NULL, NULL, NULL);
break;
default:
return (EINVAL);
}
switch (cmd) {
/*
* Handled in upper layer really, but we have to return zero
* for it to be accepted by the upper layer.
*/
case FIONBIO:
case FIOASYNC:
break;
case RNDGETENTCNT:
mutex_spin_enter(&rndpool_mtx);
*(u_int32_t *)addr = rndpool_get_entropy_count(&rnd_pool);
mutex_spin_exit(&rndpool_mtx);
break;
case RNDGETPOOLSTAT:
mutex_spin_enter(&rndpool_mtx);
rndpool_get_stats(&rnd_pool, addr, sizeof(rndpoolstat_t));
mutex_spin_exit(&rndpool_mtx);
break;
case RNDGETSRCNUM:
rst = (rndstat_t *)addr;
if (rst->count == 0)
break;
if (rst->count > RND_MAXSTATCOUNT)
return (EINVAL);
mutex_spin_enter(&rndpool_mtx);
/*
* Find the starting source by running through the
* list of sources.
*/
kr = rnd_sources.lh_first;
start = rst->start;
while (kr != NULL && start >= 1) {
kr = kr->list.le_next;
start--;
}
/*
* Return up to as many structures as the user asked
* for. If we run out of sources, a count of zero
* will be returned, without an error.
*/
for (count = 0; count < rst->count && kr != NULL; count++) {
krndsource_to_rndsource(kr, &rst->source[count]);
kr = kr->list.le_next;
}
rst->count = count;
mutex_spin_exit(&rndpool_mtx);
break;
case RNDGETSRCNAME:
/*
* Scan through the list, trying to find the name.
*/
mutex_spin_enter(&rndpool_mtx);
rstnm = (rndstat_name_t *)addr;
kr = rnd_sources.lh_first;
while (kr != NULL) {
if (strncmp(kr->name, rstnm->name,
MIN(sizeof(kr->name),
sizeof(*rstnm))) == 0) {
krndsource_to_rndsource(kr, &rstnm->source);
mutex_spin_exit(&rndpool_mtx);
return (0);
}
kr = kr->list.le_next;
}
mutex_spin_exit(&rndpool_mtx);
ret = ENOENT; /* name not found */
break;
case RNDCTL:
/*
* Set flags to enable/disable entropy counting and/or
* collection.
*/
mutex_spin_enter(&rndpool_mtx);
rctl = (rndctl_t *)addr;
kr = rnd_sources.lh_first;
/*
* Flags set apply to all sources of this type.
*/
if (rctl->type != 0xff) {
while (kr != NULL) {
if (kr->type == rctl->type) {
kr->flags &= ~rctl->mask;
kr->flags |=
(rctl->flags & rctl->mask);
}
kr = kr->list.le_next;
}
mutex_spin_exit(&rndpool_mtx);
return (0);
}
/*
* scan through the list, trying to find the name
*/
while (kr != NULL) {
if (strncmp(kr->name, rctl->name,
MIN(sizeof(kr->name),
sizeof(rctl->name))) == 0) {
kr->flags &= ~rctl->mask;
kr->flags |= (rctl->flags & rctl->mask);
mutex_spin_exit(&rndpool_mtx);
return (0);
}
kr = kr->list.le_next;
}
mutex_spin_exit(&rndpool_mtx);
ret = ENOENT; /* name not found */
break;
case RNDADDDATA:
/*
* Don't seed twice if our bootloader has
* seed loading support.
*/
if (!boot_rsp) {
rnddata = (rnddata_t *)addr;
if (rnddata->len > sizeof(rnddata->data))
return EINVAL;
if (estimate_ok) {
/*
* Do not accept absurd entropy estimates, and
* do not flood the pool with entropy such that
* new samples are discarded henceforth.
*/
estimate = MIN((rnddata->len * NBBY) / 2,
MIN(rnddata->entropy,
RND_POOLBITS / 2));
} else {
estimate = 0;
}
mutex_spin_enter(&rndpool_mtx);
rndpool_add_data(&rnd_pool, rnddata->data,
rnddata->len, estimate);
mutex_spin_exit(&rndpool_mtx);
rnd_wakeup_readers();
}
#ifdef RND_VERBOSE
else {
printf("rnd: already seeded by boot loader\n");
}
#endif
break;
default:
return (EINVAL);
}
return (ret);
}
static int
rnd_poll(struct file *fp, int events)
{
int revents;
rp_ctx_t *ctx = fp->f_data;
/*
* We are always writable.
*/
revents = events & (POLLOUT | POLLWRNORM);
/*
* Save some work if not checking for reads.
*/
if ((events & (POLLIN | POLLRDNORM)) == 0)
return (revents);
if (ctx->cprng == NULL) {
rnd_alloc_cprng(ctx);
if (__predict_false(ctx->cprng == NULL)) {
return EIO;
}
}
if (cprng_strong_ready(ctx->cprng)) {
revents |= events & (POLLIN | POLLRDNORM);
} else {
mutex_enter(&ctx->cprng->mtx);
selrecord(curlwp, &ctx->cprng->selq);
mutex_exit(&ctx->cprng->mtx);
}
return (revents);
}
static int
rnd_stat(struct file *fp, struct stat *st)
{
rp_ctx_t *ctx = fp->f_data;
/* XXX lock, if cprng allocated? why? */
memset(st, 0, sizeof(*st));
st->st_dev = makedev(cdevsw_lookup_major(&rnd_cdevsw),
ctx->hard ? RND_DEV_RANDOM :
RND_DEV_URANDOM);
/* XXX leave atimespect, mtimespec, ctimespec = 0? */
st->st_uid = kauth_cred_geteuid(fp->f_cred);
st->st_gid = kauth_cred_getegid(fp->f_cred);
st->st_mode = S_IFCHR;
return 0;
}
static int
rnd_close(struct file *fp)
{
rp_ctx_t *ctx = fp->f_data;
if (ctx->cprng) {
cprng_strong_destroy(ctx->cprng);
}
fp->f_data = NULL;
mutex_destroy(&ctx->interlock);
pool_cache_put(rp_cpc, ctx);
return 0;
}
static void
filt_rnddetach(struct knote *kn)
{
cprng_strong_t *c = kn->kn_hook;
mutex_enter(&c->mtx);
SLIST_REMOVE(&c->selq.sel_klist, kn, knote, kn_selnext);
mutex_exit(&c->mtx);
}
static int
filt_rndread(struct knote *kn, long hint)
{
cprng_strong_t *c = kn->kn_hook;
if (cprng_strong_ready(c)) {
kn->kn_data = RND_TEMP_BUFFER_SIZE;
return 1;
}
return 0;
}
static const struct filterops rnd_seltrue_filtops =
{ 1, NULL, filt_rnddetach, filt_seltrue };
static const struct filterops rndread_filtops =
{ 1, NULL, filt_rnddetach, filt_rndread };
static int
rnd_kqfilter(struct file *fp, struct knote *kn)
{
rp_ctx_t *ctx = fp->f_data;
struct klist *klist;
if (ctx->cprng == NULL) {
rnd_alloc_cprng(ctx);
if (__predict_false(ctx->cprng == NULL)) {
return EIO;
}
}
mutex_enter(&ctx->cprng->mtx);
switch (kn->kn_filter) {
case EVFILT_READ:
klist = &ctx->cprng->selq.sel_klist;
kn->kn_fop = &rndread_filtops;
break;
case EVFILT_WRITE:
klist = &ctx->cprng->selq.sel_klist;
kn->kn_fop = &rnd_seltrue_filtops;
break;
default:
mutex_exit(&ctx->cprng->mtx);
return EINVAL;
}
kn->kn_hook = ctx->cprng;
SLIST_INSERT_HEAD(klist, kn, kn_selnext);
mutex_exit(&ctx->cprng->mtx);
return (0);
}
--- src/sys/dev/iscsi/iscsi_text.c 2011/11/29 03:50:31 1.2
+++ src/sys/dev/iscsi/iscsi_text.c 2011/12/17 20:05:39 1.3
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: iscsi_text.c,v 1.2 2011/11/29 03:50:31 tls Exp $ */ | 1 | /* $NetBSD: iscsi_text.c,v 1.3 2011/12/17 20:05:39 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Wasabi Systems, Inc. | 8 | * by Wasabi Systems, Inc. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -1449,27 +1449,27 @@ assemble_security_parameters(connection_ | @@ -1449,27 +1449,27 @@ assemble_security_parameters(connection_ | |||
1449 | 1449 | |||
1450 | cpar = set_key_s(state, K_Auth_CHAP_Response, state->temp_buf); | 1450 | cpar = set_key_s(state, K_Auth_CHAP_Response, state->temp_buf); | |
1451 | if (cpar != NULL) | 1451 | if (cpar != NULL) | |
1452 | cpar->list_num = CHAP_MD5_SIZE; | 1452 | cpar->list_num = CHAP_MD5_SIZE; | |
1453 | 1453 | |||
1454 | if (par->auth_info.mutual_auth) { | 1454 | if (par->auth_info.mutual_auth) { | |
1455 | if (!state->target_password[0]) { | 1455 | if (!state->target_password[0]) { | |
1456 | DEBOUT(("No target password with mutual authentication!\n")); | 1456 | DEBOUT(("No target password with mutual authentication!\n")); | |
1457 | return ISCSI_STATUS_PARAMETER_MISSING; | 1457 | return ISCSI_STATUS_PARAMETER_MISSING; | |
1458 | } | 1458 | } | |
1459 | 1459 | |||
1460 | cprng_strong(kern_cprng, | 1460 | cprng_strong(kern_cprng, | |
1461 | &state->temp_buf[CHAP_MD5_SIZE], | 1461 | &state->temp_buf[CHAP_MD5_SIZE], | |
1462 | CHAP_CHALLENGE_LEN + 1); | 1462 | CHAP_CHALLENGE_LEN + 1, 0); | |
1463 | set_key_n(state, K_Auth_CHAP_Identifier, | 1463 | set_key_n(state, K_Auth_CHAP_Identifier, | |
1464 | state->temp_buf[CHAP_MD5_SIZE]); | 1464 | state->temp_buf[CHAP_MD5_SIZE]); | |
1465 | cpar = set_key_s(state, K_Auth_CHAP_Challenge, | 1465 | cpar = set_key_s(state, K_Auth_CHAP_Challenge, | |
1466 | &state->temp_buf[CHAP_MD5_SIZE + 1]); | 1466 | &state->temp_buf[CHAP_MD5_SIZE + 1]); | |
1467 | if (cpar != NULL) | 1467 | if (cpar != NULL) | |
1468 | cpar->list_num = CHAP_CHALLENGE_LEN; | 1468 | cpar->list_num = CHAP_CHALLENGE_LEN; | |
1469 | next = -1; | 1469 | next = -1; | |
1470 | } | 1470 | } | |
1471 | state->auth_state = AUTH_CHAP_RSP_SENT; | 1471 | state->auth_state = AUTH_CHAP_RSP_SENT; | |
1472 | break; | 1472 | break; | |
1473 | 1473 | |||
1474 | case AUTH_CHAP_RSP_SENT: | 1474 | case AUTH_CHAP_RSP_SENT: | |
1475 | /* we can only be here for mutual authentication */ | 1475 | /* we can only be here for mutual authentication */ |
--- src/sys/dist/pf/netinet/tcp_rndiss.c 2011/11/19 22:51:24 1.3
+++ src/sys/dist/pf/netinet/tcp_rndiss.c 2011/12/17 20:05:39 1.4
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | /* $OpenBSD: tcp_subr.c,v 1.98 2007/06/25 12:17:43 markus Exp $ */ | 1 | /* $OpenBSD: tcp_subr.c,v 1.98 2007/06/25 12:17:43 markus Exp $ */ | |
2 | /* $NetBSD: tcp_rndiss.c,v 1.3 2011/11/19 22:51:24 tls Exp $ */ | 2 | /* $NetBSD: tcp_rndiss.c,v 1.4 2011/12/17 20:05:39 tls Exp $ */ | |
3 | 3 | |||
4 | /* | 4 | /* | |
5 | * Copyright (c) 1982, 1986, 1988, 1990, 1993 | 5 | * Copyright (c) 1982, 1986, 1988, 1990, 1993 | |
6 | * The Regents of the University of California. All rights reserved. | 6 | * The Regents of the University of California. All rights reserved. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
@@ -59,27 +59,27 @@ | @@ -59,27 +59,27 @@ | |||
59 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 59 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
60 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | 60 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
61 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 61 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
62 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 62 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
63 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 63 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
64 | * | 64 | * | |
65 | * The views and conclusions contained in the software and documentation | 65 | * The views and conclusions contained in the software and documentation | |
66 | * are those of the authors and should not be interpreted as representing | 66 | * are those of the authors and should not be interpreted as representing | |
67 | * official policies, either expressed or implied, of the US Naval | 67 | * official policies, either expressed or implied, of the US Naval | |
68 | * Research Laboratory (NRL). | 68 | * Research Laboratory (NRL). | |
69 | */ | 69 | */ | |
70 | 70 | |||
71 | #include <sys/cdefs.h> | 71 | #include <sys/cdefs.h> | |
72 | __KERNEL_RCSID(0, "$NetBSD: tcp_rndiss.c,v 1.3 2011/11/19 22:51:24 tls Exp $"); | 72 | __KERNEL_RCSID(0, "$NetBSD: tcp_rndiss.c,v 1.4 2011/12/17 20:05:39 tls Exp $"); | |
73 | 73 | |||
74 | #include <sys/param.h> | 74 | #include <sys/param.h> | |
75 | #include <sys/cprng.h> | 75 | #include <sys/cprng.h> | |
76 | 76 | |||
77 | #include <netinet/tcp.h> | 77 | #include <netinet/tcp.h> | |
78 | #include <netinet/tcp_seq.h> | 78 | #include <netinet/tcp_seq.h> | |
79 | #include <netinet/tcp_rndiss.h> | 79 | #include <netinet/tcp_rndiss.h> | |
80 | 80 | |||
81 | #define TCP_RNDISS_ROUNDS 16 | 81 | #define TCP_RNDISS_ROUNDS 16 | |
82 | #define TCP_RNDISS_OUT 7200 | 82 | #define TCP_RNDISS_OUT 7200 | |
83 | #define TCP_RNDISS_MAX 30000 | 83 | #define TCP_RNDISS_MAX 30000 | |
84 | 84 | |||
85 | u_int8_t tcp_rndiss_sbox[128]; | 85 | u_int8_t tcp_rndiss_sbox[128]; | |
@@ -94,27 +94,27 @@ tcp_rndiss_encrypt(u_int16_t val) | @@ -94,27 +94,27 @@ tcp_rndiss_encrypt(u_int16_t val) | |||
94 | 94 | |||
95 | for (i = 0; i < TCP_RNDISS_ROUNDS; i++) { | 95 | for (i = 0; i < TCP_RNDISS_ROUNDS; i++) { | |
96 | sum += 0x79b9; | 96 | sum += 0x79b9; | |
97 | val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7; | 97 | val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7; | |
98 | val = ((val & 0xff) << 7) | (val >> 8); | 98 | val = ((val & 0xff) << 7) | (val >> 8); | |
99 | } | 99 | } | |
100 | 100 | |||
101 | return val; | 101 | return val; | |
102 | } | 102 | } | |
103 | 103 | |||
104 | void | 104 | void | |
105 | tcp_rndiss_init(void) | 105 | tcp_rndiss_init(void) | |
106 | { | 106 | { | |
107 | cprng_strong(kern_cprng, tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox)); | 107 | cprng_strong(kern_cprng, tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox), 0); | |
108 | 108 | |||
109 | tcp_rndiss_reseed = time_second + TCP_RNDISS_OUT; | 109 | tcp_rndiss_reseed = time_second + TCP_RNDISS_OUT; | |
110 | tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000; | 110 | tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000; | |
111 | tcp_rndiss_cnt = 0; | 111 | tcp_rndiss_cnt = 0; | |
112 | } | 112 | } | |
113 | 113 | |||
114 | tcp_seq | 114 | tcp_seq | |
115 | tcp_rndiss_next(void) | 115 | tcp_rndiss_next(void) | |
116 | { | 116 | { | |
117 | if (tcp_rndiss_cnt >= TCP_RNDISS_MAX || | 117 | if (tcp_rndiss_cnt >= TCP_RNDISS_MAX || | |
118 | time_second > tcp_rndiss_reseed) | 118 | time_second > tcp_rndiss_reseed) | |
119 | tcp_rndiss_init(); | 119 | tcp_rndiss_init(); | |
120 | 120 |
--- src/sys/kern/init_sysctl.c 2011/11/20 01:09:14 1.185
+++ src/sys/kern/init_sysctl.c 2011/12/17 20:05:39 1.186
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: init_sysctl.c,v 1.185 2011/11/20 01:09:14 tls Exp $ */ | 1 | /* $NetBSD: init_sysctl.c,v 1.186 2011/12/17 20:05:39 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Andrew Brown, and by Andrew Doran. | 8 | * by Andrew Brown, and by Andrew Doran. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -20,27 +20,27 @@ | @@ -20,27 +20,27 @@ | |||
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | 31 | |||
32 | #include <sys/cdefs.h> | 32 | #include <sys/cdefs.h> | |
33 | __KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.185 2011/11/20 01:09:14 tls Exp $"); | 33 | __KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.186 2011/12/17 20:05:39 tls Exp $"); | |
34 | 34 | |||
35 | #include "opt_sysv.h" | 35 | #include "opt_sysv.h" | |
36 | #include "opt_compat_netbsd.h" | 36 | #include "opt_compat_netbsd.h" | |
37 | #include "opt_modular.h" | 37 | #include "opt_modular.h" | |
38 | #include "opt_sa.h" | 38 | #include "opt_sa.h" | |
39 | #include "opt_posix.h" | 39 | #include "opt_posix.h" | |
40 | #include "pty.h" | 40 | #include "pty.h" | |
41 | 41 | |||
42 | #include <sys/types.h> | 42 | #include <sys/types.h> | |
43 | #include <sys/param.h> | 43 | #include <sys/param.h> | |
44 | #include <sys/sysctl.h> | 44 | #include <sys/sysctl.h> | |
45 | #include <sys/cpu.h> | 45 | #include <sys/cpu.h> | |
46 | #include <sys/errno.h> | 46 | #include <sys/errno.h> | |
@@ -1386,27 +1386,27 @@ sysctl_kern_sbmax(SYSCTLFN_ARGS) | @@ -1386,27 +1386,27 @@ sysctl_kern_sbmax(SYSCTLFN_ARGS) | |||
1386 | 1386 | |||
1387 | return (error); | 1387 | return (error); | |
1388 | } | 1388 | } | |
1389 | 1389 | |||
1390 | /* | 1390 | /* | |
1391 | * sysctl helper routine for kern.urandom node. Picks a random number | 1391 | * sysctl helper routine for kern.urandom node. Picks a random number | |
1392 | * for you. | 1392 | * for you. | |
1393 | */ | 1393 | */ | |
1394 | static int | 1394 | static int | |
1395 | sysctl_kern_urnd(SYSCTLFN_ARGS) | 1395 | sysctl_kern_urnd(SYSCTLFN_ARGS) | |
1396 | { | 1396 | { | |
1397 | int v, rv; | 1397 | int v, rv; | |
1398 | 1398 | |||
1399 | rv = cprng_strong(sysctl_prng, &v, sizeof(v)); | 1399 | rv = cprng_strong(sysctl_prng, &v, sizeof(v), 0); | |
1400 | if (rv == sizeof(v)) { | 1400 | if (rv == sizeof(v)) { | |
1401 | struct sysctlnode node = *rnode; | 1401 | struct sysctlnode node = *rnode; | |
1402 | node.sysctl_data = &v; | 1402 | node.sysctl_data = &v; | |
1403 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | 1403 | return (sysctl_lookup(SYSCTLFN_CALL(&node))); | |
1404 | } | 1404 | } | |
1405 | else | 1405 | else | |
1406 | return (EIO); /*XXX*/ | 1406 | return (EIO); /*XXX*/ | |
1407 | } | 1407 | } | |
1408 | 1408 | |||
1409 | /* | 1409 | /* | |
1410 | * sysctl helper routine for kern.arandom node. Picks a random number | 1410 | * sysctl helper routine for kern.arandom node. Picks a random number | |
1411 | * for you. | 1411 | * for you. | |
1412 | */ | 1412 | */ |
--- src/sys/kern/subr_cprng.c 2011/11/29 21:48:22 1.4
+++ src/sys/kern/subr_cprng.c 2011/12/17 20:05:39 1.5
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: subr_cprng.c,v 1.4 2011/11/29 21:48:22 njoly Exp $ */ | 1 | /* $NetBSD: subr_cprng.c,v 1.5 2011/12/17 20:05:39 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -36,252 +36,262 @@ | @@ -36,252 +36,262 @@ | |||
36 | #include <sys/systm.h> | 36 | #include <sys/systm.h> | |
37 | #include <sys/kmem.h> | 37 | #include <sys/kmem.h> | |
38 | #include <sys/mutex.h> | 38 | #include <sys/mutex.h> | |
39 | #include <sys/rngtest.h> | 39 | #include <sys/rngtest.h> | |
40 | #include <sys/rnd.h> | 40 | #include <sys/rnd.h> | |
41 | #include <dev/rnd_private.h> | 41 | #include <dev/rnd_private.h> | |
42 | 42 | |||
43 | #if defined(__HAVE_CPU_COUNTER) | 43 | #if defined(__HAVE_CPU_COUNTER) | |
44 | #include <machine/cpu_counter.h> | 44 | #include <machine/cpu_counter.h> | |
45 | #endif | 45 | #endif | |
46 | 46 | |||
47 | #include <sys/cprng.h> | 47 | #include <sys/cprng.h> | |
48 | 48 | |||
49 | __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.4 2011/11/29 21:48:22 njoly Exp $"); | 49 | __KERNEL_RCSID(0, "$NetBSD: subr_cprng.c,v 1.5 2011/12/17 20:05:39 tls Exp $"); | |
50 | 50 | |||
51 | void | 51 | void | |
52 | cprng_init(void) | 52 | cprng_init(void) | |
53 | { | 53 | { | |
54 | nist_ctr_initialize(); | 54 | nist_ctr_initialize(); | |
55 | } | 55 | } | |
56 | 56 | |||
57 | static inline uint32_t | 57 | static inline uint32_t | |
58 | cprng_counter(void) | 58 | cprng_counter(void) | |
59 | { | 59 | { | |
60 | struct timeval tv; | 60 | struct timeval tv; | |
61 | 61 | |||
62 | #if defined(__HAVE_CPU_COUNTER) | 62 | #if defined(__HAVE_CPU_COUNTER) | |
63 | if (cpu_hascounter()) | 63 | if (cpu_hascounter()) | |
64 | return cpu_counter32(); | 64 | return cpu_counter32(); | |
65 | #endif | 65 | #endif | |
66 | if (__predict_false(cold)) { | 66 | if (__predict_false(cold)) { | |
67 | /* microtime unsafe if clock not running yet */ | 67 | /* microtime unsafe if clock not running yet */ | |
68 | return 0; | 68 | return 0; | |
69 | } | 69 | } | |
70 | microtime(&tv); | 70 | microtime(&tv); | |
71 | return (tv.tv_sec * 1000000 + tv.tv_usec); | 71 | return (tv.tv_sec * 1000000 + tv.tv_usec); | |
72 | } | 72 | } | |
73 | 73 | |||
74 | static void | 74 | static void | |
75 | cprng_strong_sched_reseed(cprng_strong_t *const c) | |||
76 | { | |||
77 | KASSERT(mutex_owned(&c->mtx)); | |||
78 | if (!(c->reseed_pending)) { | |||
79 | c->reseed_pending = 1; | |||
80 | c->reseed.len = NIST_BLOCK_KEYLEN_BYTES; | |||
81 | rndsink_attach(&c->reseed); | |||
82 | } | |||
83 | } | |||
84 | ||||
85 | static void | |||
75 | cprng_strong_reseed(void *const arg) | 86 | cprng_strong_reseed(void *const arg) | |
76 | { | 87 | { | |
77 | cprng_strong_t *c = arg; | 88 | cprng_strong_t *c = arg; | |
78 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | 89 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | |
79 | uint32_t cc = cprng_counter(); | 90 | uint32_t cc = cprng_counter(); | |
80 | 91 | |||
81 | mutex_enter(&c->mtx); | 92 | mutex_enter(&c->mtx); | |
82 | if (c->reseed.len != sizeof(key)) { | 93 | if (c->reseed.len != sizeof(key)) { | |
83 | panic("cprng_strong_reseed: bad entropy length %d " | 94 | panic("cprng_strong_reseed: bad entropy length %d " | |
84 | " (expected %d)", (int)c->reseed.len, (int)sizeof(key)); | 95 | " (expected %d)", (int)c->reseed.len, (int)sizeof(key)); | |
85 | } | 96 | } | |
86 | if (nist_ctr_drbg_reseed(&c->drbg, c->reseed.data, c->reseed.len, | 97 | if (nist_ctr_drbg_reseed(&c->drbg, c->reseed.data, c->reseed.len, | |
87 | &cc, sizeof(cc))) { | 98 | &cc, sizeof(cc))) { | |
88 | panic("cprng %s: nist_ctr_drbg_reseed failed.", c->name); | 99 | panic("cprng %s: nist_ctr_drbg_reseed failed.", c->name); | |
89 | } | 100 | } | |
90 | c->reseed_pending = 0; | 101 | c->reseed_pending = 0; | |
91 | if (c->flags & CPRNG_USE_CV) { | 102 | if (c->flags & CPRNG_USE_CV) { | |
92 | cv_broadcast(&c->cv); | 103 | cv_broadcast(&c->cv); | |
93 | } | 104 | } | |
105 | selnotify(&c->selq, 0, 0); | |||
94 | mutex_exit(&c->mtx); | 106 | mutex_exit(&c->mtx); | |
95 | } | 107 | } | |
96 | 108 | |||
97 | cprng_strong_t * | 109 | cprng_strong_t * | |
98 | cprng_strong_create(const char *const name, int ipl, int flags) | 110 | cprng_strong_create(const char *const name, int ipl, int flags) | |
99 | { | 111 | { | |
100 | cprng_strong_t *c; | 112 | cprng_strong_t *c; | |
101 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | 113 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | |
102 | int r, getmore = 0; | 114 | int r, getmore = 0, hard = 0; | |
103 | uint32_t cc; | 115 | uint32_t cc; | |
104 | 116 | |||
105 | c = kmem_alloc(sizeof(*c), KM_NOSLEEP); | 117 | c = kmem_alloc(sizeof(*c), KM_NOSLEEP); | |
106 | if (c == NULL) { | 118 | if (c == NULL) { | |
107 | return NULL; | 119 | return NULL; | |
108 | } | 120 | } | |
109 | c->flags = flags; | 121 | c->flags = flags; | |
110 | strlcpy(c->name, name, sizeof(c->name)); | 122 | strlcpy(c->name, name, sizeof(c->name)); | |
111 | c->reseed_pending = 0; | 123 | c->reseed_pending = 0; | |
112 | c->reseed.cb = cprng_strong_reseed; | 124 | c->reseed.cb = cprng_strong_reseed; | |
113 | c->reseed.arg = c; | 125 | c->reseed.arg = c; | |
114 | strlcpy(c->reseed.name, name, sizeof(c->reseed.name)); | 126 | strlcpy(c->reseed.name, name, sizeof(c->reseed.name)); | |
115 | 127 | |||
116 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | 128 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | |
117 | 129 | |||
118 | if (c->flags & CPRNG_USE_CV) { | 130 | if (c->flags & CPRNG_USE_CV) { | |
119 | cv_init(&c->cv, name); | 131 | cv_init(&c->cv, name); | |
120 | } | 132 | } | |
121 | 133 | |||
134 | selinit(&c->selq); | |||
135 | ||||
122 | r = rnd_extract_data(key, sizeof(key), RND_EXTRACT_GOOD); | 136 | r = rnd_extract_data(key, sizeof(key), RND_EXTRACT_GOOD); | |
123 | if (r != sizeof(key)) { | 137 | if (r != sizeof(key)) { | |
124 | if (c->flags & CPRNG_INIT_ANY) { | 138 | if (c->flags & CPRNG_INIT_ANY) { | |
139 | #ifdef DEBUG | |||
125 | printf("cprng %s: WARNING insufficient " | 140 | printf("cprng %s: WARNING insufficient " | |
126 | "entropy at creation.\n", name); | 141 | "entropy at creation.\n", name); | |
142 | #endif | |||
127 | rnd_extract_data(key + r, sizeof(key - r), | 143 | rnd_extract_data(key + r, sizeof(key - r), | |
128 | RND_EXTRACT_ANY); | 144 | RND_EXTRACT_ANY); | |
129 | } else { | 145 | } else { | |
130 | return NULL; | 146 | hard++; | |
131 | } | 147 | } | |
132 | getmore++; | 148 | getmore++; | |
133 | } | 149 | } | |
134 | 150 | |||
135 | if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key), | 151 | if (nist_ctr_drbg_instantiate(&c->drbg, key, sizeof(key), | |
136 | &cc, sizeof(cc), name, strlen(name))) { | 152 | &cc, sizeof(cc), name, strlen(name))) { | |
137 | panic("cprng %s: instantiation failed.", name); | 153 | panic("cprng %s: instantiation failed.", name); | |
138 | } | 154 | } | |
139 | 155 | |||
140 | if (getmore) { | 156 | if (getmore) { | |
141 | int wr = 0; | 157 | /* Cause readers to wait for rekeying. */ | |
142 | 158 | if (hard) { | ||
143 | /* Ask for more. */ | 159 | c->drbg.reseed_counter = | |
144 | c->reseed_pending = 1; | 160 | NIST_CTR_DRBG_RESEED_INTERVAL + 1; | |
145 | c->reseed.len = sizeof(key); | 161 | } else { | |
146 | rndsink_attach(&c->reseed); | 162 | c->drbg.reseed_counter = | |
147 | if (c->flags & CPRNG_USE_CV) { | 163 | (NIST_CTR_DRBG_RESEED_INTERVAL / 2) + 1; | |
148 | mutex_enter(&c->mtx); | |||
149 | do { | |||
150 | wr = cv_wait_sig(&c->cv, &c->mtx); | |||
151 | if (__predict_true(wr == 0)) { | |||
152 | break; | |||
153 | } | |||
154 | if (wr == ERESTART) { | |||
155 | continue; | |||
156 | } else { | |||
157 | cv_destroy(&c->cv); | |||
158 | mutex_exit(&c->mtx); | |||
159 | mutex_destroy(&c->mtx); | |||
160 | kmem_free(c, sizeof(c)); | |||
161 | return NULL; | |||
162 | } | |||
163 | } while (1); | |||
164 | mutex_exit(&c->mtx); | |||
165 | } | 164 | } | |
166 | } | 165 | } | |
167 | return c; | 166 | return c; | |
168 | } | 167 | } | |
169 | 168 | |||
170 | size_t | 169 | size_t | |
171 | cprng_strong(cprng_strong_t *const c, void *const p, size_t len) | 170 | cprng_strong(cprng_strong_t *const c, void *const p, size_t len, int flags) | |
172 | { | 171 | { | |
173 | uint32_t cc = cprng_counter(); | 172 | uint32_t cc = cprng_counter(); | |
174 | 173 | #ifdef DEBUG | ||
174 | int testfail = 0; | |||
175 | #endif | |||
175 | if (len > CPRNG_MAX_LEN) { /* XXX should we loop? */ | 176 | if (len > CPRNG_MAX_LEN) { /* XXX should we loop? */ | |
176 | len = CPRNG_MAX_LEN; /* let the caller loop if desired */ | 177 | len = CPRNG_MAX_LEN; /* let the caller loop if desired */ | |
177 | } | 178 | } | |
178 | ||||
179 | mutex_enter(&c->mtx); | 179 | mutex_enter(&c->mtx); | |
180 | again: | 180 | ||
181 | if (nist_ctr_drbg_generate(&c->drbg, p, len, &cc, sizeof(cc))) { | 181 | if (nist_ctr_drbg_generate(&c->drbg, p, len, &cc, sizeof(cc))) { | |
182 | /* A generator failure really means we hit the hard limit. */ | 182 | /* A generator failure really means we hit the hard limit. */ | |
183 | if (c->flags & CPRNG_REKEY_ANY) { | 183 | if (c->flags & CPRNG_REKEY_ANY) { | |
184 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | 184 | uint8_t key[NIST_BLOCK_KEYLEN_BYTES]; | |
185 | 185 | |||
186 | printf("cprng %s: WARNING pseudorandom rekeying.\n", | 186 | printf("cprng %s: WARNING pseudorandom rekeying.\n", | |
187 | c->name); | 187 | c->name); | |
188 | rnd_extract_data(key, sizeof(key), RND_EXTRACT_ANY); | 188 | rnd_extract_data(key, sizeof(key), RND_EXTRACT_ANY); | |
189 | cc = cprng_counter(); | 189 | cc = cprng_counter(); | |
190 | if (nist_ctr_drbg_reseed(&c->drbg, key, sizeof(key), | 190 | if (nist_ctr_drbg_reseed(&c->drbg, key, sizeof(key), | |
191 | &cc, sizeof(cc))) { | 191 | &cc, sizeof(cc))) { | |
192 | panic("cprng %s: nist_ctr_drbg_reseed " | 192 | panic("cprng %s: nist_ctr_drbg_reseed " | |
193 | "failed.", c->name); | 193 | "failed.", c->name); | |
194 | } | 194 | } | |
195 | if (c->flags & CPRNG_USE_CV) { | |||
196 | cv_broadcast(&c->cv); /* XXX unnecessary? */ | |||
197 | } | |||
198 | } else { | 195 | } else { | |
199 | if (c->flags & CPRNG_USE_CV) { | 196 | if (!(flags & FNONBLOCK) && | |
197 | (c->flags & CPRNG_USE_CV)) { | |||
200 | int wr; | 198 | int wr; | |
201 | 199 | |||
200 | cprng_strong_sched_reseed(c); | |||
202 | do { | 201 | do { | |
203 | wr = cv_wait_sig(&c->cv, &c->mtx); | 202 | wr = cv_wait_sig(&c->cv, &c->mtx); | |
204 | if (wr == EINTR) { | 203 | if (wr == ERESTART) { | |
205 | mutex_exit(&c->mtx); | 204 | mutex_exit(&c->mtx); | |
206 | return 0; | 205 | return 0; | |
207 | } | 206 | } | |
208 | } while (nist_ctr_drbg_generate(&c->drbg, p, | 207 | } while (nist_ctr_drbg_generate(&c->drbg, p, | |
209 | len, &cc, | 208 | len, &cc, | |
210 | sizeof(cc))); | 209 | sizeof(cc))); | |
211 | } else { | 210 | } else { | |
212 | mutex_exit(&c->mtx); | 211 | len = 0; | |
213 | return 0; | |||
214 | } | 212 | } | |
215 | } | 213 | } | |
216 | } | 214 | } | |
217 | 215 | |||
218 | #ifdef DIAGNOSTIC | 216 | #ifdef DEBUG | |
219 | /* | 217 | /* | |
220 | * If the generator has just been keyed, perform | 218 | * If the generator has just been keyed, perform | |
221 | * the statistical RNG test. | 219 | * the statistical RNG test. | |
222 | */ | 220 | */ | |
223 | if (__predict_false(c->drbg.reseed_counter == 1)) { | 221 | if (__predict_false(c->drbg.reseed_counter == 1)) { | |
224 | rngtest_t rt; | 222 | rngtest_t *rt = kmem_alloc(sizeof(*rt), KM_NOSLEEP); | |
225 | 223 | |||
226 | strncpy(rt.rt_name, c->name, sizeof(rt.rt_name)); | 224 | if (rt) { | |
227 | 225 | |||
228 | if (nist_ctr_drbg_generate(&c->drbg, rt.rt_b, | 226 | strncpy(rt->rt_name, c->name, sizeof(rt->rt_name)); | |
229 | sizeof(rt.rt_b), NULL, 0)) { | 227 | ||
230 | panic("cprng %s: nist_ctr_drbg_generate failed!", | 228 | if (nist_ctr_drbg_generate(&c->drbg, rt->rt_b, | |
231 | c->name); | 229 | sizeof(rt->rt_b), NULL, 0)) { | |
230 | panic("cprng %s: nist_ctr_drbg_generate " | |||
231 | "failed!", c->name); | |||
232 | 232 | |||
233 | } | 233 | } | |
234 | if (rngtest(&rt)) { | 234 | testfail = rngtest(rt); | |
235 | printf("cprng %s: failed statistical RNG test.\n", | |||
236 | c->name); | |||
237 | c->drbg.reseed_counter = | |||
238 | NIST_CTR_DRBG_RESEED_INTERVAL + 1; | |||
239 | } | |||
240 | 235 | |||
241 | memset(&rt, 0, sizeof(rt)); | 236 | if (testfail) { | |
237 | printf("cprng %s: failed statistical RNG " | |||
238 | "test.\n", c->name); | |||
239 | c->drbg.reseed_counter = | |||
240 | NIST_CTR_DRBG_RESEED_INTERVAL + 1; | |||
241 | len = 0; | |||
242 | } | |||
243 | memset(rt, 0, sizeof(*rt)); | |||
244 | kmem_free(rt, sizeof(*rt)); | |||
245 | } | |||
242 | } | 246 | } | |
243 | #endif | 247 | #endif | |
244 | if (__predict_false(c->drbg.reseed_counter > | 248 | if (__predict_false(c->drbg.reseed_counter > | |
245 | (NIST_CTR_DRBG_RESEED_INTERVAL / 2))) { | 249 | (NIST_CTR_DRBG_RESEED_INTERVAL / 2))) { | |
246 | if (!(c->reseed_pending)) { | 250 | cprng_strong_sched_reseed(c); | |
247 | c->reseed_pending = 1; | 251 | } | |
248 | c->reseed.len = NIST_BLOCK_KEYLEN_BYTES; | 252 | ||
249 | rndsink_attach(&c->reseed); | 253 | if (rnd_full) { | |
250 | } | 254 | if (!c->rekeyed_on_full) { | |
251 | if (__predict_false(c->drbg.reseed_counter > | 255 | c->rekeyed_on_full++; | |
252 | NIST_CTR_DRBG_RESEED_INTERVAL)) { | 256 | cprng_strong_sched_reseed(c); | |
253 | goto again; /* statistical test failure */ | |||
254 | } | 257 | } | |
258 | } else { | |||
259 | c->rekeyed_on_full = 0; | |||
255 | } | 260 | } | |
256 | 261 | |||
257 | mutex_exit(&c->mtx); | 262 | mutex_exit(&c->mtx); | |
258 | return len; | 263 | return len; | |
259 | } | 264 | } | |
260 | 265 | |||
261 | void | 266 | void | |
262 | cprng_strong_destroy(cprng_strong_t *c) | 267 | cprng_strong_destroy(cprng_strong_t *c) | |
263 | { | 268 | { | |
264 | KASSERT(!mutex_owned(&c->mtx)); | 269 | mutex_enter(&c->mtx); | |
270 | ||||
265 | if (c->flags & CPRNG_USE_CV) { | 271 | if (c->flags & CPRNG_USE_CV) { | |
266 | KASSERT(!cv_has_waiters(&c->cv)); | 272 | KASSERT(!cv_has_waiters(&c->cv)); | |
267 | cv_destroy(&c->cv); | 273 | cv_destroy(&c->cv); | |
268 | } | 274 | } | |
275 | seldestroy(&c->selq); | |||
269 | 276 | |||
270 | mutex_destroy(&c->mtx); | |||
271 | if (c->reseed_pending) { | 277 | if (c->reseed_pending) { | |
272 | rndsink_detach(&c->reseed); | 278 | rndsink_detach(&c->reseed); | |
273 | } | 279 | } | |
274 | nist_ctr_drbg_destroy(&c->drbg); | 280 | nist_ctr_drbg_destroy(&c->drbg); | |
281 | ||||
282 | mutex_exit(&c->mtx); | |||
283 | mutex_destroy(&c->mtx); | |||
284 | ||||
275 | memset(c, 0, sizeof(*c)); | 285 | memset(c, 0, sizeof(*c)); | |
276 | kmem_free(c, sizeof(*c)); | 286 | kmem_free(c, sizeof(*c)); | |
277 | } | 287 | } | |
278 | 288 | |||
279 | int | 289 | int | |
280 | cprng_strong_getflags(cprng_strong_t *const c) | 290 | cprng_strong_getflags(cprng_strong_t *const c) | |
281 | { | 291 | { | |
282 | KASSERT(mutex_owned(&c->mtx)); | 292 | KASSERT(mutex_owned(&c->mtx)); | |
283 | return c->flags; | 293 | return c->flags; | |
284 | } | 294 | } | |
285 | 295 | |||
286 | void | 296 | void | |
287 | cprng_strong_setflags(cprng_strong_t *const c, int flags) | 297 | cprng_strong_setflags(cprng_strong_t *const c, int flags) | |
@@ -292,17 +302,18 @@ cprng_strong_setflags(cprng_strong_t *co | @@ -292,17 +302,18 @@ cprng_strong_setflags(cprng_strong_t *co | |||
292 | cv_init(&c->cv, (const char *)c->name); | 302 | cv_init(&c->cv, (const char *)c->name); | |
293 | } | 303 | } | |
294 | } else { | 304 | } else { | |
295 | if (c->flags & CPRNG_USE_CV) { | 305 | if (c->flags & CPRNG_USE_CV) { | |
296 | KASSERT(!cv_has_waiters(&c->cv)); | 306 | KASSERT(!cv_has_waiters(&c->cv)); | |
297 | cv_destroy(&c->cv); | 307 | cv_destroy(&c->cv); | |
298 | } | 308 | } | |
299 | } | 309 | } | |
300 | if (flags & CPRNG_REKEY_ANY) { | 310 | if (flags & CPRNG_REKEY_ANY) { | |
301 | if (!(c->flags & CPRNG_REKEY_ANY)) { | 311 | if (!(c->flags & CPRNG_REKEY_ANY)) { | |
302 | if (c->flags & CPRNG_USE_CV) { | 312 | if (c->flags & CPRNG_USE_CV) { | |
303 | cv_broadcast(&c->cv); | 313 | cv_broadcast(&c->cv); | |
304 | } | 314 | } | |
315 | selnotify(&c->selq, 0, 0); | |||
305 | } | 316 | } | |
306 | } | 317 | } | |
307 | c->flags = flags; | 318 | c->flags = flags; | |
308 | } | 319 | } |
--- src/sys/net/if_spppsubr.c 2011/11/19 22:51:25 1.124
+++ src/sys/net/if_spppsubr.c 2011/12/17 20:05:39 1.125
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if_spppsubr.c,v 1.124 2011/11/19 22:51:25 tls Exp $ */ | 1 | /* $NetBSD: if_spppsubr.c,v 1.125 2011/12/17 20:05:39 tls Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Synchronous PPP/Cisco link level subroutines. | 4 | * Synchronous PPP/Cisco link level subroutines. | |
5 | * Keepalive protocol implemented in both Cisco and PPP modes. | 5 | * Keepalive protocol implemented in both Cisco and PPP modes. | |
6 | * | 6 | * | |
7 | * Copyright (C) 1994-1996 Cronyx Engineering Ltd. | 7 | * Copyright (C) 1994-1996 Cronyx Engineering Ltd. | |
8 | * Author: Serge Vakulenko, <vak@cronyx.ru> | 8 | * Author: Serge Vakulenko, <vak@cronyx.ru> | |
9 | * | 9 | * | |
10 | * Heavily revamped to conform to RFC 1661. | 10 | * Heavily revamped to conform to RFC 1661. | |
11 | * Copyright (C) 1997, Joerg Wunsch. | 11 | * Copyright (C) 1997, Joerg Wunsch. | |
12 | * | 12 | * | |
13 | * RFC2472 IPv6CP support. | 13 | * RFC2472 IPv6CP support. | |
14 | * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun@iijlab.net>. | 14 | * Copyright (C) 2000, Jun-ichiro itojun Hagino <itojun@iijlab.net>. | |
@@ -31,27 +31,27 @@ | @@ -31,27 +31,27 @@ | |||
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. | |
35 | * | 35 | * | |
36 | * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 | 36 | * From: Version 2.4, Thu Apr 30 17:17:21 MSD 1997 | |
37 | * | 37 | * | |
38 | * From: if_spppsubr.c,v 1.39 1998/04/04 13:26:03 phk Exp | 38 | * From: if_spppsubr.c,v 1.39 1998/04/04 13:26:03 phk Exp | |
39 | * | 39 | * | |
40 | * From: Id: if_spppsubr.c,v 1.23 1999/02/23 14:47:50 hm Exp | 40 | * From: Id: if_spppsubr.c,v 1.23 1999/02/23 14:47:50 hm Exp | |
41 | */ | 41 | */ | |
42 | 42 | |||
43 | #include <sys/cdefs.h> | 43 | #include <sys/cdefs.h> | |
44 | __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.124 2011/11/19 22:51:25 tls Exp $"); | 44 | __KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.125 2011/12/17 20:05:39 tls Exp $"); | |
45 | 45 | |||
46 | #if defined(_KERNEL_OPT) | 46 | #if defined(_KERNEL_OPT) | |
47 | #include "opt_inet.h" | 47 | #include "opt_inet.h" | |
48 | #include "opt_ipx.h" | 48 | #include "opt_ipx.h" | |
49 | #include "opt_iso.h" | 49 | #include "opt_iso.h" | |
50 | #include "opt_pfil_hooks.h" | 50 | #include "opt_pfil_hooks.h" | |
51 | #include "opt_modular.h" | 51 | #include "opt_modular.h" | |
52 | #include "opt_compat_netbsd.h" | 52 | #include "opt_compat_netbsd.h" | |
53 | #endif | 53 | #endif | |
54 | 54 | |||
55 | 55 | |||
56 | #include <sys/param.h> | 56 | #include <sys/param.h> | |
57 | #include <sys/proc.h> | 57 | #include <sys/proc.h> | |
@@ -4288,27 +4288,27 @@ sppp_chap_scr(struct sppp *sp) | @@ -4288,27 +4288,27 @@ sppp_chap_scr(struct sppp *sp) | |||
4288 | { | 4288 | { | |
4289 | uint32_t *ch; | 4289 | uint32_t *ch; | |
4290 | u_char clen = 4 * sizeof(uint32_t); | 4290 | u_char clen = 4 * sizeof(uint32_t); | |
4291 | 4291 | |||
4292 | if (sp->myauth.name == NULL) { | 4292 | if (sp->myauth.name == NULL) { | |
4293 | /* can't do anything useful */ | 4293 | /* can't do anything useful */ | |
4294 | printf("%s: chap starting without my name being set\n", | 4294 | printf("%s: chap starting without my name being set\n", | |
4295 | sp->pp_if.if_xname); | 4295 | sp->pp_if.if_xname); | |
4296 | return; | 4296 | return; | |
4297 | } | 4297 | } | |
4298 | 4298 | |||
4299 | /* Compute random challenge. */ | 4299 | /* Compute random challenge. */ | |
4300 | ch = (uint32_t *)sp->myauth.challenge; | 4300 | ch = (uint32_t *)sp->myauth.challenge; | |
4301 | cprng_strong(kern_cprng, ch, clen); | 4301 | cprng_strong(kern_cprng, ch, clen, 0); | |
4302 | 4302 | |||
4303 | sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; | 4303 | sp->confid[IDX_CHAP] = ++sp->pp_seq[IDX_CHAP]; | |
4304 | 4304 | |||
4305 | sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], | 4305 | sppp_auth_send(&chap, sp, CHAP_CHALLENGE, sp->confid[IDX_CHAP], | |
4306 | sizeof clen, (const char *)&clen, | 4306 | sizeof clen, (const char *)&clen, | |
4307 | sizeof(sp->myauth.challenge), sp->myauth.challenge, | 4307 | sizeof(sp->myauth.challenge), sp->myauth.challenge, | |
4308 | sp->myauth.name_len, | 4308 | sp->myauth.name_len, | |
4309 | sp->myauth.name, | 4309 | sp->myauth.name, | |
4310 | 0); | 4310 | 0); | |
4311 | } | 4311 | } | |
4312 | 4312 | |||
4313 | /* | 4313 | /* | |
4314 | *--------------------------------------------------------------------------* | 4314 | *--------------------------------------------------------------------------* |
--- src/sys/netinet/tcp_subr.c 2011/11/19 22:51:26 1.243
+++ src/sys/netinet/tcp_subr.c 2011/12/17 20:05:39 1.244
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tcp_subr.c,v 1.243 2011/11/19 22:51:26 tls Exp $ */ | 1 | /* $NetBSD: tcp_subr.c,v 1.244 2011/12/17 20:05:39 tls Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -81,27 +81,27 @@ | @@ -81,27 +81,27 @@ | |||
81 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 81 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
82 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 82 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
83 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 83 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
84 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 84 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
85 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 85 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
86 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 86 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
87 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 87 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
88 | * SUCH DAMAGE. | 88 | * SUCH DAMAGE. | |
89 | * | 89 | * | |
90 | * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 | 90 | * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 | |
91 | */ | 91 | */ | |
92 | 92 | |||
93 | #include <sys/cdefs.h> | 93 | #include <sys/cdefs.h> | |
94 | __KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.243 2011/11/19 22:51:26 tls Exp $"); | 94 | __KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.244 2011/12/17 20:05:39 tls Exp $"); | |
95 | 95 | |||
96 | #include "opt_inet.h" | 96 | #include "opt_inet.h" | |
97 | #include "opt_ipsec.h" | 97 | #include "opt_ipsec.h" | |
98 | #include "opt_tcp_compat_42.h" | 98 | #include "opt_tcp_compat_42.h" | |
99 | #include "opt_inet_csum.h" | 99 | #include "opt_inet_csum.h" | |
100 | #include "opt_mbuftrace.h" | 100 | #include "opt_mbuftrace.h" | |
101 | 101 | |||
102 | #include <sys/param.h> | 102 | #include <sys/param.h> | |
103 | #include <sys/proc.h> | 103 | #include <sys/proc.h> | |
104 | #include <sys/systm.h> | 104 | #include <sys/systm.h> | |
105 | #include <sys/malloc.h> | 105 | #include <sys/malloc.h> | |
106 | #include <sys/mbuf.h> | 106 | #include <sys/mbuf.h> | |
107 | #include <sys/socket.h> | 107 | #include <sys/socket.h> | |
@@ -2210,27 +2210,27 @@ tcp_seq | @@ -2210,27 +2210,27 @@ tcp_seq | |||
2210 | tcp_new_iss1(void *laddr, void *faddr, u_int16_t lport, u_int16_t fport, | 2210 | tcp_new_iss1(void *laddr, void *faddr, u_int16_t lport, u_int16_t fport, | |
2211 | size_t addrsz, tcp_seq addin) | 2211 | size_t addrsz, tcp_seq addin) | |
2212 | { | 2212 | { | |
2213 | tcp_seq tcp_iss; | 2213 | tcp_seq tcp_iss; | |
2214 | 2214 | |||
2215 | static bool tcp_iss_gotten_secret; | 2215 | static bool tcp_iss_gotten_secret; | |
2216 | 2216 | |||
2217 | /* | 2217 | /* | |
2218 | * If we haven't been here before, initialize our cryptographic | 2218 | * If we haven't been here before, initialize our cryptographic | |
2219 | * hash secret. | 2219 | * hash secret. | |
2220 | */ | 2220 | */ | |
2221 | if (tcp_iss_gotten_secret == false) { | 2221 | if (tcp_iss_gotten_secret == false) { | |
2222 | cprng_strong(kern_cprng, | 2222 | cprng_strong(kern_cprng, | |
2223 | tcp_iss_secret, sizeof(tcp_iss_secret)); | 2223 | tcp_iss_secret, sizeof(tcp_iss_secret), 0); | |
2224 | tcp_iss_gotten_secret = true; | 2224 | tcp_iss_gotten_secret = true; | |
2225 | } | 2225 | } | |
2226 | 2226 | |||
2227 | if (tcp_do_rfc1948) { | 2227 | if (tcp_do_rfc1948) { | |
2228 | MD5_CTX ctx; | 2228 | MD5_CTX ctx; | |
2229 | u_int8_t hash[16]; /* XXX MD5 knowledge */ | 2229 | u_int8_t hash[16]; /* XXX MD5 knowledge */ | |
2230 | 2230 | |||
2231 | /* | 2231 | /* | |
2232 | * Compute the base value of the ISS. It is a hash | 2232 | * Compute the base value of the ISS. It is a hash | |
2233 | * of (saddr, sport, daddr, dport, secret). | 2233 | * of (saddr, sport, daddr, dport, secret). | |
2234 | */ | 2234 | */ | |
2235 | MD5Init(&ctx); | 2235 | MD5Init(&ctx); | |
2236 | 2236 |
--- src/sys/rump/dev/lib/librnd/Makefile 2010/02/16 20:42:45 1.2
+++ src/sys/rump/dev/lib/librnd/Makefile 2011/12/17 20:05:39 1.3
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | # $NetBSD: Makefile,v 1.2 2010/02/16 20:42:45 pooka Exp $ | 1 | # $NetBSD: Makefile,v 1.3 2011/12/17 20:05:39 tls Exp $ | |
2 | # | 2 | # | |
3 | 3 | |||
4 | .PATH: ${.CURDIR}/../../../../dev | 4 | .PATH: ${.CURDIR}/../../../../dev | |
5 | 5 | |||
6 | LIB= rumpdev_rnd | 6 | LIB= rumpdev_rnd | |
7 | 7 | |||
8 | SRCS= rnd.c rndpool.c | 8 | SRCS= rnd.c rndpseudo.c rndpool.c | |
9 | 9 | |||
10 | SRCS+= component.c | 10 | SRCS+= component.c | |
11 | 11 | |||
12 | CPPFLAGS+= -I${RUMPTOP}/librump/rumpvfs | 12 | CPPFLAGS+= -I${RUMPTOP}/librump/rumpvfs | |
13 | 13 | |||
14 | .include <bsd.lib.mk> | 14 | .include <bsd.lib.mk> | |
15 | .include <bsd.klinks.mk> | 15 | .include <bsd.klinks.mk> |
--- src/sys/rump/librump/rumpkern/Attic/cprng_stub.c 2011/11/28 08:05:07 1.3
+++ src/sys/rump/librump/rumpkern/Attic/cprng_stub.c 2011/12/17 20:05:40 1.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: cprng_stub.c,v 1.3 2011/11/28 08:05:07 tls Exp $ */ | 1 | /* $NetBSD: cprng_stub.c,v 1.4 2011/12/17 20:05:40 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -49,52 +49,57 @@ | @@ -49,52 +49,57 @@ | |||
49 | * the pseudodevice. The other, by the fact that I am not smart enough | 49 | * the pseudodevice. The other, by the fact that I am not smart enough | |
50 | * to understand how to deal with code in rumpkern that depends on code | 50 | * to understand how to deal with code in rumpkern that depends on code | |
51 | * that lives in sys/crypto. Sigh. | 51 | * that lives in sys/crypto. Sigh. | |
52 | */ | 52 | */ | |
53 | 53 | |||
54 | cprng_strong_t *kern_cprng = NULL; | 54 | cprng_strong_t *kern_cprng = NULL; | |
55 | 55 | |||
56 | void | 56 | void | |
57 | cprng_init(void) | 57 | cprng_init(void) | |
58 | { | 58 | { | |
59 | return; | 59 | return; | |
60 | } | 60 | } | |
61 | 61 | |||
62 | cprng_strong_t *cprng_strong_create(const char *const name, int ipl, int flags) | 62 | cprng_strong_t * | |
63 | cprng_strong_create(const char *const name, int ipl, int flags) | |||
63 | { | 64 | { | |
64 | cprng_strong_t *c; | 65 | cprng_strong_t *c; | |
65 | 66 | |||
66 | c = kmem_alloc(sizeof(*c), KM_NOSLEEP); | 67 | /* zero struct to zero counters we won't ever set with no DRBG */ | |
68 | c = kmem_zalloc(sizeof(*c), KM_NOSLEEP); | |||
67 | if (c == NULL) { | 69 | if (c == NULL) { | |
68 | return NULL; | 70 | return NULL; | |
69 | } | 71 | } | |
70 | strlcpy(c->name, name, sizeof(c->name)); | 72 | strlcpy(c->name, name, sizeof(c->name)); | |
71 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | 73 | mutex_init(&c->mtx, MUTEX_DEFAULT, ipl); | |
72 | if (c->flags & CPRNG_USE_CV) { | 74 | if (c->flags & CPRNG_USE_CV) { | |
73 | cv_init(&c->cv, name); | 75 | cv_init(&c->cv, name); | |
74 | } | 76 | } | |
77 | selinit(&c->selq); | |||
75 | return c; | 78 | return c; | |
76 | } | 79 | } | |
77 | 80 | |||
78 | 81 | |||
79 | size_t cprng_strong(cprng_strong_t *c, void *p, size_t len) | 82 | size_t | |
83 | cprng_strong(cprng_strong_t *c, void *p, size_t len, int blocking) | |||
80 | { | 84 | { | |
81 | mutex_enter(&c->mtx); | 85 | mutex_enter(&c->mtx); | |
82 | cprng_fast(p, len); /* XXX! */ | 86 | cprng_fast(p, len); /* XXX! */ | |
83 | mutex_exit(&c->mtx); | 87 | mutex_exit(&c->mtx); | |
84 | return len; | 88 | return len; | |
85 | } | 89 | } | |
86 | 90 | |||
87 | void cprng_strong_destroy(cprng_strong_t *c) | 91 | void | |
92 | cprng_strong_destroy(cprng_strong_t *c) | |||
88 | { | 93 | { | |
89 | mutex_destroy(&c->mtx); | 94 | mutex_destroy(&c->mtx); | |
90 | cv_destroy(&c->cv); | 95 | cv_destroy(&c->cv); | |
91 | memset(c, 0, sizeof(*c)); | 96 | memset(c, 0, sizeof(*c)); | |
92 | kmem_free(c, sizeof(*c)); | 97 | kmem_free(c, sizeof(*c)); | |
93 | } | 98 | } | |
94 | 99 | |||
95 | size_t | 100 | size_t | |
96 | cprng_fast(void *p, size_t len) | 101 | cprng_fast(void *p, size_t len) | |
97 | { | 102 | { | |
98 | uint8_t *resp, *pchar = (uint8_t *)p; | 103 | uint8_t *resp, *pchar = (uint8_t *)p; | |
99 | uint32_t res; | 104 | uint32_t res; | |
100 | size_t i; | 105 | size_t i; |
--- src/sys/sys/cprng.h 2011/12/13 08:00:36 1.3
+++ src/sys/sys/cprng.h 2011/12/17 20:05:40 1.4
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: cprng.h,v 1.3 2011/12/13 08:00:36 mlelstv Exp $ */ | 1 | /* $NetBSD: cprng.h,v 1.4 2011/12/17 20:05:40 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 2011 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Thor Lancelot Simon. | 8 | * by Thor Lancelot Simon. | |
9 | * | 9 | * | |
10 | * Redistribution and use in source and binary forms, with or without | 10 | * Redistribution and use in source and binary forms, with or without | |
11 | * modification, are permitted provided that the following conditions | 11 | * modification, are permitted provided that the following conditions | |
12 | * are met: | 12 | * are met: | |
13 | * 1. Redistributions of source code must retain the above copyright | 13 | * 1. Redistributions of source code must retain the above copyright | |
14 | * notice, this list of conditions and the following disclaimer. | 14 | * notice, this list of conditions and the following disclaimer. | |
@@ -22,30 +22,32 @@ | @@ -22,30 +22,32 @@ | |||
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
29 | * POSSIBILITY OF SUCH DAMAGE. | 29 | * POSSIBILITY OF SUCH DAMAGE. | |
30 | */ | 30 | */ | |
31 | #ifndef _CPRNG_H | 31 | #ifndef _CPRNG_H | |
32 | #define _CPRNG_H | 32 | #define _CPRNG_H | |
33 | 33 | |||
34 | #include <sys/types.h> | 34 | #include <sys/types.h> | |
35 | #include <sys/fcntl.h> | |||
35 | #include <lib/libkern/libkern.h> | 36 | #include <lib/libkern/libkern.h> | |
36 | #include <sys/rnd.h> | 37 | #include <sys/rnd.h> | |
37 | #include <crypto/nist_ctr_drbg/nist_ctr_drbg.h> | 38 | #include <crypto/nist_ctr_drbg/nist_ctr_drbg.h> | |
38 | #include <sys/condvar.h> | 39 | #include <sys/condvar.h> | |
40 | #include <sys/select.h> | |||
39 | 41 | |||
40 | /* | 42 | /* | |
41 | * NIST SP800-90 says 2^19 bytes per request for the CTR_DRBG. | 43 | * NIST SP800-90 says 2^19 bytes per request for the CTR_DRBG. | |
42 | */ | 44 | */ | |
43 | #define CPRNG_MAX_LEN 524288 | 45 | #define CPRNG_MAX_LEN 524288 | |
44 | 46 | |||
45 | #if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI) | 47 | #if !defined(_RUMPKERNEL) && !defined(_RUMP_NATIVE_ABI) | |
46 | /* | 48 | /* | |
47 | * We do not want an arc4random() prototype available to anyone. | 49 | * We do not want an arc4random() prototype available to anyone. | |
48 | */ | 50 | */ | |
49 | void _arc4randbytes(void *, size_t); | 51 | void _arc4randbytes(void *, size_t); | |
50 | uint32_t _arc4random(void); | 52 | uint32_t _arc4random(void); | |
51 | 53 | |||
@@ -66,55 +68,84 @@ static inline uint64_t | @@ -66,55 +68,84 @@ static inline uint64_t | |||
66 | cprng_fast64(void) | 68 | cprng_fast64(void) | |
67 | { | 69 | { | |
68 | uint64_t r; | 70 | uint64_t r; | |
69 | _arc4randbytes(&r, sizeof(r)); | 71 | _arc4randbytes(&r, sizeof(r)); | |
70 | return r; | 72 | return r; | |
71 | } | 73 | } | |
72 | #else | 74 | #else | |
73 | size_t cprng_fast(void *, size_t); | 75 | size_t cprng_fast(void *, size_t); | |
74 | uint32_t cprng_fast32(void); | 76 | uint32_t cprng_fast32(void); | |
75 | uint64_t cprng_fast64(void); | 77 | uint64_t cprng_fast64(void); | |
76 | #endif | 78 | #endif | |
77 | 79 | |||
78 | typedef struct _cprng_strong { | 80 | typedef struct _cprng_strong { | |
79 | kmutex_t mtx; | 81 | kmutex_t mtx; | |
80 | kcondvar_t cv; | 82 | kcondvar_t cv; | |
81 | NIST_CTR_DRBG drbg; | 83 | struct selinfo selq; | |
82 | int flags; | 84 | NIST_CTR_DRBG drbg; | |
83 | char name[16]; | 85 | int flags; | |
84 | int reseed_pending; | 86 | char name[16]; | |
85 | rndsink_t reseed; | 87 | int reseed_pending; | |
88 | int rekeyed_on_full; | |||
89 | rndsink_t reseed; | |||
86 | } cprng_strong_t; | 90 | } cprng_strong_t; | |
87 | 91 | |||
88 | #define CPRNG_INIT_ANY 0x00000001 | 92 | #define CPRNG_INIT_ANY 0x00000001 | |
89 | #define CPRNG_REKEY_ANY 0x00000002 | 93 | #define CPRNG_REKEY_ANY 0x00000002 | |
90 | #define CPRNG_USE_CV 0x00000004 | 94 | #define CPRNG_USE_CV 0x00000004 | |
91 | 95 | |||
92 | cprng_strong_t *cprng_strong_create(const char *const, int, int); | 96 | cprng_strong_t *cprng_strong_create(const char *const, int, int); | |
93 | 97 | |||
94 | size_t cprng_strong(cprng_strong_t *const, void *const, size_t); | 98 | size_t cprng_strong(cprng_strong_t *const, void *const, size_t, int); | |
95 | 99 | |||
96 | void cprng_strong_destroy(cprng_strong_t *); | 100 | void cprng_strong_destroy(cprng_strong_t *); | |
97 | 101 | |||
98 | extern cprng_strong_t * kern_cprng; | 102 | extern cprng_strong_t * kern_cprng; | |
99 | 103 | |||
100 | static inline uint32_t | 104 | static inline uint32_t | |
101 | cprng_strong32(void) | 105 | cprng_strong32(void) | |
102 | { | 106 | { | |
103 | uint32_t r; | 107 | uint32_t r; | |
104 | cprng_strong(kern_cprng, &r, sizeof(r)); | 108 | cprng_strong(kern_cprng, &r, sizeof(r), 0); | |
105 | return r; | 109 | return r; | |
106 | } | 110 | } | |
107 | 111 | |||
108 | static inline uint64_t | 112 | static inline uint64_t | |
109 | cprng_strong64(void) | 113 | cprng_strong64(void) | |
110 | { | 114 | { | |
111 | uint64_t r; | 115 | uint64_t r; | |
112 | cprng_strong(kern_cprng, &r, sizeof(r)); | 116 | cprng_strong(kern_cprng, &r, sizeof(r), 0); | |
113 | return r; | 117 | return r; | |
114 | } | 118 | } | |
115 | 119 | |||
120 | static inline int | |||
121 | cprng_strong_ready(cprng_strong_t *c) | |||
122 | { | |||
123 | int ret = 0; | |||
124 | ||||
125 | mutex_enter(&c->mtx); | |||
126 | if (c->drbg.reseed_counter < NIST_CTR_DRBG_RESEED_INTERVAL) { | |||
127 | ret = 1; | |||
128 | } | |||
129 | mutex_exit(&c->mtx); | |||
130 | return ret; | |||
131 | } | |||
132 | ||||
133 | static inline void | |||
134 | cprng_strong_deplete(cprng_strong_t *c) | |||
135 | { | |||
136 | mutex_enter(&c->mtx); | |||
137 | c->drbg.reseed_counter = NIST_CTR_DRBG_RESEED_INTERVAL + 1; | |||
138 | mutex_exit(&c->mtx); | |||
139 | } | |||
140 | ||||
141 | static inline int | |||
142 | cprng_strong_strength(cprng_strong_t *c) | |||
143 | { | |||
144 | return NIST_BLOCK_KEYLEN_BYTES; | |||
145 | } | |||
146 | ||||
116 | void cprng_init(void); | 147 | void cprng_init(void); | |
117 | int cprng_strong_getflags(cprng_strong_t *const); | 148 | int cprng_strong_getflags(cprng_strong_t *const); | |
118 | void cprng_strong_setflags(cprng_strong_t *const, int); | 149 | void cprng_strong_setflags(cprng_strong_t *const, int); | |
119 | 150 | |||
120 | #endif | 151 | #endif |
--- src/sys/sys/param.h 2011/11/28 08:05:07 1.397
+++ src/sys/sys/param.h 2011/12/17 20:05:40 1.398
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: param.h,v 1.397 2011/11/28 08:05:07 tls Exp $ */ | 1 | /* $NetBSD: param.h,v 1.398 2011/12/17 20:05:40 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1982, 1986, 1989, 1993 | 4 | * Copyright (c) 1982, 1986, 1989, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * (c) UNIX System Laboratories, Inc. | 6 | * (c) UNIX System Laboratories, Inc. | |
7 | * All or some portions of this file are derived from material licensed | 7 | * All or some portions of this file are derived from material licensed | |
8 | * to the University of California by American Telephone and Telegraph | 8 | * to the University of California by American Telephone and Telegraph | |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
10 | * the permission of UNIX System Laboratories, Inc. | 10 | * the permission of UNIX System Laboratories, Inc. | |
11 | * | 11 | * | |
12 | * Redistribution and use in source and binary forms, with or without | 12 | * Redistribution and use in source and binary forms, with or without | |
13 | * modification, are permitted provided that the following conditions | 13 | * modification, are permitted provided that the following conditions | |
14 | * are met: | 14 | * are met: | |
@@ -53,27 +53,27 @@ | @@ -53,27 +53,27 @@ | |||
53 | * m = minor version; a minor number of 99 indicates current. | 53 | * m = minor version; a minor number of 99 indicates current. | |
54 | * r = 0 (*) | 54 | * r = 0 (*) | |
55 | * p = patchlevel | 55 | * p = patchlevel | |
56 | * | 56 | * | |
57 | * When new releases are made, src/gnu/usr.bin/groff/tmac/mdoc.local | 57 | * When new releases are made, src/gnu/usr.bin/groff/tmac/mdoc.local | |
58 | * needs to be updated and the changes sent back to the groff maintainers. | 58 | * needs to be updated and the changes sent back to the groff maintainers. | |
59 | * | 59 | * | |
60 | * (*) Up to 2.0I "release" used to be "",A-Z,Z[A-Z] but numeric | 60 | * (*) Up to 2.0I "release" used to be "",A-Z,Z[A-Z] but numeric | |
61 | * e.g. NetBSD-1.2D = 102040000 ('D' == 4) | 61 | * e.g. NetBSD-1.2D = 102040000 ('D' == 4) | |
62 | * NetBSD-2.0H (200080000) was changed on 20041001 to: | 62 | * NetBSD-2.0H (200080000) was changed on 20041001 to: | |
63 | * 2.99.9 (299000900) | 63 | * 2.99.9 (299000900) | |
64 | */ | 64 | */ | |
65 | 65 | |||
66 | #define __NetBSD_Version__ 599005800 /* NetBSD 5.99.58 */ | 66 | #define __NetBSD_Version__ 599005900 /* NetBSD 5.99.59 */ | |
67 | 67 | |||
68 | #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ | 68 | #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ | |
69 | (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) | 69 | (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) | |
70 | 70 | |||
71 | /* | 71 | /* | |
72 | * Historical NetBSD #define | 72 | * Historical NetBSD #define | |
73 | * | 73 | * | |
74 | * NetBSD 1.4 was the last release for which this value was incremented. | 74 | * NetBSD 1.4 was the last release for which this value was incremented. | |
75 | * The value is now permanently fixed at 199905. It will never be | 75 | * The value is now permanently fixed at 199905. It will never be | |
76 | * changed again. | 76 | * changed again. | |
77 | * | 77 | * | |
78 | * New code must use __NetBSD_Version__ instead, and should not even | 78 | * New code must use __NetBSD_Version__ instead, and should not even | |
79 | * count on NetBSD being defined. | 79 | * count on NetBSD being defined. |
--- src/sys/sys/rnd.h 2011/12/17 12:59:21 1.27
+++ src/sys/sys/rnd.h 2011/12/17 20:05:40 1.28
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: rnd.h,v 1.27 2011/12/17 12:59:21 apb Exp $ */ | 1 | /* $NetBSD: rnd.h,v 1.28 2011/12/17 20:05:40 tls Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | 4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * This code is derived from software contributed to The NetBSD Foundation | 7 | * This code is derived from software contributed to The NetBSD Foundation | |
8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | 8 | * by Michael Graff <explorer@flame.org>. This code uses ideas and | |
9 | * algorithms from the Linux driver written by Ted Ts'o. | 9 | * algorithms from the Linux driver written by Ted Ts'o. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -155,26 +155,28 @@ uint32_t rndpool_extract_data(rndpool_t | @@ -155,26 +155,28 @@ uint32_t rndpool_extract_data(rndpool_t | |||
155 | void rnd_init(void); | 155 | void rnd_init(void); | |
156 | void rnd_add_uint32(krndsource_t *, uint32_t); | 156 | void rnd_add_uint32(krndsource_t *, uint32_t); | |
157 | void rnd_add_data(krndsource_t *, const void *const, uint32_t, | 157 | void rnd_add_data(krndsource_t *, const void *const, uint32_t, | |
158 | uint32_t); | 158 | uint32_t); | |
159 | void rnd_attach_source(krndsource_t *, const char *, | 159 | void rnd_attach_source(krndsource_t *, const char *, | |
160 | uint32_t, uint32_t); | 160 | uint32_t, uint32_t); | |
161 | void rnd_detach_source(krndsource_t *); | 161 | void rnd_detach_source(krndsource_t *); | |
162 | 162 | |||
163 | void rndsink_attach(rndsink_t *); | 163 | void rndsink_attach(rndsink_t *); | |
164 | void rndsink_detach(rndsink_t *); | 164 | void rndsink_detach(rndsink_t *); | |
165 | 165 | |||
166 | void rnd_seed(void *, size_t); | 166 | void rnd_seed(void *, size_t); | |
167 | 167 | |||
168 | extern int rnd_full; | |||
169 | ||||
168 | #endif /* _KERNEL */ | 170 | #endif /* _KERNEL */ | |
169 | 171 | |||
170 | #define RND_MAXSTATCOUNT 10 /* 10 sources at once max */ | 172 | #define RND_MAXSTATCOUNT 10 /* 10 sources at once max */ | |
171 | 173 | |||
172 | /* | 174 | /* | |
173 | * return "count" random entries, starting at "start" | 175 | * return "count" random entries, starting at "start" | |
174 | */ | 176 | */ | |
175 | typedef struct { | 177 | typedef struct { | |
176 | uint32_t start; | 178 | uint32_t start; | |
177 | uint32_t count; | 179 | uint32_t count; | |
178 | rndsource_t source[RND_MAXSTATCOUNT]; | 180 | rndsource_t source[RND_MAXSTATCOUNT]; | |
179 | } rndstat_t; | 181 | } rndstat_t; | |
180 | 182 |