Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: sun4i-ss - support the Security System PRNG

The Security System has a PRNG, this patch adds support for it via
crypto_rng.

Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Corentin LABBE and committed by
Herbert Xu
b8ae5c73 3822c331

+106
+8
drivers/crypto/Kconfig
··· 616 616 To compile this driver as a module, choose M here: the module 617 617 will be called sun4i-ss. 618 618 619 + config CRYPTO_DEV_SUN4I_SS_PRNG 620 + bool "Support for Allwinner Security System PRNG" 621 + depends on CRYPTO_DEV_SUN4I_SS 622 + select CRYPTO_RNG 623 + help 624 + Select this option if you want to provide kernel-side support for 625 + the Pseudo-Random Number Generator found in the Security System. 626 + 619 627 config CRYPTO_DEV_ROCKCHIP 620 628 tristate "Rockchip's Cryptographic Engine driver" 621 629 depends on OF && ARCH_ROCKCHIP
+1
drivers/crypto/sunxi-ss/Makefile
··· 1 1 obj-$(CONFIG_CRYPTO_DEV_SUN4I_SS) += sun4i-ss.o 2 2 sun4i-ss-y += sun4i-ss-core.o sun4i-ss-hash.o sun4i-ss-cipher.o 3 + sun4i-ss-$(CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG) += sun4i-ss-prng.o
+30
drivers/crypto/sunxi-ss/sun4i-ss-core.c
··· 213 213 } 214 214 } 215 215 }, 216 + #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG 217 + { 218 + .type = CRYPTO_ALG_TYPE_RNG, 219 + .alg.rng = { 220 + .base = { 221 + .cra_name = "stdrng", 222 + .cra_driver_name = "sun4i_ss_rng", 223 + .cra_priority = 300, 224 + .cra_ctxsize = 0, 225 + .cra_module = THIS_MODULE, 226 + }, 227 + .generate = sun4i_ss_prng_generate, 228 + .seed = sun4i_ss_prng_seed, 229 + .seedsize = SS_SEED_LEN / BITS_PER_BYTE, 230 + } 231 + }, 232 + #endif 216 233 }; 217 234 218 235 static int sun4i_ss_probe(struct platform_device *pdev) ··· 372 355 goto error_alg; 373 356 } 374 357 break; 358 + case CRYPTO_ALG_TYPE_RNG: 359 + err = crypto_register_rng(&ss_algs[i].alg.rng); 360 + if (err) { 361 + dev_err(ss->dev, "Fail to register %s\n", 362 + ss_algs[i].alg.rng.base.cra_name); 363 + } 364 + break; 375 365 } 376 366 } 377 367 platform_set_drvdata(pdev, ss); ··· 392 368 break; 393 369 case CRYPTO_ALG_TYPE_AHASH: 394 370 crypto_unregister_ahash(&ss_algs[i].alg.hash); 371 + break; 372 + case CRYPTO_ALG_TYPE_RNG: 373 + crypto_unregister_rng(&ss_algs[i].alg.rng); 395 374 break; 396 375 } 397 376 } ··· 419 392 break; 420 393 case CRYPTO_ALG_TYPE_AHASH: 421 394 crypto_unregister_ahash(&ss_algs[i].alg.hash); 395 + break; 396 + case CRYPTO_ALG_TYPE_RNG: 397 + crypto_unregister_rng(&ss_algs[i].alg.rng); 422 398 break; 423 399 } 424 400 }
+56
drivers/crypto/sunxi-ss/sun4i-ss-prng.c
··· 1 + #include "sun4i-ss.h" 2 + 3 + int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, 4 + unsigned int slen) 5 + { 6 + struct sun4i_ss_alg_template *algt; 7 + struct rng_alg *alg = crypto_rng_alg(tfm); 8 + 9 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); 10 + memcpy(algt->ss->seed, seed, slen); 11 + 12 + return 0; 13 + } 14 + 15 + int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, 16 + unsigned int slen, u8 *dst, unsigned int dlen) 17 + { 18 + struct sun4i_ss_alg_template *algt; 19 + struct rng_alg *alg = crypto_rng_alg(tfm); 20 + int i; 21 + u32 v; 22 + u32 *data = (u32 *)dst; 23 + const u32 mode = SS_OP_PRNG | SS_PRNG_CONTINUE | SS_ENABLED; 24 + size_t len; 25 + struct sun4i_ss_ctx *ss; 26 + unsigned int todo = (dlen / 4) * 4; 27 + 28 + algt = container_of(alg, struct sun4i_ss_alg_template, alg.rng); 29 + ss = algt->ss; 30 + 31 + spin_lock(&ss->slock); 32 + 33 + writel(mode, ss->base + SS_CTL); 34 + 35 + while (todo > 0) { 36 + /* write the seed */ 37 + for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) 38 + writel(ss->seed[i], ss->base + SS_KEY0 + i * 4); 39 + 40 + /* Read the random data */ 41 + len = min_t(size_t, SS_DATA_LEN / BITS_PER_BYTE, todo); 42 + readsl(ss->base + SS_TXFIFO, data, len / 4); 43 + data += len / 4; 44 + todo -= len; 45 + 46 + /* Update the seed */ 47 + for (i = 0; i < SS_SEED_LEN / BITS_PER_LONG; i++) { 48 + v = readl(ss->base + SS_KEY0 + i * 4); 49 + ss->seed[i] = v; 50 + } 51 + } 52 + 53 + writel(0, ss->base + SS_CTL); 54 + spin_unlock(&ss->slock); 55 + return dlen; 56 + }
+11
drivers/crypto/sunxi-ss/sun4i-ss.h
··· 32 32 #include <crypto/aes.h> 33 33 #include <crypto/des.h> 34 34 #include <crypto/internal/rng.h> 35 + #include <crypto/rng.h> 35 36 36 37 #define SS_CTL 0x00 37 38 #define SS_KEY0 0x04 ··· 128 127 #define SS_RXFIFO_EMP_INT_ENABLE (1 << 2) 129 128 #define SS_TXFIFO_AVA_INT_ENABLE (1 << 0) 130 129 130 + #define SS_SEED_LEN 192 131 + #define SS_DATA_LEN 160 132 + 131 133 struct sun4i_ss_ctx { 132 134 void __iomem *base; 133 135 int irq; ··· 140 136 struct device *dev; 141 137 struct resource *res; 142 138 spinlock_t slock; /* control the use of the device */ 139 + #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG 140 + u32 seed[SS_SEED_LEN / BITS_PER_LONG]; 141 + #endif 143 142 }; 144 143 145 144 struct sun4i_ss_alg_template { ··· 151 144 union { 152 145 struct skcipher_alg crypto; 153 146 struct ahash_alg hash; 147 + struct rng_alg rng; 154 148 } alg; 155 149 struct sun4i_ss_ctx *ss; 156 150 }; ··· 209 201 unsigned int keylen); 210 202 int sun4i_ss_des3_setkey(struct crypto_skcipher *tfm, const u8 *key, 211 203 unsigned int keylen); 204 + int sun4i_ss_prng_generate(struct crypto_rng *tfm, const u8 *src, 205 + unsigned int slen, u8 *dst, unsigned int dlen); 206 + int sun4i_ss_prng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen);