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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux