Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate random bytes #1730

Closed
matzedav opened this issue Aug 2, 2017 · 6 comments
Closed

Generate random bytes #1730

matzedav opened this issue Aug 2, 2017 · 6 comments
Labels

Comments

@matzedav
Copy link

matzedav commented Aug 2, 2017

Hey,

I want to use LibTomCrypt in my TA to generate random keys (on QEMU Optee v8). If I use the following methods I get repeatedly the same "random" bytes.

res = TEE_GenerateKey(obh, key_size, attr, attr_size)
res = TEE_GenerateRandom(buf, buf_size)

Did I have to initialize the PRNG by myself or is it initialized automatically when i call the functions?
Your help is much appreciated!

@matzedav matzedav changed the title random bytes from TA Generate random bytes Aug 2, 2017
@jforissier
Copy link
Contributor

Hi @xNado,

TL;DR: it looks like something's wrong with entropy gathering. You should not need to call any PRNG initialization function. More investigation is needed.

  • QEMU v8 uses a software PRNG. This is configured by CFG_WITH_SOFTWARE_PRNG=y (here) because there is no hardware source of randomness on this platform (or we don't have a driver for it). The software implementation is based on the Fortuna algorithm in LibTomcrypt, unless AES or SHA256 are disabled (here), in which case RC4 is used (here).
  • Entropy is injected into the PRNG (whatever its type) by plat_prng_add_jitter_entropy() and plat_prng_add_jitter_entropy_no_rpc() (here). Those can be redefined by platform-specific code. For QEMU, which has a CNTPCT counter (CFG_SECURE_TIME_SOURCE_CNTPCT=y, here), entropy is read from the CNTPCT (here).
  • Entropy is injected first at OP-TEE initialization time (here), and also when switching from secure to normal world (here and when a TA opens (here) or closes (here) a session. So we should expect no repeating pattern in the random output.

That's for the theory. Now, indeed I observe that after each boot of QEMU, the output of TEE_GenerateRandom() is the same, although plat_prng_add_jitter_entropy() claims it is adding a different value each time (you need to build with CFG_TEE_CORE_LOG_LEVEL=4 to get the following traces):

# First boot
INFO:    TEE-CORE: OP-TEE version: 2.5.0-dev #8 Thu Aug  3 07:34:41 UTC 2017 aarch64
DEBUG:   [0x0] TEE-CORE:mobj_mapped_shm_init:592: Shared memory address range: f800000, 10c00000
FLOW:    [0x0] TEE-CORE:plat_prng_add_jitter_entropy:98: plat_prng_add_jitter_entropy: 0x3F79
INFO:    TEE-CORE: Initialized

# Second boot
INFO:    TEE-CORE: OP-TEE version: 2.5.0-dev #8 Thu Aug  3 07:34:41 UTC 2017 aarch64
DEBUG:   [0x0] TEE-CORE:mobj_mapped_shm_init:592: Shared memory address range: f800000, 10c00000
FLOW:    [0x0] TEE-CORE:plat_prng_add_jitter_entropy:98: plat_prng_add_jitter_entropy: 0xB8EB
INFO:    TEE-CORE: Initialized

It looks like prng_add_entropy() has no effect on the bytes returned by prng_read(). Weird.

@jforissier jforissier added the bug label Aug 3, 2017
@jforissier
Copy link
Contributor

It seems Fortuna needs to be fed lots of entropy bytes before the output of the first random read will change. See this discussion: https://groups.google.com/forum/#!msg/libtom/yzfarD7k2nA/-7h9zyuuHjcJ.

@d3zd3z
Copy link
Contributor

d3zd3z commented Sep 7, 2017

It may be worth looking at how FreeBSD does the randomness. Their /dev/random device will block initially, until the driver believes it has enough entropy (such as loading a previous state). Then it doesn't block any more.

@matzedav
Copy link
Author

Hi,

what's the status with this bug? It's a very critical point. Without randomness the whole cryptography is pointless.

Should I call the function as many times as described in the google discussion? Or will this be fixed in optee os?

@jbech-linaro
Copy link
Contributor

Hi @xNado ,

We have patches ready basically since this was brought up, we will submit them as a PR probably this week. Reason for delaying is that we have a disclosure process which involves talking to the stakeholders of OP-TEE also. So even though we could and want to submit fixes asap, there are some cases where we do things with the stakeholders before publish everything. But again, we will submit the PR probably this week. Thanks for reaching out and sending a reminder.

jforissier added a commit to jforissier/optee_os that referenced this issue Sep 27, 2017
This commit fixes a vulnerability that affects platforms built with
CFG_WITH_SOFTWARE_PRNG=y. Note however that platforms built with
CFG_WITH_SOFTWARE_PRNG=y *and* CFG_SECURE_TIME_SOURCE_REE=y are still
vulnerable, unless they provide an implementation of
plat_prng_add_jitter_entropy_norpc().

The LibTomCrypt API is not used properly in the current PRNG
initialization code (tee_ltc_prng_init()). We have:

  prng->start();
  prng->ready();
  plat_prng_add_jitter_entropy_norpc();

...and at this point, the PRNG is assumed to be ready to provide random
data through rng->read().

That is broken, because there is no guarantee that the added entropy
will have an immediate effect on the output of rng->read(). In fact, it
usually will NOT. For instance, the default software PRNG used in
OP-TEE (Fortuna) re-seeds its PRNG generator from the entropy pools
only once every ten reads. So we're effectively using an un-seeded
generator for the first ten calls to prng->read(). Practically it means
that the same byte sequences are generated after each boot and, for the
Fortuna PRNG, until the 11th call to the PRNG read function. At the
Internal Core API level, this affects TEE_GenerateRandom() and
TEE_GenerateKey().

The fix is simple: prng->ready() seeds the generator from the pools, so
by moving plat_prng_add_jitter_entropy_norpc() before prng->ready(), we
can ensure that some amount of entropy is used immediately.

Fixes: OP-TEE#1730
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
@jforissier
Copy link
Contributor

Hi @xNado,

Please see #1843.

jforissier added a commit to jforissier/optee_os that referenced this issue Oct 11, 2017
This commit fixes a vulnerability (OP-TEE-2017-0001) that affects
platforms built with CFG_WITH_SOFTWARE_PRNG=y. Note however that
platforms that also set CFG_SECURE_TIME_SOURCE_REE=y are still
vulnerable, unless they provide an implementation of
plat_prng_add_jitter_entropy_norpc().

The LibTomCrypt API is not used properly in the current PRNG
initialization code (tee_ltc_prng_init()). We have:

  prng->start();
  prng->ready();
  plat_prng_add_jitter_entropy_norpc();

...and at this point, the PRNG is assumed to be ready to provide random
data through rng->read().

That is broken, because there is no guarantee that the added entropy
will have an immediate effect on the output of rng->read(). In fact, it
usually will NOT. For instance, the default software PRNG used in
OP-TEE (Fortuna) re-seeds its PRNG generator from the entropy pools
only once every ten reads. So we're effectively using an un-seeded
generator for the first ten calls to prng->read(). Practically it means
that the same byte sequences are generated after each boot and, for the
Fortuna PRNG, until the 11th call to the PRNG read function. At the
Internal Core API level, this affects TEE_GenerateRandom() and
TEE_GenerateKey().

The fix is simple: prng->ready() seeds the generator from the pools, so
by moving plat_prng_add_jitter_entropy_norpc() before prng->ready(), we
can ensure that some amount of entropy is used immediately.

Fixes: OP-TEE#1730
Link: https://op-tee.org/security-advisories
Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Joakim Bech <joakim.bech@linaro.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants