aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/random.c')
-rw-r--r--drivers/char/random.c67
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
761static void extract_buf(struct entropy_store *r, __u8 *out) 761static 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
1021static ssize_t 1023static int
1022random_write(struct file * file, const char __user * buffer, 1024write_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
1044static ssize_t
1045random_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
1054static int 1063static 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);