diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/char/random.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index b86eae9b77df..85e81ec1451e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -399,7 +399,6 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); | |||
| 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); | 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); |
| 400 | static struct fasync_struct *fasync; | 400 | static struct fasync_struct *fasync; |
| 401 | 401 | ||
| 402 | #if 0 | ||
| 403 | static bool debug; | 402 | static bool debug; |
| 404 | module_param(debug, bool, 0644); | 403 | module_param(debug, bool, 0644); |
| 405 | #define DEBUG_ENT(fmt, arg...) do { \ | 404 | #define DEBUG_ENT(fmt, arg...) do { \ |
| @@ -410,9 +409,6 @@ module_param(debug, bool, 0644); | |||
| 410 | blocking_pool.entropy_count,\ | 409 | blocking_pool.entropy_count,\ |
| 411 | nonblocking_pool.entropy_count,\ | 410 | nonblocking_pool.entropy_count,\ |
| 412 | ## arg); } while (0) | 411 | ## arg); } while (0) |
| 413 | #else | ||
| 414 | #define DEBUG_ENT(fmt, arg...) do {} while (0) | ||
| 415 | #endif | ||
| 416 | 412 | ||
| 417 | /********************************************************************** | 413 | /********************************************************************** |
| 418 | * | 414 | * |
| @@ -437,6 +433,7 @@ struct entropy_store { | |||
| 437 | int entropy_count; | 433 | int entropy_count; |
| 438 | int entropy_total; | 434 | int entropy_total; |
| 439 | unsigned int initialized:1; | 435 | unsigned int initialized:1; |
| 436 | bool last_data_init; | ||
| 440 | __u8 last_data[EXTRACT_SIZE]; | 437 | __u8 last_data[EXTRACT_SIZE]; |
| 441 | }; | 438 | }; |
| 442 | 439 | ||
| @@ -829,7 +826,7 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | |||
| 829 | bytes = min_t(int, bytes, sizeof(tmp)); | 826 | bytes = min_t(int, bytes, sizeof(tmp)); |
| 830 | 827 | ||
| 831 | DEBUG_ENT("going to reseed %s with %d bits " | 828 | DEBUG_ENT("going to reseed %s with %d bits " |
| 832 | "(%d of %d requested)\n", | 829 | "(%zu of %d requested)\n", |
| 833 | r->name, bytes * 8, nbytes * 8, r->entropy_count); | 830 | r->name, bytes * 8, nbytes * 8, r->entropy_count); |
| 834 | 831 | ||
| 835 | bytes = extract_entropy(r->pull, tmp, bytes, | 832 | bytes = extract_entropy(r->pull, tmp, bytes, |
| @@ -860,7 +857,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 860 | spin_lock_irqsave(&r->lock, flags); | 857 | spin_lock_irqsave(&r->lock, flags); |
| 861 | 858 | ||
| 862 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); | 859 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); |
| 863 | DEBUG_ENT("trying to extract %d bits from %s\n", | 860 | DEBUG_ENT("trying to extract %zu bits from %s\n", |
| 864 | nbytes * 8, r->name); | 861 | nbytes * 8, r->name); |
| 865 | 862 | ||
| 866 | /* Can we pull enough? */ | 863 | /* Can we pull enough? */ |
| @@ -882,7 +879,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 882 | } | 879 | } |
| 883 | } | 880 | } |
| 884 | 881 | ||
| 885 | DEBUG_ENT("debiting %d entropy credits from %s%s\n", | 882 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", |
| 886 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); | 883 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); |
| 887 | 884 | ||
| 888 | spin_unlock_irqrestore(&r->lock, flags); | 885 | spin_unlock_irqrestore(&r->lock, flags); |
| @@ -957,6 +954,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 957 | ssize_t ret = 0, i; | 954 | ssize_t ret = 0, i; |
| 958 | __u8 tmp[EXTRACT_SIZE]; | 955 | __u8 tmp[EXTRACT_SIZE]; |
| 959 | 956 | ||
| 957 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | ||
| 958 | if (fips_enabled && !r->last_data_init) | ||
| 959 | nbytes += EXTRACT_SIZE; | ||
| 960 | |||
| 960 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | 961 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); |
| 961 | xfer_secondary_pool(r, nbytes); | 962 | xfer_secondary_pool(r, nbytes); |
| 962 | nbytes = account(r, nbytes, min, reserved); | 963 | nbytes = account(r, nbytes, min, reserved); |
| @@ -967,6 +968,17 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 967 | if (fips_enabled) { | 968 | if (fips_enabled) { |
| 968 | unsigned long flags; | 969 | unsigned long flags; |
| 969 | 970 | ||
| 971 | |||
| 972 | /* prime last_data value if need be, per fips 140-2 */ | ||
| 973 | if (!r->last_data_init) { | ||
| 974 | spin_lock_irqsave(&r->lock, flags); | ||
| 975 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
| 976 | r->last_data_init = true; | ||
| 977 | nbytes -= EXTRACT_SIZE; | ||
| 978 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 979 | extract_buf(r, tmp); | ||
| 980 | } | ||
| 981 | |||
| 970 | spin_lock_irqsave(&r->lock, flags); | 982 | spin_lock_irqsave(&r->lock, flags); |
| 971 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 983 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
| 972 | panic("Hardware RNG duplicated output!\n"); | 984 | panic("Hardware RNG duplicated output!\n"); |
| @@ -1086,6 +1098,7 @@ static void init_std_data(struct entropy_store *r) | |||
| 1086 | 1098 | ||
| 1087 | r->entropy_count = 0; | 1099 | r->entropy_count = 0; |
| 1088 | r->entropy_total = 0; | 1100 | r->entropy_total = 0; |
| 1101 | r->last_data_init = false; | ||
| 1089 | mix_pool_bytes(r, &now, sizeof(now), NULL); | 1102 | mix_pool_bytes(r, &now, sizeof(now), NULL); |
| 1090 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { | 1103 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { |
| 1091 | if (!arch_get_random_long(&rv)) | 1104 | if (!arch_get_random_long(&rv)) |
| @@ -1142,11 +1155,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1142 | if (n > SEC_XFER_SIZE) | 1155 | if (n > SEC_XFER_SIZE) |
| 1143 | n = SEC_XFER_SIZE; | 1156 | n = SEC_XFER_SIZE; |
| 1144 | 1157 | ||
| 1145 | DEBUG_ENT("reading %d bits\n", n*8); | 1158 | DEBUG_ENT("reading %zu bits\n", n*8); |
| 1146 | 1159 | ||
| 1147 | n = extract_entropy_user(&blocking_pool, buf, n); | 1160 | n = extract_entropy_user(&blocking_pool, buf, n); |
| 1148 | 1161 | ||
| 1149 | DEBUG_ENT("read got %d bits (%d still needed)\n", | 1162 | if (n < 0) { |
| 1163 | retval = n; | ||
| 1164 | break; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | DEBUG_ENT("read got %zd bits (%zd still needed)\n", | ||
| 1150 | n*8, (nbytes-n)*8); | 1168 | n*8, (nbytes-n)*8); |
| 1151 | 1169 | ||
| 1152 | if (n == 0) { | 1170 | if (n == 0) { |
| @@ -1171,10 +1189,6 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1171 | continue; | 1189 | continue; |
| 1172 | } | 1190 | } |
| 1173 | 1191 | ||
| 1174 | if (n < 0) { | ||
| 1175 | retval = n; | ||
| 1176 | break; | ||
| 1177 | } | ||
| 1178 | count += n; | 1192 | count += n; |
| 1179 | buf += n; | 1193 | buf += n; |
| 1180 | nbytes -= n; | 1194 | nbytes -= n; |
