Bug 1627822

Summary: rngd: failed to init TPM2 RNG
Product: Red Hat Enterprise Linux 7 Reporter: Vilém Maršík <vmarsik>
Component: rng-toolsAssignee: Neil Horman <nhorman>
Status: CLOSED ERRATA QA Contact: Vilém Maršík <vmarsik>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.6CC: bhu, jomurphy, jshortt, jsnitsel, nhorman, vmarsik
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2018-10-30 07:47:40 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1532680    

Description Vilém Maršík 2018-09-11 15:01:47 UTC
Description of problem:
This was found during testing of Bug 1578136 - TPM driver updates for RHEL7.6 , according to https://bugzilla.redhat.com/show_bug.cgi?id=1578136#c4.

TPM2 looks listed among HWRNG sources:
# cat /sys/devices/virtual/misc/hw_random/rng_available
tpm-rng-0
# cat /sys/devices/virtual/misc/hw_random/rng_current
tpm-rng-0

The device file is present:
# ls -l /dev/tpm0
crw-rw----. 1 tss tss 10, 224 Sep  7 06:09 /dev/tpm0

But it does not work with rngd:
# rngd -f -d
Initalizing available sources
Unable to open file: /dev/tpm0
Failed to init entropy source 1: TPM RNG Device
Enabling RDRAND rng support
Enabling JITTER rng support


Version-Release number of selected component (if applicable):
rng-tools-6.3.1-2.el7.x86_64
kernel-3.10.0-944.el7.x86_64

How reproducible:
100%

Steps to Reproduce:
1. get a machine with working TPM2
2. rngd -f -d
3.

Actual results:
Failed to init entropy source 1: TPM RNG Device

Expected results:
TPM RNG used, enough entropy in the pool

Additional info:

Comment 13 Vilém Maršík 2018-09-12 14:40:50 UTC
Yes, it sounds like a reasonable speedup. With "rngd -f -d -x 1 -x 2 -x 5", the command 
time cat /dev/random | rngtest -c 1
took 2.4s. Without, I have killed it after 5 and half minutes of waiting.

With "-c 100" and rngd it takes 3m45s.

Comment 14 Neil Horman 2018-09-12 15:54:21 UTC
ok, so I'll just default disable the TPM in rngd, and start work upstream to remove it entirely there

Comment 16 Vilém Maršík 2018-09-12 17:05:10 UTC
So you are saying that new kernel feeds entropy directly from both TPM1.2 and TPM2, so that you can remove that part from rngd?

Comment 18 Jerry Snitselaar 2018-09-12 18:12:53 UTC
(In reply to Vilém Maršík from comment #16)
> So you are saying that new kernel feeds entropy directly from both TPM1.2
> and TPM2, so that you can remove that part from rngd?

The code that went into the 7.6 kernel for tpm now registers a hwrng device, which you can see in the /sys/devices/virtual/misc/hw_randcom/rng_available as tpm-rng-0. If rngd is using the hwrng entropy source, then it will be able to
talk to the tpm through that interface if tpm-rng-0 is the hwrng device being used (whichever is in /sys/devices/virtual/misc/hw_random/rng_current I believe). So there is no need for rngd to try and interact directly with the tpm through /dev/tpm0.

The new code has a function named tpm_hwrng_read(), which will get called. This in turn will call tpm_get_random(), which has code to deal with both a tpm1.2 device and a tpm2.0 device.

Comment 19 Vilém Maršík 2018-09-13 13:28:27 UTC
(In reply to Jerry Snitselaar from comment #18)
Thanks Jerry for the explanation, that would all make sense ... except the kernel 3.10.0-944.el7.x86_64 failed to get entropy from the TPM, when I was testing it: https://bugzilla.redhat.com/show_bug.cgi?id=1578136#c10

Did I use an old version? Or is that another bug to open?

Comment 20 Jerry Snitselaar 2018-09-13 14:08:30 UTC
It was getting entropy from the tpm when rngd was running according to your comment. When you ran the command Neil suggested it was getting entropy, yes?

Comment 21 Jerry Snitselaar 2018-09-13 14:36:53 UTC
With rngd stopped, I can also generate entropy with the following example:

# systemctl status rngd

● rngd.service - Hardware RNG Entropy Gatherer Daemon
   Loaded: loaded (/usr/lib/systemd/system/rngd.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Mon 2010-09-13 07:27:21 MST; 11min ago
  Process: 29018 ExecStart=/sbin/rngd -f (code=killed, signal=TERM)
 Main PID: 29018 (code=killed, signal=TERM)

Sep 11 12:09:20 nuc7 systemd[1]: Started Hardware RNG Entropy Gatherer Daemon.
Sep 11 12:09:20 nuc7 systemd[1]: Starting Hardware RNG Entropy Gatherer Daemon...
Sep 11 12:09:20 nuc7 rngd[29018]: Initalizing available sources
Sep 11 12:09:20 nuc7 rngd[29018]: Failed to init entropy source 1: TPM RNG Device
Sep 11 12:09:20 nuc7 rngd[29018]: Enabling RDSEED rng support
Sep 11 12:09:21 nuc7 rngd[29018]: Enabling JITTER rng support
Sep 13 07:27:21 nuc7 systemd[1]: Stopping Hardware RNG Entropy Gatherer Daemon...
Sep 13 07:27:21 nuc7 systemd[1]: Stopped Hardware RNG Entropy Gatherer Daemon.


# echo "" > /sys/kernel/debug/tracing/trace
# cat /sys/kernel/debug/tracing/trace

# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |

# od -vAn -N2000 -tu4 < /dev/hwrng


 2727710707 2087886302  417505693 1483596787
 1304738589 1447243707 2950347962 4158438387
 2363128033 2683153495 2533959492 2639363744
 1674101285 1852002512 2924180422 2426772814
 1966433794 2809074975  346351492 3368414523
....

# cat /sys/kernel/debug/tracing/trace

# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
 3)               |  tpm_hwrng_read() {
 3)               |    tpm_get_random() {
 3)               |      tpm_chip_find_get() {
 3)   0.884 us    |        tpm_try_get_ops();
 3)   3.358 us    |      }
 3)               |      tpm2_get_random() {
 3)               |        tpm_transmit_cmd() {
 3)               |          tpm_transmit() {
 3)               |            crb_request_locality [tpm_crb]() {
 3) ! 11332.10 us |              __crb_request_locality.isra.5 [tpm_crb]();
 3) ! 11335.65 us |            }
 3)   0.288 us    |            tpm2_prepare_space();
 3)   0.375 us    |            tpm2_calc_ordinal_duration();
 3)   0.183 us    |            tpm2_commit_space();
 3)               |            crb_relinquish_locality [tpm_crb]() {
 3) ! 336.273 us  |              __crb_relinquish_locality.isra.6 [tpm_crb]();
 3) ! 337.667 us  |            }
 3) ! 18575.07 us |          }
 3) ! 18576.65 us |        }
 3)               |        tpm_transmit_cmd() {
 3)               |          tpm_transmit() {
 3)               |            crb_request_locality [tpm_crb]() {
 3) ! 113.413 us  |              __crb_request_locality.isra.5 [tpm_crb]();
 3) ! 114.642 us  |            }
 3)   0.200 us    |            tpm2_prepare_space();
 3)   0.138 us    |            tpm2_calc_ordinal_duration();
 3)   0.150 us    |            tpm2_commit_space();
 3)               |            crb_relinquish_locality [tpm_crb]() {
 3) ! 334.972 us  |              __crb_relinquish_locality.isra.6 [tpm_crb]();
 3) ! 336.210 us  |            }
 3) ! 6668.035 us |          }
 3) ! 6669.230 us |        }
 3) ! 25248.83 us |      }
 3)   0.565 us    |      tpm_put_ops();
 3) ! 25257.12 us |    }
 3) ! 25259.03 us |  }
 3)               |  tpm_hwrng_read() {
 3)               |    tpm_get_random() {
 3)               |      tpm_chip_find_get() {
 3)   0.321 us    |        tpm_try_get_ops();
 3)   1.726 us    |      }
 3)               |      tpm2_get_random() {
 3)               |        tpm_transmit_cmd() {
 3)               |          tpm_transmit() {
 3)               |            crb_request_locality [tpm_crb]() {
 3) ! 115.712 us  |              __crb_request_locality.isra.5 [tpm_crb]();
 3) ! 128.457 us  |            }
 3)   0.140 us    |            tpm2_prepare_space();
 3)   0.132 us    |            tpm2_calc_ordinal_duration();
 3)   0.265 us    |            tpm2_commit_space();
 3)               |            crb_relinquish_locality [tpm_crb]() {
 3) ! 330.803 us  |              __crb_relinquish_locality.isra.6 [tpm_crb]();
 3) ! 332.284 us  |            }
 3) ! 6739.232 us |          }
 3) ! 6740.454 us |        }
 3)               |        tpm_transmit_cmd() {
 3)               |          tpm_transmit() {
 3)               |            crb_request_locality [tpm_crb]() {
 3) ! 111.940 us  |              __crb_request_locality.isra.5 [tpm_crb]();
 3) ! 113.218 us  |            }
 3)   0.255 us    |            tpm2_prepare_space();
 3)   0.337 us    |            tpm2_calc_ordinal_duration();
 3)   0.237 us    |            tpm2_commit_space();
 3)               |            crb_relinquish_locality [tpm_crb]() {
 3) ! 330.277 us  |              __crb_relinquish_locality.isra.6 [tpm_crb]();
 3) ! 331.504 us  |            }
 3) ! 6667.393 us |          }
 3) ! 6668.627 us |        }
 3) ! 13412.01 us |      }
 3)   0.528 us    |      tpm_put_ops();
 3) ! 13417.74 us |    }
 3) ! 13418.96 us |  }
....

Comment 24 Vilém Maršík 2018-09-13 18:47:31 UTC
Okay, I had kernel 3.10, this was implemented into 3.17, thus no entropy without rngd (which BTW seemed to use RDRAND + JITTER instead of TPM).

Makes sense. New products with kernel 3.17+ don't need rngd with TPM support anymore. Running new rngd on old kernel is not supported. So the support was removed.

I can test if it works with a 3.17 kernel, check for "hwrng" kernel thread, and close this bug if everything succeeds.

Comment 25 Jerry Snitselaar 2018-09-13 19:31:04 UTC
I think it would still be possible to use rng-tools with newer kernels, especially if the kernel thread isn't configured. I'm not an expert on rng-tools though, so not sure how the kernel thread and rng-tools would behave with each other.

Comment 26 Jerry Snitselaar 2018-09-13 19:58:52 UTC
Just to be clear, I think Neil's solution of disabling direct access to the TPM 
in rngd is still a good solution to handle it complaining about not being able 
to open /dev/tpm0 in rng-tools. My responses are about what you were experiencing 
when trying to get entropy out of /dev/random without rngd running, and to show
that when rng_current is tpm-rng-0 accessing /dev/hwrng will result in getting
entropy from the tpm device.

Comment 27 Vilém Maršík 2018-09-25 14:18:59 UTC
Okay, this seems to work on Beta - rngd with RDRAND, JITTER, and direct TPM access still seems to feed entropy into system:

# time cat /dev/random | rngtest -c 1
( ... killed with CTRL-C after a few minutes )
# rngd -f -d -x 1 -x 2 -x 5
Disabling 1: TPM RNG Device
Disabling 2: Intel RDRAND Instruction RNG
Disabling 5: JITTER Entropy generator

Initalizing available sources

(switched terminal)
# echo *tpm* > /sys/kernel/debug/tracing/set_ftrace_filter
# echo *locality* >> /sys/kernel/debug/tracing/set_ftrace_filter
# echo function_graph > /sys/kernel/debug/tracing/current_tracer
# time cat /dev/random | rngtest -c 1
(...)
real    0m2.391s
(...)
# cat /sys/kernel/debug/tracing/trace
# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |
   6)               |  tpm_hwrng_read() {
   6)               |    tpm_get_random() {
   6)               |      tpm_chip_find_get() {
   6)   0.142 us    |        tpm_try_get_ops();
   6)   0.774 us    |      }
   6)               |      tpm2_get_random() {
   6)               |        tpm_transmit_cmd() {
   6)               |          tpm_transmit() {
   6)   0.077 us    |            tpm_tis_clkrun_enable();
   6)               |            request_locality() {
   6)               |              check_locality() {
   6)   1.445 us    |                tpm_tcg_read_bytes();
   6)   1.867 us    |              }
   6)   0.046 us    |              tpm_tcg_write_bytes();
   6)               |              check_locality() {
   6)   1.393 us    |                tpm_tcg_read_bytes();
   6)   1.808 us    |              }
   6)   4.838 us    |            }
(...)
   6)               |  tpm_hwrng_read() {
   6)               |    tpm_get_random() {
   6)               |      tpm_chip_find_get() {
   6)   0.045 us    |        tpm_try_get_ops();
   6)   0.363 us    |      }
   6)               |      tpm2_get_random() {
   6)               |        tpm_transmit_cmd() {
   6)               |          tpm_transmit() {
   6)   0.034 us    |            tpm_tis_clkrun_enable();
   6)               |            request_locality() {
   6)               |              check_locality() {
   6)   1.410 us    |                tpm_tcg_read_bytes();
   6)   1.744 us    |              }
   6)   0.034 us    |              tpm_tcg_write_bytes();
   6)               |              check_locality() {
   6)   1.479 us    |                tpm_tcg_read_bytes();
   6)   1.819 us    |              }
   6)   4.560 us    |            }
(...)

The problem is that rngd does not list this in the available sources, and tells it has no entropy sources.

Let's close this for tomorrow's 7.6 deadline, and open another bug for the output.

Comment 28 Vilém Maršík 2018-09-25 14:26:59 UTC
Created Bug 1632786 - rngd lists no entropy sources, but still reads from TPM2.

Comment 30 errata-xmlrpc 2018-10-30 07:47:40 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2018:3022