Description of problem:
I was doing some experimentation with kernel modules (or extending the argument even to user-space applications) which relies on random number generation support from the kernel using 'getrandom' / 'get_random_bytes' kind of
syscall/kernel interface, on platforms where we don't have a
compatible EFI firmware which supports EFI_RNG_PROTOCOL, I was
thinking that there would not be sufficient entropy (inside '/dev/urandom') available for the caller kernel modules (or user-space applications)
and I was looking to enable 'CONFIG_WARN_ALL_UNSEEDED_RANDOM=y' to ensure that
callers of unseeded randomness in such kernel modules/user-space
applications are WARN'ed.
1. Instead I saw that random numbers are available on these platforms
starting from early boot (i.e. crng init is already done):
[root@qualcomm-amberwing]# dmesg | grep -i random
random: crng init done
2. The reason is that upstream aarch64 kernel uses the timer counter
value to generate random numbers starting from early boot (which is
probable not a good alternative when we have a compatible EFI firmware
which can pass entropy to the kernel):
'include/linux/timex.h' :
---------------------------
#define random_get_entropy() get_cycles()
'arch/arm64/include/asm/timex.h' :
-------------------------------------------
/*
* Use the current timer as a cycle counter since this is what we use for
* the delay loop.
*/
#define get_cycles() arch_timer_read_counter()
'drivers/clocksource/arm_arch_timer.c' :
--------------------------------------------------
u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct;
3. And when other linux kernel modules (or even userspace
applications) try to do some random number generation using the kernel
support using 'getrandom' / 'get_random_bytes', the entropy is already
available.
So the caller would be supplied with random numbers, as I confirmed on
arm64 platforms which do not support EFI_RNG_PROTOCOL:
Also on such platforms 'wait_for_random_bytes' returns 0 indicating
that the 'urandom' pool has been seeded:
/*
* Wait for the urandom pool to be seeded and thus guaranteed to supply
* cryptographically secure random numbers. This applies to: the /dev/urandom
* device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
* family of functions. Using any of these functions without first calling
* this function forfeits the guarantee of security.
*
* Returns: 0 if the urandom pool has been seeded.
* -ERESTARTSYS if the function was interrupted by a signal.
*/
int wait_for_random_bytes(void)
4. Accordingly, I think the arm64 timer count is probably not a good
entropy source on platforms which indeed support EFI_RNG_PROTOCOL and
we should be looking to extend 'arch_get_random_*' or
'random_get_entropy' for arm64, to provide seed/entropy using APIs
like 'efi_random_get_seed'?
How reproducible:
Attachment contains an example of a loadable kernel module which can be used to generate a random number using get_random_bytes() API. It also uses 'wait_for_random_bytes' to make sure that the urandom pool is already seeded and thus guaranteed to supply cryptographically secure random numbers
Steps to Reproduce:
1. Compile the loadable module:
# cd get_random_module
# make clean; make
2. Insert the loadable module:
# insmod mod_get_random_bytes.ko
3. Verify that you see the message 'wait_for_random_bytes returned ret=0' and the random number generated is unique everytime the module is loaded.
Additional info:
Please see the upstream discussion I am having with arm maintainers on the same here: <https://marc.info/?l=kexec&m=152373738806134&w=2>