crypto: jitter - output full sample from test interface

The Jitter RNG time delta is computed based on the difference of two
high-resolution, 64-bit time stamps. However, the test interface added
in 69f1c387ba only outputs the lower 32 bits of those time stamps. To
ensure all information is available during the evaluation process of
the Jitter RNG, output the full 64-bit time stamps.

Any clients collecting data from the test interface will need to be
updated to take this change into account.

Additionally, the size of the temporary buffer that holds the data for
user space has been clarified. Previously, this buffer was
JENT_TEST_RINGBUFFER_SIZE (= 1000) bytes in size, however that value
represents the number of samples held in the kernel space ring buffer,
with each sample taking 8 (previously 4) bytes.

Rather than increasing the size to allow for all 1000 samples to be
output, we keep it at 1000 bytes, but clarify that this means at most
125 64-bit samples will be output every time this interface is called.

Reviewed-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Joachim Vandersmissen <git@jvdsn.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Joachim Vandersmissen 2024-10-09 21:47:34 -05:00 committed by Herbert Xu
parent 9374d6b466
commit 04305f8341
2 changed files with 18 additions and 17 deletions

View File

@ -15,7 +15,7 @@
#define JENT_TEST_RINGBUFFER_MASK (JENT_TEST_RINGBUFFER_SIZE - 1) #define JENT_TEST_RINGBUFFER_MASK (JENT_TEST_RINGBUFFER_SIZE - 1)
struct jent_testing { struct jent_testing {
u32 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE]; u64 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE];
u32 rb_reader; u32 rb_reader;
atomic_t rb_writer; atomic_t rb_writer;
atomic_t jent_testing_enabled; atomic_t jent_testing_enabled;
@ -72,7 +72,7 @@ static void jent_testing_fini(struct jent_testing *data, u32 boot)
pr_warn("Disabling data collection\n"); pr_warn("Disabling data collection\n");
} }
static bool jent_testing_store(struct jent_testing *data, u32 value, static bool jent_testing_store(struct jent_testing *data, u64 value,
u32 *boot) u32 *boot)
{ {
unsigned long flags; unsigned long flags;
@ -156,20 +156,20 @@ static int jent_testing_reader(struct jent_testing *data, u32 *boot,
} }
/* We copy out word-wise */ /* We copy out word-wise */
if (outbuflen < sizeof(u32)) { if (outbuflen < sizeof(u64)) {
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
goto out; goto out;
} }
memcpy(outbuf, &data->jent_testing_rb[data->rb_reader], memcpy(outbuf, &data->jent_testing_rb[data->rb_reader],
sizeof(u32)); sizeof(u64));
data->rb_reader++; data->rb_reader++;
spin_unlock_irqrestore(&data->lock, flags); spin_unlock_irqrestore(&data->lock, flags);
outbuf += sizeof(u32); outbuf += sizeof(u64);
outbuflen -= sizeof(u32); outbuflen -= sizeof(u64);
collected_data += sizeof(u32); collected_data += sizeof(u64);
} }
out: out:
@ -189,16 +189,17 @@ static int jent_testing_extract_user(struct file *file, char __user *buf,
/* /*
* The intention of this interface is for collecting at least * The intention of this interface is for collecting at least
* 1000 samples due to the SP800-90B requirements. So, we make no * 1000 samples due to the SP800-90B requirements. However, due to
* effort in avoiding allocating more memory that actually needed * memory and performance constraints, it is not desirable to allocate
* by the user. Hence, we allocate sufficient memory to always hold * 8000 bytes of memory. Instead, we allocate space for only 125
* that amount of data. * samples, which will allow the user to collect all 1000 samples using
* 8 calls to this interface.
*/ */
tmp = kmalloc(JENT_TEST_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL); tmp = kmalloc(125 * sizeof(u64) + sizeof(u64), GFP_KERNEL);
if (!tmp) if (!tmp)
return -ENOMEM; return -ENOMEM;
tmp_aligned = PTR_ALIGN(tmp, sizeof(u32)); tmp_aligned = PTR_ALIGN(tmp, sizeof(u64));
while (nbytes) { while (nbytes) {
int i; int i;
@ -212,7 +213,7 @@ static int jent_testing_extract_user(struct file *file, char __user *buf,
schedule(); schedule();
} }
i = min_t(int, nbytes, JENT_TEST_RINGBUFFER_SIZE); i = min_t(int, nbytes, 125 * sizeof(u64));
i = reader(tmp_aligned, i); i = reader(tmp_aligned, i);
if (i <= 0) { if (i <= 0) {
if (i < 0) if (i < 0)
@ -251,7 +252,7 @@ static struct jent_testing jent_raw_hires = {
.read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(jent_raw_hires.read_wait) .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(jent_raw_hires.read_wait)
}; };
int jent_raw_hires_entropy_store(__u32 value) int jent_raw_hires_entropy_store(__u64 value)
{ {
return jent_testing_store(&jent_raw_hires, value, &boot_raw_hires_test); return jent_testing_store(&jent_raw_hires, value, &boot_raw_hires_test);
} }

View File

@ -22,11 +22,11 @@ extern struct rand_data *jent_entropy_collector_alloc(unsigned int osr,
extern void jent_entropy_collector_free(struct rand_data *entropy_collector); extern void jent_entropy_collector_free(struct rand_data *entropy_collector);
#ifdef CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE #ifdef CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE
int jent_raw_hires_entropy_store(__u32 value); int jent_raw_hires_entropy_store(__u64 value);
void jent_testing_init(void); void jent_testing_init(void);
void jent_testing_exit(void); void jent_testing_exit(void);
#else /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */ #else /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */
static inline int jent_raw_hires_entropy_store(__u32 value) { return 0; } static inline int jent_raw_hires_entropy_store(__u64 value) { return 0; }
static inline void jent_testing_init(void) { } static inline void jent_testing_init(void) { }
static inline void jent_testing_exit(void) { } static inline void jent_testing_exit(void) { }
#endif /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */ #endif /* CONFIG_CRYPTO_JITTERENTROPY_TESTINTERFACE */