int crypto_get_default_rng(void) { struct crypto_rng *rng; int err; mutex_lock(&crypto_default_rng_lock); if (!crypto_default_rng) { rng = crypto_alloc_rng("stdrng", 0, 0); err = PTR_ERR(rng); if (IS_ERR(rng)) goto unlock; err = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng)); if (err) { crypto_free_rng(rng); goto unlock; } crypto_default_rng = rng; } crypto_default_rng_refcnt++; err = 0; unlock: mutex_unlock(&crypto_default_rng_lock); return err; }
int cryptodev_rng_init(struct rng_data *rdata, const char *alg_name, void *key, size_t keylen) { int ret; rdata->s = crypto_alloc_rng(alg_name, 0, 0); if (unlikely(IS_ERR(rdata->s))) { ddebug(1, "Failed to load transform for %s", alg_name); return -EINVAL; } /* Copy the key from user and set to TFM. */ ret = crypto_rng_reset(rdata->s, key, keylen); if (unlikely(ret)) { ddebug(1, "Seeding failed for %s-%zu.", alg_name, keylen*8); ret = -EINVAL; goto error; } rdata->seedsize = crypto_rng_seedsize(rdata->s); rdata->init = 1; return 0; error: crypto_free_rng(rdata->s); return ret; }
/* * Initialize big_key crypto and RNG algorithms */ static int __init big_key_crypto_init(void) { int ret = -EINVAL; /* init RNG */ big_key_rng = crypto_alloc_rng(big_key_rng_name, 0, 0); if (IS_ERR(big_key_rng)) { big_key_rng = NULL; return -EFAULT; } /* seed RNG */ ret = crypto_rng_reset(big_key_rng, NULL, crypto_rng_seedsize(big_key_rng)); if (ret) goto error; /* init block cipher */ big_key_skcipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(big_key_skcipher)) { big_key_skcipher = NULL; ret = -EFAULT; goto error; } return 0; error: crypto_free_rng(big_key_rng); big_key_rng = NULL; return ret; }
/* * Register key type */ static int __init big_key_init(void) { struct crypto_skcipher *cipher; struct crypto_rng *rng; int ret; rng = crypto_alloc_rng(big_key_rng_name, 0, 0); if (IS_ERR(rng)) { pr_err("Can't alloc rng: %ld\n", PTR_ERR(rng)); return PTR_ERR(rng); } big_key_rng = rng; /* seed RNG */ ret = crypto_rng_reset(rng, NULL, crypto_rng_seedsize(rng)); if (ret) { pr_err("Can't reset rng: %d\n", ret); goto error_rng; } /* init block cipher */ cipher = crypto_alloc_skcipher(big_key_alg_name, 0, CRYPTO_ALG_ASYNC); if (IS_ERR(cipher)) { ret = PTR_ERR(cipher); pr_err("Can't alloc crypto: %d\n", ret); goto error_rng; } big_key_skcipher = cipher; ret = register_key_type(&key_type_big_key); if (ret < 0) { pr_err("Can't register type: %d\n", ret); goto error_cipher; } return 0; error_cipher: crypto_free_skcipher(big_key_skcipher); error_rng: crypto_free_rng(big_key_rng); return ret; }
static long tegra_crypto_dev_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long arg) { struct tegra_crypto_ctx *ctx = filp->private_data; struct tegra_crypt_req crypt_req; struct tegra_rng_req rng_req; struct tegra_sha_req sha_req; struct tegra_rsa_req rsa_req; char *rng; int ret = 0; switch (ioctl_num) { case TEGRA_CRYPTO_IOCTL_NEED_SSK: ctx->use_ssk = (int)arg; break; case TEGRA_CRYPTO_IOCTL_PROCESS_REQ: ret = copy_from_user(&crypt_req, (void __user *)arg, sizeof(crypt_req)); if (ret) { ret = -EFAULT; pr_err("%s: copy_from_user fail(%d)\n", __func__, ret); break; } ret = process_crypt_req(ctx, &crypt_req); break; case TEGRA_CRYPTO_IOCTL_SET_SEED: if (copy_from_user(&rng_req, (void __user *)arg, sizeof(rng_req))) { ret = -EFAULT; pr_err("%s: copy_from_user fail(%d)\n", __func__, ret); return ret; } memcpy(ctx->seed, rng_req.seed, TEGRA_CRYPTO_RNG_SEED_SIZE); if (rng_req.type == RNG_DRBG) ret = crypto_rng_reset(ctx->rng_drbg, ctx->seed, crypto_rng_seedsize(ctx->rng_drbg)); else ret = crypto_rng_reset(ctx->rng, ctx->seed, crypto_rng_seedsize(ctx->rng)); break; case TEGRA_CRYPTO_IOCTL_GET_RANDOM: if (copy_from_user(&rng_req, (void __user *)arg, sizeof(rng_req))) { ret = -EFAULT; pr_err("%s: copy_from_user fail(%d)\n", __func__, ret); return ret; } rng = kzalloc(rng_req.nbytes, GFP_KERNEL); if (!rng) { if (rng_req.type == RNG_DRBG) pr_err("mem alloc for rng_drbg fail"); else pr_err("mem alloc for rng fail"); ret = -ENODATA; goto rng_out; } if (rng_req.type == RNG_DRBG) ret = crypto_rng_get_bytes(ctx->rng_drbg, rng, rng_req.nbytes); else ret = crypto_rng_get_bytes(ctx->rng, rng, rng_req.nbytes); if (ret != rng_req.nbytes) { if (rng_req.type == RNG_DRBG) pr_err("rng_drbg failed"); else pr_err("rng failed"); ret = -ENODATA; goto rng_out; } ret = copy_to_user((void __user *)rng_req.rdata, (const void *)rng, rng_req.nbytes); if (ret) { ret = -EFAULT; pr_err("%s: copy_to_user fail(%d)\n", __func__, ret); return ret; } rng_out: if (rng) kfree(rng); break; case TEGRA_CRYPTO_IOCTL_GET_SHA: if (tegra_get_chipid() != TEGRA_CHIPID_TEGRA2) { if (copy_from_user(&sha_req, (void __user *)arg, sizeof(sha_req))) { ret = -EFAULT; pr_err("%s: copy_from_user fail(%d)\n", __func__, ret); return ret; } ret = tegra_crypto_sha(&sha_req); } else { ret = -EINVAL; } break; case TEGRA_CRYPTO_IOCTL_RSA_REQ: if (copy_from_user(&rsa_req, (void __user *)arg, sizeof(rsa_req))) { ret = -EFAULT; pr_err("%s: copy_from_user fail(%d)\n", __func__, ret); return ret; } ret = tegra_crypt_rsa(ctx, &rsa_req); break; default: pr_debug("invalid ioctl code(%d)", ioctl_num); ret = -EINVAL; } return ret; }