* [PATCH 0/2] Add in-kernel /dev/random equivalent
@ 2014-05-11 22:36 Stephan Mueller
2014-05-11 22:37 ` [PATCH 1/2] Addition of kernel_pool Stephan Mueller
2014-06-06 11:59 ` [PATCH 0/2] Add in-kernel /dev/random equivalent Pavel Machek
0 siblings, 2 replies; 5+ messages in thread
From: Stephan Mueller @ 2014-05-11 22:36 UTC (permalink / raw)
To: Theodore Ts'o, LKML, linux-crypto
[-- Attachment #1: Type: text/plain, Size: 955 bytes --]
Hi,
as discussed in thread [1], an in-kernel equivalent to the blocking
/dev/random device behavior is suggested. This in-kernel blocking access to
the RNG can be used to seed deterministic random number generators with random
numbers that are directly backed by the underlying noise sources.
The following patch implements this concept by adding a third output pool, the
kernel_pool that is only accessible inside the kernel. That kernel_pool feeds
the blocking operation API calls to obtain random numbers.
Please find a test kernel module attached. You can unload it even while the
collection process is ongoing.
[1] https://lkml.org/lkml/2014/4/27/174
Stephan Mueller (2):
Addition of kernel_pool
Asynchronous and syncronous API for accessing kernel_pool
drivers/char/random.c | 163
+++++++++++++++++++++++++++++++++++++++++++++----
include/linux/random.h | 16 +++++
2 files changed, 166 insertions(+), 13 deletions(-)
--
1.9.0
[-- Attachment #2: lrng-asym.c --]
[-- Type: text/x-csrc, Size: 4102 bytes --]
/* Test module for verifying the correct operation of the
* SP800-90A DRBG
*
* Use: compile, load into the kernel and observe dmesg
*
* Written by: Stephan Mueller <smueller@chronox.de>
* Copyright (c) 2014
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* NO WARRANTY
*
* BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
* FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
* OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
* PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
* OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
* TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
* PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
* REPAIR OR CORRECTION.
*
* IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
* WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
* REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
* INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
* OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
* TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
* YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
* PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <linux/random.h>
#include <linux/module.h>
#include <linux/slab.h> /* needed for kzalloc */
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("Test module for verifying the correct operation of async LRNG operation");
static struct random_work my_work;
static struct random_work my_work1;
static struct random_work my_work2;
static struct random_work my_work3;
static struct random_work my_work4;
static struct random_work my_work5;
static struct random_work my_work6;
static struct random_work my_work7;
static struct random_work my_work8;
static struct random_work my_work9;
#define LEN 1024
static char buffer[LEN];
void lrng_cb(void *buf, ssize_t buflen)
{
printk("received %d bytes\n", (int)buflen);
}
static void cn(struct random_work *work)
{
get_blocking_random_bytes_cancel(work);
cancel_work_sync(&work->rw_work);
}
static int __init lrng_init(void)
{
get_blocking_random_bytes_cb(NULL, &my_work, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work1, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work2, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work3, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work4, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work5, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work6, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work7, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work8, buffer, LEN, lrng_cb);
get_blocking_random_bytes_cb(NULL, &my_work9, buffer, LEN, lrng_cb);
/* cancel one work to see that work can be canceled independent from
* others */
cn(&my_work);
return 0;
}
void __exit lrng_exit(void)
{
cn(&my_work1);
cn(&my_work2);
cn(&my_work3);
cn(&my_work4);
cn(&my_work5);
cn(&my_work6);
cn(&my_work7);
cn(&my_work8);
cn(&my_work9);
}
module_init(lrng_init);
module_exit(lrng_exit);
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 1/2] Addition of kernel_pool
2014-05-11 22:36 [PATCH 0/2] Add in-kernel /dev/random equivalent Stephan Mueller
@ 2014-05-11 22:37 ` Stephan Mueller
2014-05-11 22:38 ` [PATCH 2/2] Asynchronous and syncronous API for accessing kernel_pool Stephan Mueller
2014-06-06 11:59 ` [PATCH 0/2] Add in-kernel /dev/random equivalent Pavel Machek
1 sibling, 1 reply; 5+ messages in thread
From: Stephan Mueller @ 2014-05-11 22:37 UTC (permalink / raw)
To: Theodore Ts'o, LKML, linux-crypto
The kernel pool is intended to serve kernel-internal callers only.
Its purpose and usage is identical to the blocking_pool.
As the kernel_pool is not available to user space, user space cannot
directly interfere with the blocking behavior when obtaining
data from the kernel_pool. Thus, if entropy is present in the
kernel_pool, user space can hog /dev/random and yet the kernel
internal requestor of random numbers that are generated equally
to the blocking_pool (i.e. with the blocking behavior) will not
be affected until data is needed from the input_pool.
The patch treats the kernel_pool fully equally to the blocking and
nonblocking pool with respect to the initialization and update. As now
there are three output pools, the patch adds a round-robin logic for
processing additional entropy when the input_pool is nearly full.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
drivers/char/random.c | 50 +++++++++++++++++++++++++++++++++++++-------------
1 file changed, 37 insertions(+), 13 deletions(-)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 6b75713..2b53023 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -436,6 +436,7 @@ static void push_to_pool(struct work_struct *work);
static __u32 input_pool_data[INPUT_POOL_WORDS];
static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+static __u32 kernel_pool_data[OUTPUT_POOL_WORDS];
static struct entropy_store input_pool = {
.poolinfo = &poolinfo_table[0],
@@ -466,6 +467,17 @@ static struct entropy_store nonblocking_pool = {
push_to_pool),
};
+static struct entropy_store kernel_pool = {
+ .poolinfo = &poolinfo_table[1],
+ .name = "kernel",
+ .limit = 1,
+ .pull = &input_pool,
+ .lock = __SPIN_LOCK_UNLOCKED(kernel_pool.lock),
+ .pool = kernel_pool_data,
+ .push_work = __WORK_INITIALIZER(kernel_pool.push_work,
+ push_to_pool),
+};
+
static __u32 const twist_table[8] = {
0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
@@ -674,25 +686,36 @@ retry:
kill_fasync(&fasync, SIGIO, POLL_IN);
}
/* If the input pool is getting full, send some
- * entropy to the two output pools, flipping back and
+ * entropy to the output pools, flipping back and
* forth between them, until the output pools are 75%
* full.
*/
if (entropy_bits > random_write_wakeup_bits &&
r->initialized &&
r->entropy_total >= 2*random_read_wakeup_bits) {
- static struct entropy_store *last = &blocking_pool;
- struct entropy_store *other = &blocking_pool;
-
- if (last == &blocking_pool)
- other = &nonblocking_pool;
- if (other->entropy_count <=
- 3 * other->poolinfo->poolfracbits / 4)
- last = other;
- if (last->entropy_count <=
- 3 * last->poolinfo->poolfracbits / 4) {
- schedule_work(&last->push_work);
- r->entropy_total = 0;
+#define NUM_OUTPUT_POOLS 3
+ /* as we will recalculate this variable first thing in
+ * the loop, it will point to the first output pool
+ * after the first recalculation */
+ static int selected_pool = (NUM_OUTPUT_POOLS - 1);
+ int i = 0;
+ struct entropy_store *output_pools[NUM_OUTPUT_POOLS] = {
+ &blocking_pool,
+ &nonblocking_pool,
+ &kernel_pool};
+ /* select the next pool that has less than 75% fill
+ * rate */
+ for (i = 0; NUM_OUTPUT_POOLS > i; i++) {
+ struct entropy_store *p = NULL;
+ selected_pool =
+ (selected_pool + 1) % NUM_OUTPUT_POOLS;
+ p = output_pools[selected_pool];
+ if (p->entropy_count <=
+ p->poolinfo->poolfracbits / 4) {
+ schedule_work(&p->push_work);
+ r->entropy_total = 0;
+ break;
+ }
}
}
}
@@ -1273,6 +1296,7 @@ static int rand_initialize(void)
init_std_data(&input_pool);
init_std_data(&blocking_pool);
init_std_data(&nonblocking_pool);
+ init_std_data(&kernel_pool);
return 0;
}
early_initcall(rand_initialize);
--
1.9.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/2] Asynchronous and syncronous API for accessing kernel_pool
2014-05-11 22:37 ` [PATCH 1/2] Addition of kernel_pool Stephan Mueller
@ 2014-05-11 22:38 ` Stephan Mueller
0 siblings, 0 replies; 5+ messages in thread
From: Stephan Mueller @ 2014-05-11 22:38 UTC (permalink / raw)
To: Theodore Ts'o, LKML, linux-crypto
The kernel_pool is intended to be the in-kernel equivalent to the
blocking_pool, i.e. requests for random data may be blocked if
insufficient entropy is present.
The added API calls provide a synchronous function call
get_blocking_random_bytes where the caller is blocked.
In addition, an asynchronous API call of get_blocking_random_bytes_cb
is provided which returns immediately to the caller after submitting
the request for random data. The caller-provided buffer that shall be
filled with random data is filled up as available entropy permits. The
caller may provide a callback function that is invoked once the
request is completed.
A third API call, get_blocking_random_bytes_cancel, is provided to
cancel the random number gathering operation.
Signed-off-by: Stephan Mueller <smueller@chronox.de>
---
drivers/char/random.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/random.h | 16 +++++++
2 files changed, 129 insertions(+)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 2b53023..2e78318 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -401,6 +401,7 @@ static struct poolinfo {
*/
static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
+static DECLARE_WAIT_QUEUE_HEAD(random_kernel_wait);
static struct fasync_struct *fasync;
/**********************************************************************
@@ -682,6 +683,7 @@ retry:
/* should we wake readers? */
if (entropy_bits >= random_read_wakeup_bits) {
+ wake_up_interruptible(&random_kernel_wait);
wake_up_interruptible(&random_read_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
}
@@ -1727,3 +1729,114 @@ randomize_range(unsigned long start, unsigned long end, unsigned long len)
return 0;
return PAGE_ALIGN(get_random_int() % range + start);
}
+
+static bool get_blocking_random_bytes_term(bool *cancel)
+{
+ if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_bits)
+ return true;
+ return *cancel;
+}
+
+/*
+ * Equivalent function to get_random_bytes with the difference that this
+ * function blocks the request in a similar fashion as random_read(),
+ * implementing a /dev/random device for in-kernel users.
+ *
+ * This function may sleep.
+ *
+ * @buf caller allocated buffer filled with random data
+ * @nbytes requested number of bytes -- buffer should be at least as big
+ * @cancel pointer to variable that can be used to cancel the collection
+ * operation. If this boolean is set to true, the collection operation
+ * is terminated immediately. When it is set to false during the
+ * collection loop, the collection is terminated immediately.
+ *
+ * return: positive value: obtained number of bytes on successful
+ * negative value: error code on error
+ */
+ssize_t get_blocking_random_bytes(void *buf, ssize_t nbytes, bool *cancel)
+{
+ ssize_t ret = 0;
+
+ if (nbytes <= 0)
+ return nbytes;
+ BUG_ON(NULL == buf);
+
+ while (ret < nbytes) {
+ ssize_t round = 0;
+ ssize_t pull = min_t(ssize_t, (nbytes - ret), SEC_XFER_SIZE);
+ if (*cancel)
+ return ret;
+ round = extract_entropy(&kernel_pool, (buf + ret), pull, 0, 0);
+ if (0 > round)
+ return round;
+ /* arch_random_refill could be added here */
+ if (0 == round)
+ wait_event_interruptible(random_kernel_wait,
+ get_blocking_random_bytes_term(cancel));
+ ret += round;
+ }
+ return ret;
+}
+EXPORT_SYMBOL(get_blocking_random_bytes);
+
+/*
+ * Immediate canceling the collection operation for the random_work
+ */
+void get_blocking_random_bytes_cancel(struct random_work *rw)
+{
+ rw->cancel = true;
+ wake_up_interruptible(&random_kernel_wait);
+
+}
+EXPORT_SYMBOL(get_blocking_random_bytes_cancel);
+
+static void get_blocking_random_bytes_work(struct work_struct *work)
+{
+ struct random_work *rw = container_of(work, struct random_work,
+ rw_work);
+ int ret;
+
+ ret = get_blocking_random_bytes(rw->rw_buf, rw->rw_len, &rw->cancel);
+ if (rw->rw_cb)
+ rw->rw_cb(rw->rw_buf, ret);
+}
+
+/*
+ * Asynchronous invocation of the blocking interface. The function
+ * queues the request in either the private work queue supplied with the
+ * wq argument or in the general work queue framework if wq is NULL.
+ * Once the request is completed or upon receiving an error, the callback
+ * function of cb is called, if not NULL, to inform the caller about the
+ * completion of its operation.
+ *
+ * If a caller wants to cancel the work (e.g. in the module_exit function),
+ * simply call
+ * get_blocking_random_bytes_cancel(&my_random_work);
+ * cancel_work_sync(&my_random_work.rw_work);
+ *
+ * @wq pointer to private work queue or NULL - input
+ * @rw handle to the work queue frame - output
+ * @buf allocated buffer where random numbers are to be stored
+ * @nbytes size of buf and implicitly number of bytes requested
+ * @cb callback function where
+ * * buf holds the pointer to buf will be supplied
+ * * buflen holds the length of the gathered random numbers or error code
+ * of the generation function.
+ */
+void get_blocking_random_bytes_cb(struct workqueue_struct *wq,
+ struct random_work *rw,
+ void *buf, ssize_t nbytes,
+ void (*cb)(void *buf, ssize_t buflen))
+{
+ rw->rw_buf = buf;
+ rw->rw_len = nbytes;
+ rw->rw_cb = cb;
+ rw->cancel = false;
+ INIT_WORK(&rw->rw_work, get_blocking_random_bytes_work);
+ if (wq)
+ queue_work(wq, &rw->rw_work);
+ else
+ schedule_work(&rw->rw_work);
+}
+EXPORT_SYMBOL(get_blocking_random_bytes_cb);
diff --git a/include/linux/random.h b/include/linux/random.h
index 57fbbff..d0a1fff 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -7,6 +7,7 @@
#define _LINUX_RANDOM_H
#include <uapi/linux/random.h>
+#include <linux/workqueue.h>
extern void add_device_randomness(const void *, unsigned int);
extern void add_input_randomness(unsigned int type, unsigned int code,
@@ -112,4 +113,19 @@ static inline u32 next_pseudo_random32(u32 seed)
return seed * 1664525 + 1013904223;
}
+struct random_work {
+ struct work_struct rw_work;
+ void *rw_buf;
+ ssize_t rw_len;
+ void (*rw_cb)(void *buf, ssize_t buflen);
+ bool cancel;
+};
+
+ssize_t get_blocking_random_bytes(void *buf, ssize_t nbytes, bool *cancel);
+void get_blocking_random_bytes_cancel(struct random_work *rw);
+void get_blocking_random_bytes_cb(struct workqueue_struct *wq,
+ struct random_work *rw,
+ void *buf, ssize_t nbytes,
+ void (*cb)(void *buf, ssize_t buflen));
+
#endif /* _LINUX_RANDOM_H */
--
1.9.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] Add in-kernel /dev/random equivalent
2014-05-11 22:36 [PATCH 0/2] Add in-kernel /dev/random equivalent Stephan Mueller
2014-05-11 22:37 ` [PATCH 1/2] Addition of kernel_pool Stephan Mueller
@ 2014-06-06 11:59 ` Pavel Machek
2014-06-06 12:23 ` Stephan Mueller
1 sibling, 1 reply; 5+ messages in thread
From: Pavel Machek @ 2014-06-06 11:59 UTC (permalink / raw)
To: Stephan Mueller; +Cc: Theodore Ts'o, LKML, linux-crypto
On Mon 2014-05-12 00:36:01, Stephan Mueller wrote:
> Hi,
>
> as discussed in thread [1], an in-kernel equivalent to the blocking
> /dev/random device behavior is suggested. This in-kernel blocking access to
> the RNG can be used to seed deterministic random number generators with random
> numbers that are directly backed by the underlying noise sources.
>
> The following patch implements this concept by adding a third output pool, the
> kernel_pool that is only accessible inside the kernel. That kernel_pool feeds
> the blocking operation API calls to obtain random numbers.
>
> Please find a test kernel module attached. You can unload it even while the
> collection process is ongoing.
>
> [1] https://lkml.org/lkml/2014/4/27/174
>
> Stephan Mueller (2):
> Addition of kernel_pool
> Asynchronous and syncronous API for accessing kernel_pool
>
> drivers/char/random.c | 163
> +++++++++++++++++++++++++++++++++++++++++++++----
> include/linux/random.h | 16 +++++
> 2 files changed, 166 insertions(+), 13 deletions(-)
* Copyright (c) 2014
*
* Permission is hereby granted, free of charge, to any person
*obtaining a copy
* of this software and associated documentation files (the
*"Software"), to deal
* in the Software without restriction, including without limitation
*the rights
* to use, copy, modify, merge, publish, distribute, sublicense,
*and/or sell
* copies of the Software, and to permit persons to whom the Software
*is
* furnished to do so, subject to the following conditions:
...but module_license says this is GPL...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] Add in-kernel /dev/random equivalent
2014-06-06 11:59 ` [PATCH 0/2] Add in-kernel /dev/random equivalent Pavel Machek
@ 2014-06-06 12:23 ` Stephan Mueller
0 siblings, 0 replies; 5+ messages in thread
From: Stephan Mueller @ 2014-06-06 12:23 UTC (permalink / raw)
To: Pavel Machek; +Cc: Theodore Ts'o, LKML, linux-crypto
Am Freitag, 6. Juni 2014, 13:59:00 schrieb Pavel Machek:
Hi Pavel,
>On Mon 2014-05-12 00:36:01, Stephan Mueller wrote:
>> Hi,
>>
>> as discussed in thread [1], an in-kernel equivalent to the blocking
>> /dev/random device behavior is suggested. This in-kernel blocking
>> access to the RNG can be used to seed deterministic random number
>> generators with random numbers that are directly backed by the
>> underlying noise sources.
>>
>> The following patch implements this concept by adding a third output
>> pool, the kernel_pool that is only accessible inside the kernel.
>> That kernel_pool feeds the blocking operation API calls to obtain
>> random numbers.
>>
>> Please find a test kernel module attached. You can unload it even
>> while the collection process is ongoing.
>>
>> [1] https://lkml.org/lkml/2014/4/27/174
>>
>> Stephan Mueller (2):
>> Addition of kernel_pool
>> Asynchronous and syncronous API for accessing kernel_pool
>>
>> drivers/char/random.c | 163
>>
>> +++++++++++++++++++++++++++++++++++++++++++++----
>>
>> include/linux/random.h | 16 +++++
>> 2 files changed, 166 insertions(+), 13 deletions(-)
>
> * Copyright (c) 2014
> *
> * Permission is hereby granted, free of charge, to any person
> *obtaining a copy
> * of this software and associated documentation files (the
> *"Software"), to deal
> * in the Software without restriction, including without limitation
> *the rights
> * to use, copy, modify, merge, publish, distribute, sublicense,
> *and/or sell
> * copies of the Software, and to permit persons to whom the Software
> *is
> * furnished to do so, subject to the following conditions:
>
>...but module_license says this is GPL...
Thank you very much for the hint -- this is an oversight on my behalf. I
wanted the test kernel code to be licensed in a dual BSD/GPLv2 style.
As this is just a test module to demonstrate the appropriateness of the
offered patch, I hope you can still live with it until a potential new
submission is provided. Though, if you insist I can resubmit the test
module with the dual BSD/GPLv2 clause.
Ciao
Stephan
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2014-06-06 12:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-11 22:36 [PATCH 0/2] Add in-kernel /dev/random equivalent Stephan Mueller
2014-05-11 22:37 ` [PATCH 1/2] Addition of kernel_pool Stephan Mueller
2014-05-11 22:38 ` [PATCH 2/2] Asynchronous and syncronous API for accessing kernel_pool Stephan Mueller
2014-06-06 11:59 ` [PATCH 0/2] Add in-kernel /dev/random equivalent Pavel Machek
2014-06-06 12:23 ` Stephan Mueller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox