crypto: hw_random - Add new Exynos RNG driver
Krzysztof Kozlowski
maintainerv2 cover crypto: hw_random - Add new Exynos RNG driver
Hi,
This is a follow up of my questions around exynos-rng [1].
Changes since v1:
=================
1. Re-work the code for seeding after system resume, following suggestions and review by Stephan M?ller.
The resume path was not tested.
2. Re-seed itself from time to time (every 100 ms), suggested by Stephan M?ller.
3. Use a define for retries (Bartlomiej Zolnierkiewicz).
4. Add some docs.
Description:
============
The existing exynos-rng has many issues. The most important one is that it is a pseudo RNG device but uses hw_random interface which does not allow proper seeding.
The RNG module on Exynos4 requires seeding. On newer SoCs (like Exynos5420) it can seed itself from a true RNG. Converting the existing driver to use TRNG would effectively drop support for Exynos4 and break compatibility with existing users.
Instead I decided to convert it to crypto API. In the future I hope to add support for seeding from TRNG module.
Tested with app [2].
Patches are independent. I will take the defconfig changes (2/3 and 3/3) through samsung-soc tree.
Best regards,
Krzysztof
[1] https://www.spinics.net/lists/arm-kernel/msg569641.html
[2] https://www.spinics.net/lists/arm-kernel/msg571184.html
Krzysztof Kozlowski (3):
crypto: hw_random - Add new Exynos RNG driver
ARM: exynos_defconfig: Enable Exynos RNG and user-space crypto API
ARM: multi_v7_defconfig: Enable Exynos RNG and user-space crypto API
MAINTAINERS | 8 + arch/arm/configs/exynos_defconfig | 6 + arch/arm/configs/multi_v7_defconfig | 6 + drivers/char/hw_random/Kconfig | 14 -- drivers/char/hw_random/Makefile | 1 - drivers/char/hw_random/exynos-rng.c | 231 --------------------- drivers/crypto/Kconfig | 15 ++ drivers/crypto/Makefile | 1 + drivers/crypto/exynos-rng.c | 392 ++++++++++++++++++++++++++++++++++++ 9 files changed, 428 insertions(+), 246 deletions(-) delete mode 100644 drivers/char/hw_random/exynos-rng.c create mode 100644 drivers/crypto/exynos-rng.c
Signature · 1 line
2.9.3
Krzysztof Kozlowski
maintainerPATCH v2 1/3 crypto: hw_random - Add new Exynos RNG driver
Replace existing hw_ranndom/exynos-rng driver with a new, reworked one. This is a driver for pseudo random number generator block which on Exynos4 chipsets must be seeded with some value. On newer Exynos5420 chipsets it might seed itself from true random number generator block but this is not implemented yet.
New driver is a complete rework to use the crypto ALGAPI instead of hw_random API. Rationale for the change:
1. hw_random interface is for true RNG devices.
2. The old driver was seeding itself with jiffies which is not a reliable source for randomness.
3. Device generates five random numbers in each pass but old driver was returning only one thus its performance was reduced.
Compatibility with DeviceTree bindings is preserved.
New driver does not use runtime power management but manually enables and disables the clock when needed. This is preferred approach because using runtime PM just to toggle clock is huge overhead.
Another difference is reseeding itself with generated random data periodically and during resuming from system suspend (previously driver was re-seeding itself again with jiffies).
---
The resume path is untested as my Odroid U3 fails to go online. Testing on Trats2 or other devices would be appreciated.
--- MAINTAINERS | 8 + drivers/char/hw_random/Kconfig | 14 -- drivers/char/hw_random/Makefile | 1 - drivers/char/hw_random/exynos-rng.c | 231 --------------------- drivers/crypto/Kconfig | 15 ++ drivers/crypto/Makefile | 1 + drivers/crypto/exynos-rng.c | 392 ++++++++++++++++++++++++++++++++++++ 7 files changed, 416 insertions(+), 246 deletions(-) delete mode 100644 drivers/char/hw_random/exynos-rng.c create mode 100644 drivers/crypto/exynos-rng.c
MAINTAINERS +8 -0
@@ -10977,6 +10977,14 @@ L: alsa-devel at alsa-project.org (moderated for non-subscribers) S: Supported F: sound/soc/samsung/ +SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER +M: Krzysztof Kozlowski <[email protected]> +L: linux-crypto at vger.kernel.org +L: linux-samsung-soc at vger.kernel.org +S: Maintained +F: drivers/crypto/exynos-rng.c +F: Documentation/devicetree/bindings/rng/samsung,exynos-rng4.txt + SAMSUNG FRAMEBUFFER DRIVER M: Jingoo Han <[email protected]> L: linux-fbdev at vger.kernel.org
drivers/char/hw_random/Kconfig +0 -14
@@ -294,20 +294,6 @@ config HW_RANDOM_POWERNV If unsure, say Y. -config HW_RANDOM_EXYNOS - tristate "EXYNOS HW random number generator support" - depends on ARCH_EXYNOS || COMPILE_TEST - depends on HAS_IOMEM - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on EXYNOS SOCs. - - To compile this driver as a module, choose M here: the - module will be called exynos-rng. - - If unsure, say Y. - config HW_RANDOM_TPM tristate "TPM HW Random Number Generator support" depends on TCG_TPM
drivers/char/hw_random/Makefile +0 -1
@@ -24,7 +24,6 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o -obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
drivers/char/hw_random/exynos-rng.c deleted +0 -231
231 lines not on this page · raw message
drivers/crypto/Kconfig +15 -0
@@ -388,6 +388,21 @@ config CRYPTO_DEV_MXC_SCC This option enables support for the Security Controller (SCC) found in Freescale i.MX25 chips. +config CRYPTO_DEV_EXYNOS_RNG + tristate "EXYNOS HW pseudo random number generator support" + depends on ARCH_EXYNOS || COMPILE_TEST + depends on HAS_IOMEM + select CRYPTO_RNG + ---help--- + This driver provides kernel-side support through the + cryptographic API for the pseudo random number generator hardware + found on Exynos SoCs. + + To compile this driver as a module, choose M here: the + module will be called exynos-rng. + + If unsure, say Y. + config CRYPTO_DEV_S5P tristate "Support for Samsung S5PV210/Exynos crypto accelerator" depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
drivers/crypto/Makefile +1 -0
@@ -6,6 +6,7 @@ obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += cavium/ obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/ obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/ obj-$(CONFIG_CRYPTO_DEV_CPT) += cavium/cpt/ +obj-$(CONFIG_CRYPTO_DEV_EXYNOS_RNG) += exynos-rng.o obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
drivers/crypto/exynos-rng.c new file +392 -0
392 lines not on this page · raw message
Signature · 1 line
2.9.3
Am Freitag, 24. M?rz 2017, 19:26:04 CET schrieb Krzysztof Kozlowski:
Hi Krzysztof,
Quoted 7 lines
drivers/crypto/exynos-rng.c new file +7
-0+static unsigned int exynos_rng_copy_random (struct exynos_rng_dev *rng, +u8 *dst,unsigned int dlen) +{ +unsigned int cnt =0 ; +int i, j; +u32 val; +
drivers/crypto/exynos-rng.c line 157
Quoted 10 lines
drivers/crypto/exynos-rng.c new file +10
-0+for (j =0 ; j <EXYNOS_RNG_SEED_REGS ; j++) { + val =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j)); + +for (i =0 ; i <4 ; i++) { + dst[cnt] = val &0xff ; + val >>=8 ; +if (++cnt >= dlen) +return cnt; + } + rng->seed_save[j] = val;
Just to clarify: is this call right? Shouldn't that be removed? Any RNG that is given to a caller is tainted and should not serve as seed.
drivers/crypto/exynos-rng.c line 165
Quoted 8 lines
drivers/crypto/exynos-rng.c new file +8
-0+ } + +/* +* Engine filled all output registers, so read the remaining registers +* for storing data as future seed. +*/ +for (; j <EXYNOS_RNG_SEED_REGS ; j++) + rng->seed_save[j] =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j));
With this call, I guess the questioned line above could go away, right?
Ciao
Stephan
Krzysztof Kozlowski
maintainerQuoted 16 lines · Stephan M?ller
Am Freitag, 24. M?rz 2017, 19:26:04 CET schrieb Krzysztof Kozlowski:
Hi Krzysztof,
Quoted 12 lines
drivers/crypto/exynos-rng.c new file +12
-0+static unsigned int exynos_rng_copy_random (struct exynos_rng_dev *rng, +u8 *dst,unsigned int dlen) +{ +unsigned int cnt =0 ; +int i, j; +u32 val; + +for (j =0 ; j <EXYNOS_RNG_SEED_REGS ; j++) { + val =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j)); + +for (i =0 ; i <4 ; i++) { + dst[cnt] = val &0xff ;
Quoted 8 lines
drivers/crypto/exynos-rng.c line 157
Quoted 5 lines
drivers/crypto/exynos-rng.c new file +5
-0+ val >>=8 ; +if (++cnt >= dlen) +return cnt; + } + rng->seed_save[j] = val;Just to clarify: is this call right? Shouldn't that be removed? Any RNG that is given to a caller is tainted and should not serve as seed.
In that case I could either re-use RNGs not passed to the caller (like in the block quoted below) or generate another round of them just for purpose of next seeding.
With the first approach the problem is that I might wait for such unused numbers pretty long. If user is requesting large amount of data, then I will always give him all five output numbers. I will not have unused numbers.
The second approach seems safe, but requires additional engine run which will slow down some of the generate() calls.
Quoted 10 lines
drivers/crypto/exynos-rng.c line 165
Quoted 8 lines
drivers/crypto/exynos-rng.c new file +8
-0+ } + +/* +* Engine filled all output registers, so read the remaining registers +* for storing data as future seed. +*/ +for (; j <EXYNOS_RNG_SEED_REGS ; j++) + rng->seed_save[j] =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j));With this call, I guess the questioned line above could go away, right?
This is used in combination with the previous line so I will get five seeds (for five registers).
Best regards,
Krzysztof
Am Samstag, 25. M?rz 2017, 08:36:48 CET schrieb Krzysztof Kozlowski:
Hi Krzysztof,
Quoted 30 lines · Stephan M?ller
Quoted 16 lines
Am Freitag, 24. M?rz 2017, 19:26:04 CET schrieb Krzysztof Kozlowski:
Hi Krzysztof,
Quoted 12 lines
drivers/crypto/exynos-rng.c new file +12
-0+static unsigned int exynos_rng_copy_random (struct exynos_rng_dev *rng, +u8 *dst,unsigned int dlen) +{ +unsigned int cnt =0 ; +int i, j; +u32 val; + +for (j =0 ; j <EXYNOS_RNG_SEED_REGS ; j++) { + val =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j)); + +for (i =0 ; i <4 ; i++) { + dst[cnt] = val &0xff ;Quoted 8 lines
drivers/crypto/exynos-rng.c line 157
Quoted 5 lines
drivers/crypto/exynos-rng.c new file +5
-0+ val >>=8 ; +if (++cnt >= dlen) +return cnt; + } + rng->seed_save[j] = val;Just to clarify: is this call right? Shouldn't that be removed? Any RNG that is given to a caller is tainted and should not serve as seed.
In that case I could either re-use RNGs not passed to the caller (like in the block quoted below) or generate another round of them just for purpose of next seeding.
Quoted 7 lines
With the first approach the problem is that I might wait for such unused numbers pretty long. If user is requesting large amount of data, then I will always give him all five output numbers. I will not have unused numbers.
The second approach seems safe, but requires additional engine run which will slow down some of the
generate()calls.
Random numbers should never be used twice.
Quoted 12 lines
Quoted 11 lines
drivers/crypto/exynos-rng.c line 165
Quoted 9 lines
drivers/crypto/exynos-rng.c new file +8
-0+ } + +/* +* Engine filled all output registers, so read the remaining registers +* for storing data as future seed. +*/ +for (; j <EXYNOS_RNG_SEED_REGS ; j++) + rng->seed_save[j] =exynos_rng_readl (rng,EXYNOS_RNG_OUT (j));With this call, I guess the questioned line above could go away, right?
Quoted 5 lines
This is used in combination with the previous line so I will get five seeds (for five registers).
Best regards,
Krzysztof
Ciao
Stephan
Krzysztof Kozlowski
maintainerPATCH v2 2/3 ARM: exynos_defconfig: Enable Exynos RNG and user-space crypto API
In reply to Krzysztof KozlowskiEnable the new Exynos pseudo random number generator driver and user-space API to access crypto algorithms and devices (not only RNG).
--- arch/arm/configs/exynos_defconfig | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm/configs/exynos_defconfig +6 -0
@@ -265,6 +265,12 @@ CONFIG_DEBUG_RT_MUTEXES=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_USER=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_USER_API_RNG=m +CONFIG_CRYPTO_USER_API_AEAD=m +CONFIG_CRYPTO_DEV_EXYNOS_RNG=y CONFIG_CRYPTO_DEV_S5P=y CONFIG_ARM_CRYPTO=y CONFIG_CRYPTO_SHA1_ARM_NEON=m
Signature · 1 line
2.9.3
Krzysztof Kozlowski
maintainerPATCH v2 3/3 ARM: multi_v7_defconfig: Enable Exynos RNG and user-space crypto API
In reply to Krzysztof KozlowskiEnable the new Exynos pseudo random number generator driver and user-space API to access crypto algorithms and devices (not only RNG).
--- arch/arm/configs/multi_v7_defconfig | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm/configs/multi_v7_defconfig +6 -0
@@ -935,7 +935,13 @@ CONFIG_CPUFREQ_DT=y CONFIG_KEYSTONE_IRQ=y CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_ST=y +CONFIG_CRYPTO_USER=m +CONFIG_CRYPTO_USER_API_HASH=m +CONFIG_CRYPTO_USER_API_SKCIPHER=m +CONFIG_CRYPTO_USER_API_RNG=m +CONFIG_CRYPTO_USER_API_AEAD=m CONFIG_CRYPTO_DEV_MARVELL_CESA=m +CONFIG_CRYPTO_DEV_EXYNOS_RNG=m CONFIG_CRYPTO_DEV_S5P=m CONFIG_CRYPTO_DEV_SUN4I_SS=m CONFIG_CRYPTO_DEV_ROCKCHIP=m
Signature · 1 line
2.9.3