"ChaCha20 256-bit key");
#endif /* CONFIG_LIBUKRANDOM_CMDLINE_SEED */
+/* It is critical that the internal state is initialized before we generate
+ * random numbers. Instead of relying on the calling API, use this as an
+ * additional failsafe for self-protection.
+ */
+static __bool initialized = __false;
+
/* This value isn't important, as long as it's sufficiently asymmetric */
static const char sigma[16] = "expand 32-byte k";
*drv = (void *)UK_SWRAND_DRIVER_NONE;
chacha_init(&uk_swrand_def, seedv);
+ initialized = __true;
return rc;
}
*drv = (void *)UK_SWRAND_DRIVER_NONE;
chacha_init(&uk_swrand_def, seedv_cmdl);
+ initialized = __true;
return 0;
}
uk_pr_info("Entropy source: %s\n", (*drv)->name);
chacha_init(&uk_swrand_def, seedv);
+ initialized = __true;
return 0;
}
-static __u32 uk_swrand_randr_r(struct uk_swrand *r)
+static inline __u32 uk_swrand_randr_r(struct uk_swrand *r)
{
__u32 res;
}
}
-__u32 uk_swrand_randr(void)
+int __check_result uk_swrand_randr(__u32 *val)
{
- __u32 ret;
+ if (unlikely(initialized == __false))
+ return -ENODEV;
uk_spin_lock(&swrand_lock);
- ret = uk_swrand_randr_r(&uk_swrand_def);
+ *val = uk_swrand_randr_r(&uk_swrand_def);
uk_spin_unlock(&swrand_lock);
- return ret;
+ return 0;
}
{
__sz step, chunk_size, i;
__u32 rd;
+ int rc;
if (!driver)
return -ENODEV;
step = sizeof(__u32);
chunk_size = buflen % step;
- for (i = 0; i < buflen - chunk_size; i += step)
- *(__u32 *)((char *)buf + i) = uk_swrand_randr();
+ for (i = 0; i < buflen - chunk_size; i += step) {
+ rc = uk_swrand_randr(&rd);
+ if (unlikely(rc))
+ return rc;
+ *(__u32 *)((char *)buf + i) = rd;
+ }
/* fill the remaining bytes of the buffer */
if (chunk_size > 0) {
- rd = uk_swrand_randr();
+ rc = uk_swrand_randr(&rd);
+ if (unlikely(rc))
+ return rc;
memcpy(buf + i, &rd, chunk_size);
}
int uk_swrand_init(struct uk_random_driver **drv);
/* Get a 32-bit random number */
-__u32 uk_swrand_randr(void);
+int __check_result uk_swrand_randr(__u32 *val);
#endif /* __UK_RANDOM_SWRAND_H__ */