Bug 1568263 - kaslr: arm64 kernel does not use entropy source supplied from EFI_RNG_PROTOCOL to populate /dev/urandom
Summary: kaslr: arm64 kernel does not use entropy source supplied from EFI_RNG_PROTOCO...
Keywords:
Status: CLOSED WONTFIX
Alias: None
Product: Fedora
Classification: Fedora
Component: kernel
Version: rawhide
Hardware: aarch64
OS: Linux
unspecified
low
Target Milestone: ---
Assignee: Bhupesh Sharma
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2018-04-17 05:09 UTC by Bhupesh Sharma
Modified: 2020-07-30 06:29 UTC (History)
19 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2020-07-30 06:29:44 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Bhupesh Sharma 2018-04-17 05:09:57 UTC
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>


Note You need to log in before you can comment on or make changes to this bug.