Re: [PATCH] API for true Random Number Generators to add entropy (2.6.11)

Evgeniy Polyakov
2005-03-25T05:47:59Z

[-- Attachment #1: Type: text/plain, Size: 8304 bytes --]

On Thu, 2005-03-24 at 14:59 +0300, Evgeniy Polyakov wrote:

> For example here is patch to enable acrypto support for hw_random.c
> It is very simple and support only upto 4 bytes request, of course it
> is not interested for anyone, but it is only 2-minutes example:

Full port.

--- ./drivers/char/hw_random.c.orig 2005-03-24 13:36:05.000000000 +0300
+++ ./drivers/char/hw_random.c 2005-03-25 08:46:03.841601032 +0300
@@ -34,6 +34,10 @@
#include <linux/smp_lock.h>
#include <linux/mm.h>
#include <linux/delay.h>
+#include <linux/acrypto.h>
+#include <linux/crypto_def.h>
+#include <linux/crypto_stat.h>
+#include <linux/highmem.h>

#ifdef __i386__
#include <asm/msr.h>
@@ -73,6 +77,8 @@
#endif

#define RNG_MISCDEV_MINOR 183 /* official */
+
+static DEFINE_SPINLOCK(rng_lock);

static int rng_dev_open (struct inode *inode, struct file *filp);
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
@@ -482,7 +488,6 @@
static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
loff_t * offp)
{
- static DEFINE_SPINLOCK(rng_lock);
unsigned int have_data;
u32 data = 0;
ssize_t ret = 0;
@@ -526,7 +531,163 @@
return ret;
}

+#ifdef CONFIG_ACRYPTO
+static struct crypto_device *hwr_cdev;
+static struct crypto_capability hwr_caps[] = {
+ {CRYPTO_OP_RNG, 0, 0, 100},
+};
+static int hwr_pid, hwr_need_exit;
+static struct completion hwr_thread_exited;
+static DECLARE_WAIT_QUEUE_HEAD(hwr_wait);
+
+
+static void hwr_data_ready(struct crypto_device *dev)
+{
+ wake_up(&hwr_wait);
+}
+
+static int hwr_process(void *data)
+{
+ struct crypto_device *dev = data;
+ struct crypto_session *s, *n;
+ u32 rng_data = 0;
+ unsigned int have_data, size;
+ int i;
+ u8 *ptr;
+
+ daemonize("%s", dev->name);
+ allow_signal(SIGTERM);
+
+ while (!hwr_need_exit) {
+ interruptible_sleep_on_timeout(&hwr_wait, 10);
+
+ list_for_each_entry_safe(s, n, &dev->session_list, dev_queue_entry) {
+ if (!session_completed(s) && !session_is_processed(s)) {
+ start_process_session(s);
+
+ if (s->data.sg_src_num != s->data.sg_dst_num) {
+ dprintk("%s: session %llu [%llu]: different src/dst sg numbers: %d %d.\n",
+ dev->name, s->ci.id, s->ci.dev_id,
+ s->data.sg_src_num, s->data.sg_dst_num);
+ broke_session(s);
+ goto out_complete_session;
+ }
+
+ for (i=0; i<s->data.sg_src_num; ++i) {
+ if (s->data.sg_dst[i].length != s->data.sg_src[i].length) {
+ dprintk("%s: session %llu [%llu]: sg %d different src/dst lengths: %u %u.\n",
+ dev->name, s->ci.id, s->ci.dev_id, i,
+ s->data.sg_src[i].length, s->data.sg_dst[i].length);
+ if (s->data.sg_dst[i].length)
+ s->data.sg_src[i].length = s->data.sg_dst[i].length;
+ else
+ s->data.sg_dst[i].length = s->data.sg_src[i].length;
+
+ }
+
+ size = s->data.sg_dst[i].length;
+
+ while (size) {
+ spin_lock(&rng_lock);
+ have_data = 0;
+ if (rng_ops->data_present()) {
+ rng_data = rng_ops->data_read();
+ have_data = rng_ops->n_bytes;
+ }
+ spin_unlock (&rng_lock);
+
+ ptr = kmap_atomic(s->data.sg_dst[i].page, KM_USER0) + s->data.sg_dst[i].offset +
+ s->data.sg_dst[i].length - size;
+
+ while (size && have_data) {
+ *ptr = rng_data & 0xff;
+ size--;
+ have_data--;
+ rng_data >>= 8;
+ }
+ kunmap_atomic(ptr, KM_USER0);
+
+ if (size)
+ msleep_interruptible(1);
+ }
+ }
+
+ crypto_stat_complete_inc(s);
+
+out_complete_session:
+ crypto_session_dequeue_route(s);
+ complete_session(s);
+ stop_process_session(s);
+ }
+ }
+ }
+
+ complete_and_exit(&hwr_thread_exited, 0);
+}
+
+static int hwr_acrypto_init(struct rng_operations *ops)
+{
+ int err;
+
+ hwr_cdev = kmalloc(sizeof(*hwr_cdev), GFP_KERNEL);
+ if (!hwr_cdev) {
+ printk(KERN_ERR "Failed to allocate new crypto_device structure.\n");
+ return -ENOMEM;
+ }
+
+ memset(hwr_cdev, 0, sizeof(*hwr_cdev));
+
+ hwr_cdev->cap = hwr_caps;
+ hwr_cdev->cap_number = sizeof(hwr_caps)/sizeof(hwr_caps[0]);
+ hwr_cdev->priv = ops;
+ hwr_cdev->data_ready = &hwr_data_ready;
+ snprintf(hwr_cdev->name, sizeof(hwr_cdev->name), "%s", "hwr");
+
+ init_completion(&hwr_thread_exited);
+ hwr_pid = kernel_thread(hwr_process, hwr_cdev, CLONE_FS | CLONE_FILES);
+ if (hwr_pid < 0) {
+ err = hwr_pid;
+ goto err_out_free_cdev;
+ }

+ err = crypto_device_add(hwr_cdev);
+ if (err)
+ goto err_out_remove_thread;
+
+ printk(KERN_INFO "%s acrypto support is turned on.\n", hwr_cdev->name);
+
+err_out_remove_thread:
+ hwr_need_exit = 1;
+ kill_proc(hwr_pid, SIGTERM, 0);
+ wait_for_completion(&hwr_thread_exited);
+err_out_free_cdev:
+ kfree(hwr_cdev);
+ hwr_cdev = NULL;
+ return err;
+}
+
+static void hwr_acrypto_fini(void)
+{
+ crypto_device_remove(hwr_cdev);
+ printk(KERN_INFO "%s acrypto support is turned off.\n", hwr_cdev->name);
+
+ hwr_need_exit = 1;
+ kill_proc(hwr_pid, SIGTERM, 0);
+ wait_for_completion(&hwr_thread_exited);
+
+ kfree(hwr_cdev);
+ hwr_cdev = NULL;
+}
+#else
+static int hwr_acrypto_init(struct rng_operations *ops)
+{
+ return 0;
+}
+
+static void hwr_acrypto_fini(void)
+{
+}
+#endif

/*
* rng_init_one - look for and attempt to init a single RNG
@@ -549,9 +710,15 @@
goto err_out_cleanup_hw;
}

+ rc = hwr_acrypto_init(rng_ops);
+ if (rc)
+ goto err_out_misc_unregister;
+
DPRINTK ("EXIT, returning 0\n");
return 0;

+err_out_misc_unregister:
+ misc_deregister(&rng_miscdev);
err_out_cleanup_hw:
rng_ops->cleanup();
err_out:
@@ -617,6 +784,8 @@
{
DPRINTK ("ENTER\n");

+ hwr_acrypto_fini();
+
misc_deregister (&rng_miscdev);

if (rng_ops->cleanup)

--
Evgeniy Polyakov

Crash is better than data corruption -- Arthur Grabowski

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]