diff options
author | Theodore Ts'o <tytso@mit.edu> | 2018-04-11 16:32:17 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2018-04-14 11:59:31 -0400 |
commit | d848e5f8e1ebdb227d045db55fe4f825e82965fa (patch) | |
tree | 7661e5f63b463d3fb22da99aef52bf1e00d814f4 | |
parent | 0bb29a849a6433b72e249eea7695477b02056e94 (diff) |
random: add new ioctl RNDRESEEDCRNG
Add a new ioctl which forces the the crng to be reseeded.
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org
-rw-r--r-- | drivers/char/random.c | 13 | ||||
-rw-r--r-- | include/uapi/linux/random.h | 3 |
2 files changed, 15 insertions, 1 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 898233f594b4..3cd3aae24d6d 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -429,6 +429,7 @@ struct crng_state primary_crng = { | |||
429 | static int crng_init = 0; | 429 | static int crng_init = 0; |
430 | #define crng_ready() (likely(crng_init > 1)) | 430 | #define crng_ready() (likely(crng_init > 1)) |
431 | static int crng_init_cnt = 0; | 431 | static int crng_init_cnt = 0; |
432 | static unsigned long crng_global_init_time = 0; | ||
432 | #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) | 433 | #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) |
433 | static void _extract_crng(struct crng_state *crng, | 434 | static void _extract_crng(struct crng_state *crng, |
434 | __u32 out[CHACHA20_BLOCK_WORDS]); | 435 | __u32 out[CHACHA20_BLOCK_WORDS]); |
@@ -933,7 +934,8 @@ static void _extract_crng(struct crng_state *crng, | |||
933 | unsigned long v, flags; | 934 | unsigned long v, flags; |
934 | 935 | ||
935 | if (crng_ready() && | 936 | if (crng_ready() && |
936 | time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) | 937 | (time_after(crng_global_init_time, crng->init_time) || |
938 | time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))) | ||
937 | crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); | 939 | crng_reseed(crng, crng == &primary_crng ? &input_pool : NULL); |
938 | spin_lock_irqsave(&crng->lock, flags); | 940 | spin_lock_irqsave(&crng->lock, flags); |
939 | if (arch_get_random_long(&v)) | 941 | if (arch_get_random_long(&v)) |
@@ -1757,6 +1759,7 @@ static int rand_initialize(void) | |||
1757 | init_std_data(&input_pool); | 1759 | init_std_data(&input_pool); |
1758 | init_std_data(&blocking_pool); | 1760 | init_std_data(&blocking_pool); |
1759 | crng_initialize(&primary_crng); | 1761 | crng_initialize(&primary_crng); |
1762 | crng_global_init_time = jiffies; | ||
1760 | return 0; | 1763 | return 0; |
1761 | } | 1764 | } |
1762 | early_initcall(rand_initialize); | 1765 | early_initcall(rand_initialize); |
@@ -1930,6 +1933,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
1930 | input_pool.entropy_count = 0; | 1933 | input_pool.entropy_count = 0; |
1931 | blocking_pool.entropy_count = 0; | 1934 | blocking_pool.entropy_count = 0; |
1932 | return 0; | 1935 | return 0; |
1936 | case RNDRESEEDCRNG: | ||
1937 | if (!capable(CAP_SYS_ADMIN)) | ||
1938 | return -EPERM; | ||
1939 | if (crng_init < 2) | ||
1940 | return -ENODATA; | ||
1941 | crng_reseed(&primary_crng, NULL); | ||
1942 | crng_global_init_time = jiffies - 1; | ||
1943 | return 0; | ||
1933 | default: | 1944 | default: |
1934 | return -EINVAL; | 1945 | return -EINVAL; |
1935 | } | 1946 | } |
diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h index c34f4490d025..26ee91300e3e 100644 --- a/include/uapi/linux/random.h +++ b/include/uapi/linux/random.h | |||
@@ -35,6 +35,9 @@ | |||
35 | /* Clear the entropy pool and associated counters. (Superuser only.) */ | 35 | /* Clear the entropy pool and associated counters. (Superuser only.) */ |
36 | #define RNDCLEARPOOL _IO( 'R', 0x06 ) | 36 | #define RNDCLEARPOOL _IO( 'R', 0x06 ) |
37 | 37 | ||
38 | /* Reseed CRNG. (Superuser only.) */ | ||
39 | #define RNDRESEEDCRNG _IO( 'R', 0x07 ) | ||
40 | |||
38 | struct rand_pool_info { | 41 | struct rand_pool_info { |
39 | int entropy_count; | 42 | int entropy_count; |
40 | int buf_size; | 43 | int buf_size; |