diff options
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r-- | drivers/char/random.c | 67 |
1 files changed, 38 insertions, 29 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c index 46c1b97748b6..0474cac4a84e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -760,7 +760,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
760 | 760 | ||
761 | static void extract_buf(struct entropy_store *r, __u8 *out) | 761 | static void extract_buf(struct entropy_store *r, __u8 *out) |
762 | { | 762 | { |
763 | int i, x; | 763 | int i; |
764 | __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS]; | 764 | __u32 data[16], buf[5 + SHA_WORKSPACE_WORDS]; |
765 | 765 | ||
766 | sha_init(buf); | 766 | sha_init(buf); |
@@ -772,9 +772,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
772 | * attempts to find previous ouputs), unless the hash | 772 | * attempts to find previous ouputs), unless the hash |
773 | * function can be inverted. | 773 | * function can be inverted. |
774 | */ | 774 | */ |
775 | for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) { | 775 | for (i = 0; i < r->poolinfo->poolwords; i += 16) { |
776 | sha_transform(buf, (__u8 *)r->pool+i, buf + 5); | 776 | /* hash blocks of 16 words = 512 bits */ |
777 | add_entropy_words(r, &buf[x % 5], 1); | 777 | sha_transform(buf, (__u8 *)(r->pool + i), buf + 5); |
778 | /* feed back portion of the resulting hash */ | ||
779 | add_entropy_words(r, &buf[i % 5], 1); | ||
778 | } | 780 | } |
779 | 781 | ||
780 | /* | 782 | /* |
@@ -782,7 +784,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
782 | * portion of the pool while mixing, and hash one | 784 | * portion of the pool while mixing, and hash one |
783 | * final time. | 785 | * final time. |
784 | */ | 786 | */ |
785 | __add_entropy_words(r, &buf[x % 5], 1, data); | 787 | __add_entropy_words(r, &buf[i % 5], 1, data); |
786 | sha_transform(buf, (__u8 *)data, buf + 5); | 788 | sha_transform(buf, (__u8 *)data, buf + 5); |
787 | 789 | ||
788 | /* | 790 | /* |
@@ -1018,37 +1020,44 @@ random_poll(struct file *file, poll_table * wait) | |||
1018 | return mask; | 1020 | return mask; |
1019 | } | 1021 | } |
1020 | 1022 | ||
1021 | static ssize_t | 1023 | static int |
1022 | random_write(struct file * file, const char __user * buffer, | 1024 | write_pool(struct entropy_store *r, const char __user *buffer, size_t count) |
1023 | size_t count, loff_t *ppos) | ||
1024 | { | 1025 | { |
1025 | int ret = 0; | ||
1026 | size_t bytes; | 1026 | size_t bytes; |
1027 | __u32 buf[16]; | 1027 | __u32 buf[16]; |
1028 | const char __user *p = buffer; | 1028 | const char __user *p = buffer; |
1029 | size_t c = count; | ||
1030 | 1029 | ||
1031 | while (c > 0) { | 1030 | while (count > 0) { |
1032 | bytes = min(c, sizeof(buf)); | 1031 | bytes = min(count, sizeof(buf)); |
1032 | if (copy_from_user(&buf, p, bytes)) | ||
1033 | return -EFAULT; | ||
1033 | 1034 | ||
1034 | bytes -= copy_from_user(&buf, p, bytes); | 1035 | count -= bytes; |
1035 | if (!bytes) { | ||
1036 | ret = -EFAULT; | ||
1037 | break; | ||
1038 | } | ||
1039 | c -= bytes; | ||
1040 | p += bytes; | 1036 | p += bytes; |
1041 | 1037 | ||
1042 | add_entropy_words(&input_pool, buf, (bytes + 3) / 4); | 1038 | add_entropy_words(r, buf, (bytes + 3) / 4); |
1043 | } | ||
1044 | if (p == buffer) { | ||
1045 | return (ssize_t)ret; | ||
1046 | } else { | ||
1047 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1048 | inode->i_mtime = current_fs_time(inode->i_sb); | ||
1049 | mark_inode_dirty(inode); | ||
1050 | return (ssize_t)(p - buffer); | ||
1051 | } | 1039 | } |
1040 | |||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | static ssize_t | ||
1045 | random_write(struct file * file, const char __user * buffer, | ||
1046 | size_t count, loff_t *ppos) | ||
1047 | { | ||
1048 | size_t ret; | ||
1049 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1050 | |||
1051 | ret = write_pool(&blocking_pool, buffer, count); | ||
1052 | if (ret) | ||
1053 | return ret; | ||
1054 | ret = write_pool(&nonblocking_pool, buffer, count); | ||
1055 | if (ret) | ||
1056 | return ret; | ||
1057 | |||
1058 | inode->i_mtime = current_fs_time(inode->i_sb); | ||
1059 | mark_inode_dirty(inode); | ||
1060 | return (ssize_t)count; | ||
1052 | } | 1061 | } |
1053 | 1062 | ||
1054 | static int | 1063 | static int |
@@ -1087,8 +1096,8 @@ random_ioctl(struct inode * inode, struct file * file, | |||
1087 | return -EINVAL; | 1096 | return -EINVAL; |
1088 | if (get_user(size, p++)) | 1097 | if (get_user(size, p++)) |
1089 | return -EFAULT; | 1098 | return -EFAULT; |
1090 | retval = random_write(file, (const char __user *) p, | 1099 | retval = write_pool(&input_pool, (const char __user *)p, |
1091 | size, &file->f_pos); | 1100 | size); |
1092 | if (retval < 0) | 1101 | if (retval < 0) |
1093 | return retval; | 1102 | return retval; |
1094 | credit_entropy_store(&input_pool, ent_count); | 1103 | credit_entropy_store(&input_pool, ent_count); |