You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
Pull crypto update from Herbert Xu:
"API:
- Crypto self tests can now be disabled at boot/run time.
- Add async support to algif_aead.
Algorithms:
- A large number of fixes to MPI from Nicolai Stange.
- Performance improvement for HMAC DRBG.
Drivers:
- Use generic crypto engine in omap-des.
- Merge ppc4xx-rng and crypto4xx drivers.
- Fix lockups in sun4i-ss driver by disabling IRQs.
- Add DMA engine support to ccp.
- Reenable talitos hash algorithms.
- Add support for Hisilicon SoC RNG.
- Add basic crypto driver for the MXC SCC.
Others:
- Do not allocate crypto hash tfm in NORECLAIM context in ecryptfs"
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (77 commits)
crypto: qat - change the adf_ctl_stop_devices to void
crypto: caam - fix caam_jr_alloc() ret code
crypto: vmx - comply with ABIs that specify vrsave as reserved.
crypto: testmgr - Add a flag allowing the self-tests to be disabled at runtime.
crypto: ccp - constify ccp_actions structure
crypto: marvell/cesa - Use dma_pool_zalloc
crypto: qat - make adf_vf_isr.c dependant on IOV config
crypto: qat - Fix typo in comments
lib: asn1_decoder - add MODULE_LICENSE("GPL")
crypto: omap-sham - Use dma_request_chan() for requesting DMA channel
crypto: omap-des - Use dma_request_chan() for requesting DMA channel
crypto: omap-aes - Use dma_request_chan() for requesting DMA channel
crypto: omap-des - Integrate with the crypto engine framework
crypto: s5p-sss - fix incorrect usage of scatterlists api
crypto: s5p-sss - Fix missed interrupts when working with 8 kB blocks
crypto: s5p-sss - Use common BIT macro
crypto: mxc-scc - fix unwinding in mxc_scc_crypto_register()
crypto: mxc-scc - signedness bugs in mxc_scc_ablkcipher_req_init()
crypto: talitos - fix ahash algorithms registration
crypto: ccp - Ensure all dependencies are specified
...
This commit is contained in:
@@ -1936,9 +1936,9 @@ static int test_skcipher(void)
|
||||
}
|
||||
|
||||
req = skcipher_request_alloc(skcipher, GFP_KERNEL);
|
||||
if (IS_ERR(req)) {
|
||||
pr_info("could not allocate request queue\n");
|
||||
ret = PTR_ERR(req);
|
||||
if (!req) {
|
||||
pr_info("could not allocate skcipher request\n");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
Freescale Security Controller (SCC)
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "fsl,imx25-scc".
|
||||
- reg : Should contain register location and length.
|
||||
- interrupts : Should contain interrupt numbers for SCM IRQ and SMN IRQ.
|
||||
- interrupt-names : Should specify the names "scm" and "smn" for the
|
||||
SCM IRQ and SMN IRQ.
|
||||
- clocks: Should contain the clock driving the SCC core.
|
||||
- clock-names: Should be set to "ipg".
|
||||
|
||||
Example:
|
||||
|
||||
scc: crypto@53fac000 {
|
||||
compatible = "fsl,imx25-scc";
|
||||
reg = <0x53fac000 0x4000>;
|
||||
clocks = <&clks 111>;
|
||||
clock-names = "ipg";
|
||||
interrupts = <49>, <50>;
|
||||
interrupt-names = "scm", "smn";
|
||||
};
|
||||
@@ -23,10 +23,8 @@ Required properties:
|
||||
- "samsung,exynos4210-secss" for Exynos4210, Exynos4212, Exynos4412, Exynos5250,
|
||||
Exynos5260 and Exynos5420 SoCs.
|
||||
- reg : Offset and length of the register set for the module
|
||||
- interrupts : interrupt specifiers of SSS module interrupts, should contain
|
||||
following entries:
|
||||
- first : feed control interrupt (required for all variants),
|
||||
- second : hash interrupt (required only for samsung,s5pv210-secss).
|
||||
- interrupts : interrupt specifiers of SSS module interrupts (one feed
|
||||
control interrupt).
|
||||
|
||||
- clocks : list of clock phandle and specifier pairs for all clocks listed in
|
||||
clock-names property.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Hisilicon Random Number Generator
|
||||
|
||||
Required properties:
|
||||
- compatible : Should be "hisilicon,hip04-rng" or "hisilicon,hip05-rng"
|
||||
- reg : Offset and length of the register set of this block
|
||||
|
||||
Example:
|
||||
|
||||
rng@d1010000 {
|
||||
compatible = "hisilicon,hip05-rng";
|
||||
reg = <0xd1010000 0x100>;
|
||||
};
|
||||
@@ -838,6 +838,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
It will be ignored when crashkernel=X,high is not used
|
||||
or memory reserved is below 4G.
|
||||
|
||||
cryptomgr.notests
|
||||
[KNL] Disable crypto self-tests
|
||||
|
||||
cs89x0_dma= [HW,NET]
|
||||
Format: <dma>
|
||||
|
||||
|
||||
@@ -627,6 +627,7 @@ F: include/linux/altera_jtaguart.h
|
||||
|
||||
AMD CRYPTOGRAPHIC COPROCESSOR (CCP) DRIVER
|
||||
M: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
M: Gary Hook <gary.hook@amd.com>
|
||||
L: linux-crypto@vger.kernel.org
|
||||
S: Supported
|
||||
F: drivers/crypto/ccp/
|
||||
|
||||
@@ -420,6 +420,15 @@
|
||||
interrupts = <41>;
|
||||
};
|
||||
|
||||
scc: crypto@53fac000 {
|
||||
compatible = "fsl,imx25-scc";
|
||||
reg = <0x53fac000 0x4000>;
|
||||
clocks = <&clks 111>;
|
||||
clock-names = "ipg";
|
||||
interrupts = <49>, <50>;
|
||||
interrupt-names = "scm", "smn";
|
||||
};
|
||||
|
||||
esdhc1: esdhc@53fb4000 {
|
||||
compatible = "fsl,imx25-esdhc";
|
||||
reg = <0x53fb4000 0x4000>;
|
||||
|
||||
+237
-31
@@ -13,7 +13,7 @@
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include <crypto/aead.h>
|
||||
#include <crypto/internal/aead.h>
|
||||
#include <crypto/scatterwalk.h>
|
||||
#include <crypto/if_alg.h>
|
||||
#include <linux/init.h>
|
||||
@@ -29,15 +29,24 @@ struct aead_sg_list {
|
||||
struct scatterlist sg[ALG_MAX_PAGES];
|
||||
};
|
||||
|
||||
struct aead_async_rsgl {
|
||||
struct af_alg_sgl sgl;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct aead_async_req {
|
||||
struct scatterlist *tsgl;
|
||||
struct aead_async_rsgl first_rsgl;
|
||||
struct list_head list;
|
||||
struct kiocb *iocb;
|
||||
unsigned int tsgls;
|
||||
char iv[];
|
||||
};
|
||||
|
||||
struct aead_ctx {
|
||||
struct aead_sg_list tsgl;
|
||||
/*
|
||||
* RSGL_MAX_ENTRIES is an artificial limit where user space at maximum
|
||||
* can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES
|
||||
* pages
|
||||
*/
|
||||
#define RSGL_MAX_ENTRIES ALG_MAX_PAGES
|
||||
struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES];
|
||||
struct aead_async_rsgl first_rsgl;
|
||||
struct list_head list;
|
||||
|
||||
void *iv;
|
||||
|
||||
@@ -75,6 +84,17 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx)
|
||||
return ctx->used >= ctx->aead_assoclen + as;
|
||||
}
|
||||
|
||||
static void aead_reset_ctx(struct aead_ctx *ctx)
|
||||
{
|
||||
struct aead_sg_list *sgl = &ctx->tsgl;
|
||||
|
||||
sg_init_table(sgl->sg, ALG_MAX_PAGES);
|
||||
sgl->cur = 0;
|
||||
ctx->used = 0;
|
||||
ctx->more = 0;
|
||||
ctx->merge = 0;
|
||||
}
|
||||
|
||||
static void aead_put_sgl(struct sock *sk)
|
||||
{
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
@@ -90,11 +110,7 @@ static void aead_put_sgl(struct sock *sk)
|
||||
put_page(sg_page(sg + i));
|
||||
sg_assign_page(sg + i, NULL);
|
||||
}
|
||||
sg_init_table(sg, ALG_MAX_PAGES);
|
||||
sgl->cur = 0;
|
||||
ctx->used = 0;
|
||||
ctx->more = 0;
|
||||
ctx->merge = 0;
|
||||
aead_reset_ctx(ctx);
|
||||
}
|
||||
|
||||
static void aead_wmem_wakeup(struct sock *sk)
|
||||
@@ -349,23 +365,188 @@ unlock:
|
||||
return err ?: size;
|
||||
}
|
||||
|
||||
static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags)
|
||||
#define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \
|
||||
((char *)req + sizeof(struct aead_request) + \
|
||||
crypto_aead_reqsize(tfm))
|
||||
|
||||
#define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \
|
||||
crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \
|
||||
sizeof(struct aead_request)
|
||||
|
||||
static void aead_async_cb(struct crypto_async_request *_req, int err)
|
||||
{
|
||||
struct sock *sk = _req->data;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct aead_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
|
||||
struct aead_request *req = aead_request_cast(_req);
|
||||
struct aead_async_req *areq = GET_ASYM_REQ(req, tfm);
|
||||
struct scatterlist *sg = areq->tsgl;
|
||||
struct aead_async_rsgl *rsgl;
|
||||
struct kiocb *iocb = areq->iocb;
|
||||
unsigned int i, reqlen = GET_REQ_SIZE(tfm);
|
||||
|
||||
list_for_each_entry(rsgl, &areq->list, list) {
|
||||
af_alg_free_sg(&rsgl->sgl);
|
||||
if (rsgl != &areq->first_rsgl)
|
||||
sock_kfree_s(sk, rsgl, sizeof(*rsgl));
|
||||
}
|
||||
|
||||
for (i = 0; i < areq->tsgls; i++)
|
||||
put_page(sg_page(sg + i));
|
||||
|
||||
sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
|
||||
sock_kfree_s(sk, req, reqlen);
|
||||
__sock_put(sk);
|
||||
iocb->ki_complete(iocb, err, err);
|
||||
}
|
||||
|
||||
static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg,
|
||||
int flags)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct aead_ctx *ctx = ask->private;
|
||||
struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req);
|
||||
struct aead_async_req *areq;
|
||||
struct aead_request *req = NULL;
|
||||
struct aead_sg_list *sgl = &ctx->tsgl;
|
||||
struct aead_async_rsgl *last_rsgl = NULL, *rsgl;
|
||||
unsigned int as = crypto_aead_authsize(tfm);
|
||||
unsigned int i, reqlen = GET_REQ_SIZE(tfm);
|
||||
int err = -ENOMEM;
|
||||
unsigned long used;
|
||||
size_t outlen;
|
||||
size_t usedpages = 0;
|
||||
|
||||
lock_sock(sk);
|
||||
if (ctx->more) {
|
||||
err = aead_wait_for_data(sk, flags);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
used = ctx->used;
|
||||
outlen = used;
|
||||
|
||||
if (!aead_sufficient_data(ctx))
|
||||
goto unlock;
|
||||
|
||||
req = sock_kmalloc(sk, reqlen, GFP_KERNEL);
|
||||
if (unlikely(!req))
|
||||
goto unlock;
|
||||
|
||||
areq = GET_ASYM_REQ(req, tfm);
|
||||
memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl));
|
||||
INIT_LIST_HEAD(&areq->list);
|
||||
areq->iocb = msg->msg_iocb;
|
||||
memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm));
|
||||
aead_request_set_tfm(req, tfm);
|
||||
aead_request_set_ad(req, ctx->aead_assoclen);
|
||||
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||
aead_async_cb, sk);
|
||||
used -= ctx->aead_assoclen + (ctx->enc ? as : 0);
|
||||
|
||||
/* take over all tx sgls from ctx */
|
||||
areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur,
|
||||
GFP_KERNEL);
|
||||
if (unlikely(!areq->tsgl))
|
||||
goto free;
|
||||
|
||||
sg_init_table(areq->tsgl, sgl->cur);
|
||||
for (i = 0; i < sgl->cur; i++)
|
||||
sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]),
|
||||
sgl->sg[i].length, sgl->sg[i].offset);
|
||||
|
||||
areq->tsgls = sgl->cur;
|
||||
|
||||
/* create rx sgls */
|
||||
while (iov_iter_count(&msg->msg_iter)) {
|
||||
size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
|
||||
(outlen - usedpages));
|
||||
|
||||
if (list_empty(&areq->list)) {
|
||||
rsgl = &areq->first_rsgl;
|
||||
|
||||
} else {
|
||||
rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
|
||||
if (unlikely(!rsgl)) {
|
||||
err = -ENOMEM;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
rsgl->sgl.npages = 0;
|
||||
list_add_tail(&rsgl->list, &areq->list);
|
||||
|
||||
/* make one iovec available as scatterlist */
|
||||
err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
|
||||
if (err < 0)
|
||||
goto free;
|
||||
|
||||
usedpages += err;
|
||||
|
||||
/* chain the new scatterlist with previous one */
|
||||
if (last_rsgl)
|
||||
af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
|
||||
|
||||
last_rsgl = rsgl;
|
||||
|
||||
/* we do not need more iovecs as we have sufficient memory */
|
||||
if (outlen <= usedpages)
|
||||
break;
|
||||
|
||||
iov_iter_advance(&msg->msg_iter, err);
|
||||
}
|
||||
err = -EINVAL;
|
||||
/* ensure output buffer is sufficiently large */
|
||||
if (usedpages < outlen)
|
||||
goto free;
|
||||
|
||||
aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used,
|
||||
areq->iv);
|
||||
err = ctx->enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req);
|
||||
if (err) {
|
||||
if (err == -EINPROGRESS) {
|
||||
sock_hold(sk);
|
||||
err = -EIOCBQUEUED;
|
||||
aead_reset_ctx(ctx);
|
||||
goto unlock;
|
||||
} else if (err == -EBADMSG) {
|
||||
aead_put_sgl(sk);
|
||||
}
|
||||
goto free;
|
||||
}
|
||||
aead_put_sgl(sk);
|
||||
|
||||
free:
|
||||
list_for_each_entry(rsgl, &areq->list, list) {
|
||||
af_alg_free_sg(&rsgl->sgl);
|
||||
if (rsgl != &areq->first_rsgl)
|
||||
sock_kfree_s(sk, rsgl, sizeof(*rsgl));
|
||||
}
|
||||
if (areq->tsgl)
|
||||
sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls);
|
||||
if (req)
|
||||
sock_kfree_s(sk, req, reqlen);
|
||||
unlock:
|
||||
aead_wmem_wakeup(sk);
|
||||
release_sock(sk);
|
||||
return err ? err : outlen;
|
||||
}
|
||||
|
||||
static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
struct aead_ctx *ctx = ask->private;
|
||||
unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req));
|
||||
struct aead_sg_list *sgl = &ctx->tsgl;
|
||||
unsigned int i = 0;
|
||||
struct aead_async_rsgl *last_rsgl = NULL;
|
||||
struct aead_async_rsgl *rsgl, *tmp;
|
||||
int err = -EINVAL;
|
||||
unsigned long used = 0;
|
||||
size_t outlen = 0;
|
||||
size_t usedpages = 0;
|
||||
unsigned int cnt = 0;
|
||||
|
||||
/* Limit number of IOV blocks to be accessed below */
|
||||
if (msg->msg_iter.nr_segs > RSGL_MAX_ENTRIES)
|
||||
return -ENOMSG;
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
@@ -417,21 +598,33 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
|
||||
size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter),
|
||||
(outlen - usedpages));
|
||||
|
||||
if (list_empty(&ctx->list)) {
|
||||
rsgl = &ctx->first_rsgl;
|
||||
} else {
|
||||
rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL);
|
||||
if (unlikely(!rsgl)) {
|
||||
err = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
rsgl->sgl.npages = 0;
|
||||
list_add_tail(&rsgl->list, &ctx->list);
|
||||
|
||||
/* make one iovec available as scatterlist */
|
||||
err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter,
|
||||
seglen);
|
||||
err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen);
|
||||
if (err < 0)
|
||||
goto unlock;
|
||||
usedpages += err;
|
||||
/* chain the new scatterlist with previous one */
|
||||
if (cnt)
|
||||
af_alg_link_sg(&ctx->rsgl[cnt-1], &ctx->rsgl[cnt]);
|
||||
if (last_rsgl)
|
||||
af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl);
|
||||
|
||||
last_rsgl = rsgl;
|
||||
|
||||
/* we do not need more iovecs as we have sufficient memory */
|
||||
if (outlen <= usedpages)
|
||||
break;
|
||||
iov_iter_advance(&msg->msg_iter, err);
|
||||
cnt++;
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
@@ -440,8 +633,7 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
|
||||
goto unlock;
|
||||
|
||||
sg_mark_end(sgl->sg + sgl->cur - 1);
|
||||
|
||||
aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg,
|
||||
aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg,
|
||||
used, ctx->iv);
|
||||
aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen);
|
||||
|
||||
@@ -454,23 +646,35 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
|
||||
/* EBADMSG implies a valid cipher operation took place */
|
||||
if (err == -EBADMSG)
|
||||
aead_put_sgl(sk);
|
||||
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
aead_put_sgl(sk);
|
||||
|
||||
err = 0;
|
||||
|
||||
unlock:
|
||||
for (i = 0; i < cnt; i++)
|
||||
af_alg_free_sg(&ctx->rsgl[i]);
|
||||
|
||||
list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) {
|
||||
af_alg_free_sg(&rsgl->sgl);
|
||||
if (rsgl != &ctx->first_rsgl)
|
||||
sock_kfree_s(sk, rsgl, sizeof(*rsgl));
|
||||
list_del(&rsgl->list);
|
||||
}
|
||||
INIT_LIST_HEAD(&ctx->list);
|
||||
aead_wmem_wakeup(sk);
|
||||
release_sock(sk);
|
||||
|
||||
return err ? err : outlen;
|
||||
}
|
||||
|
||||
static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored,
|
||||
int flags)
|
||||
{
|
||||
return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ?
|
||||
aead_recvmsg_async(sock, msg, flags) :
|
||||
aead_recvmsg_sync(sock, msg, flags);
|
||||
}
|
||||
|
||||
static unsigned int aead_poll(struct file *file, struct socket *sock,
|
||||
poll_table *wait)
|
||||
{
|
||||
@@ -540,6 +744,7 @@ static void aead_sock_destruct(struct sock *sk)
|
||||
unsigned int ivlen = crypto_aead_ivsize(
|
||||
crypto_aead_reqtfm(&ctx->aead_req));
|
||||
|
||||
WARN_ON(atomic_read(&sk->sk_refcnt) != 0);
|
||||
aead_put_sgl(sk);
|
||||
sock_kzfree_s(sk, ctx->iv, ivlen);
|
||||
sock_kfree_s(sk, ctx, ctx->len);
|
||||
@@ -574,6 +779,7 @@ static int aead_accept_parent(void *private, struct sock *sk)
|
||||
ctx->aead_assoclen = 0;
|
||||
af_alg_init_completion(&ctx->completion);
|
||||
sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES);
|
||||
INIT_LIST_HEAD(&ctx->list);
|
||||
|
||||
ask->private = ctx;
|
||||
|
||||
|
||||
@@ -237,6 +237,7 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
|
||||
break;
|
||||
case OID_sha224:
|
||||
ctx->sinfo->sig.hash_algo = "sha224";
|
||||
break;
|
||||
default:
|
||||
printk("Unsupported digest algo: %u\n", ctx->last_oid);
|
||||
return -ENOPKG;
|
||||
|
||||
+25
-14
@@ -592,8 +592,10 @@ static const struct drbg_state_ops drbg_ctr_ops = {
|
||||
******************************************************************/
|
||||
|
||||
#if defined(CONFIG_CRYPTO_DRBG_HASH) || defined(CONFIG_CRYPTO_DRBG_HMAC)
|
||||
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
||||
unsigned char *outval, const struct list_head *in);
|
||||
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
|
||||
const struct list_head *in);
|
||||
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
|
||||
const unsigned char *key);
|
||||
static int drbg_init_hash_kernel(struct drbg_state *drbg);
|
||||
static int drbg_fini_hash_kernel(struct drbg_state *drbg);
|
||||
#endif /* (CONFIG_CRYPTO_DRBG_HASH || CONFIG_CRYPTO_DRBG_HMAC) */
|
||||
@@ -619,9 +621,11 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
|
||||
LIST_HEAD(seedlist);
|
||||
LIST_HEAD(vdatalist);
|
||||
|
||||
if (!reseed)
|
||||
if (!reseed) {
|
||||
/* 10.1.2.3 step 2 -- memset(0) of C is implicit with kzalloc */
|
||||
memset(drbg->V, 1, drbg_statelen(drbg));
|
||||
drbg_kcapi_hmacsetkey(drbg, drbg->C);
|
||||
}
|
||||
|
||||
drbg_string_fill(&seed1, drbg->V, drbg_statelen(drbg));
|
||||
list_add_tail(&seed1.list, &seedlist);
|
||||
@@ -641,12 +645,13 @@ static int drbg_hmac_update(struct drbg_state *drbg, struct list_head *seed,
|
||||
prefix = DRBG_PREFIX1;
|
||||
/* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */
|
||||
seed2.buf = &prefix;
|
||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->C, &seedlist);
|
||||
ret = drbg_kcapi_hash(drbg, drbg->C, &seedlist);
|
||||
if (ret)
|
||||
return ret;
|
||||
drbg_kcapi_hmacsetkey(drbg, drbg->C);
|
||||
|
||||
/* 10.1.2.2 step 2 and 5 -- HMAC for V */
|
||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &vdatalist);
|
||||
ret = drbg_kcapi_hash(drbg, drbg->V, &vdatalist);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -681,7 +686,7 @@ static int drbg_hmac_generate(struct drbg_state *drbg,
|
||||
while (len < buflen) {
|
||||
unsigned int outlen = 0;
|
||||
/* 10.1.2.5 step 4.1 */
|
||||
ret = drbg_kcapi_hash(drbg, drbg->C, drbg->V, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, drbg->V, &datalist);
|
||||
if (ret)
|
||||
return ret;
|
||||
outlen = (drbg_blocklen(drbg) < (buflen - len)) ?
|
||||
@@ -796,7 +801,7 @@ static int drbg_hash_df(struct drbg_state *drbg,
|
||||
while (len < outlen) {
|
||||
short blocklen = 0;
|
||||
/* 10.4.1 step 4.1 */
|
||||
ret = drbg_kcapi_hash(drbg, NULL, tmp, entropylist);
|
||||
ret = drbg_kcapi_hash(drbg, tmp, entropylist);
|
||||
if (ret)
|
||||
goto out;
|
||||
/* 10.4.1 step 4.2 */
|
||||
@@ -874,7 +879,7 @@ static int drbg_hash_process_addtl(struct drbg_state *drbg,
|
||||
list_add_tail(&data1.list, &datalist);
|
||||
list_add_tail(&data2.list, &datalist);
|
||||
list_splice_tail(addtl, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -907,7 +912,7 @@ static int drbg_hash_hashgen(struct drbg_state *drbg,
|
||||
while (len < buflen) {
|
||||
unsigned int outlen = 0;
|
||||
/* 10.1.1.4 step hashgen 4.1 */
|
||||
ret = drbg_kcapi_hash(drbg, NULL, dst, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, dst, &datalist);
|
||||
if (ret) {
|
||||
len = ret;
|
||||
goto out;
|
||||
@@ -956,7 +961,7 @@ static int drbg_hash_generate(struct drbg_state *drbg,
|
||||
list_add_tail(&data1.list, &datalist);
|
||||
drbg_string_fill(&data2, drbg->V, drbg_statelen(drbg));
|
||||
list_add_tail(&data2.list, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, NULL, drbg->scratchpad, &datalist);
|
||||
ret = drbg_kcapi_hash(drbg, drbg->scratchpad, &datalist);
|
||||
if (ret) {
|
||||
len = ret;
|
||||
goto out;
|
||||
@@ -1600,14 +1605,20 @@ static int drbg_fini_hash_kernel(struct drbg_state *drbg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drbg_kcapi_hash(struct drbg_state *drbg, const unsigned char *key,
|
||||
unsigned char *outval, const struct list_head *in)
|
||||
static void drbg_kcapi_hmacsetkey(struct drbg_state *drbg,
|
||||
const unsigned char *key)
|
||||
{
|
||||
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
||||
|
||||
crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
|
||||
}
|
||||
|
||||
static int drbg_kcapi_hash(struct drbg_state *drbg, unsigned char *outval,
|
||||
const struct list_head *in)
|
||||
{
|
||||
struct sdesc *sdesc = (struct sdesc *)drbg->priv_data;
|
||||
struct drbg_string *input = NULL;
|
||||
|
||||
if (key)
|
||||
crypto_shash_setkey(sdesc->shash.tfm, key, drbg_statelen(drbg));
|
||||
crypto_shash_init(&sdesc->shash);
|
||||
list_for_each_entry(input, in, list)
|
||||
crypto_shash_update(&sdesc->shash, input->buf, input->len);
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ static int lzo_init(struct crypto_tfm *tfm)
|
||||
struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
|
||||
|
||||
ctx->lzo_comp_mem = kmalloc(LZO1X_MEM_COMPRESS,
|
||||
GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!ctx->lzo_comp_mem)
|
||||
ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
|
||||
if (!ctx->lzo_comp_mem)
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
static bool notests;
|
||||
module_param(notests, bool, 0644);
|
||||
MODULE_PARM_DESC(notests, "disable crypto self-tests");
|
||||
|
||||
#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTS
|
||||
|
||||
/* a perfect nop */
|
||||
@@ -3885,6 +3889,11 @@ int alg_test(const char *driver, const char *alg, u32 type, u32 mask)
|
||||
int j;
|
||||
int rc;
|
||||
|
||||
if (!fips_enabled && notests) {
|
||||
printk_once(KERN_INFO "alg: self-tests disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
alg_test_descs_check_order();
|
||||
|
||||
if ((type & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_CIPHER) {
|
||||
|
||||
@@ -268,19 +268,6 @@ config HW_RANDOM_NOMADIK
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_PPC4XX
|
||||
tristate "PowerPC 4xx generic true random number generator support"
|
||||
depends on PPC && 4xx
|
||||
default HW_RANDOM
|
||||
---help---
|
||||
This driver provides the kernel-side support for the TRNG hardware
|
||||
found in the security function of some PowerPC 4xx SoCs.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ppc4xx-rng.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config HW_RANDOM_PSERIES
|
||||
tristate "pSeries HW Random Number Generator support"
|
||||
depends on PPC64 && IBMVIO
|
||||
@@ -309,7 +296,8 @@ config HW_RANDOM_POWERNV
|
||||
|
||||
config HW_RANDOM_EXYNOS
|
||||
tristate "EXYNOS HW random number generator support"
|
||||
depends on ARCH_EXYNOS
|
||||
depends on ARCH_EXYNOS || COMPILE_TEST
|
||||
depends on HAS_IOMEM
|
||||
default HW_RANDOM
|
||||
---help---
|
||||
This driver provides kernel-side support for the Random Number
|
||||
@@ -333,6 +321,19 @@ config HW_RANDOM_TPM
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_HISI
|
||||
tristate "Hisilicon Random Number Generator support"
|
||||
depends on HW_RANDOM && ARCH_HISI
|
||||
default HW_RANDOM
|
||||
---help---
|
||||
This driver provides kernel-side support for the Random Number
|
||||
Generator hardware found on Hisilicon Hip04 and Hip05 SoC.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called hisi-rng.
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_MSM
|
||||
tristate "Qualcomm SoCs Random Number Generator support"
|
||||
depends on HW_RANDOM && ARCH_QCOM
|
||||
|
||||
@@ -22,10 +22,10 @@ obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
|
||||
obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-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
|
||||
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* exynos-rng.c - Random Number Generator driver for the exynos
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Jonghwa Lee <jonghwa3.lee@smasung.com>
|
||||
* Jonghwa Lee <jonghwa3.lee@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -77,7 +77,8 @@ static int exynos_init(struct hwrng *rng)
|
||||
|
||||
pm_runtime_get_sync(exynos_rng->dev);
|
||||
ret = exynos_rng_configure(exynos_rng);
|
||||
pm_runtime_put_noidle(exynos_rng->dev);
|
||||
pm_runtime_mark_last_busy(exynos_rng->dev);
|
||||
pm_runtime_put_autosuspend(exynos_rng->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -89,6 +90,7 @@ static int exynos_read(struct hwrng *rng, void *buf,
|
||||
struct exynos_rng, rng);
|
||||
u32 *data = buf;
|
||||
int retry = 100;
|
||||
int ret = 4;
|
||||
|
||||
pm_runtime_get_sync(exynos_rng->dev);
|
||||
|
||||
@@ -97,23 +99,27 @@ static int exynos_read(struct hwrng *rng, void *buf,
|
||||
while (!(exynos_rng_readl(exynos_rng,
|
||||
EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
|
||||
cpu_relax();
|
||||
if (!retry)
|
||||
return -ETIMEDOUT;
|
||||
if (!retry) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
|
||||
|
||||
*data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
|
||||
|
||||
out:
|
||||
pm_runtime_mark_last_busy(exynos_rng->dev);
|
||||
pm_runtime_put_sync_autosuspend(exynos_rng->dev);
|
||||
|
||||
return 4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_rng_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct exynos_rng *exynos_rng;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng),
|
||||
GFP_KERNEL);
|
||||
@@ -141,7 +147,21 @@ static int exynos_rng_probe(struct platform_device *pdev)
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
return devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
|
||||
ret = devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
|
||||
if (ret) {
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int exynos_rng_remove(struct platform_device *pdev)
|
||||
{
|
||||
pm_runtime_dont_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev)
|
||||
@@ -201,6 +221,7 @@ static struct platform_driver exynos_rng_driver = {
|
||||
.of_match_table = exynos_rng_dt_match,
|
||||
},
|
||||
.probe = exynos_rng_probe,
|
||||
.remove = exynos_rng_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(exynos_rng_driver);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2016 HiSilicon Co., Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#define RNG_SEED 0x0
|
||||
#define RNG_CTRL 0x4
|
||||
#define RNG_SEED_SEL BIT(2)
|
||||
#define RNG_RING_EN BIT(1)
|
||||
#define RNG_EN BIT(0)
|
||||
#define RNG_RAN_NUM 0x10
|
||||
#define RNG_PHY_SEED 0x14
|
||||
|
||||
#define to_hisi_rng(p) container_of(p, struct hisi_rng, rng)
|
||||
|
||||
static int seed_sel;
|
||||
module_param(seed_sel, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(seed_sel, "Auto reload seed. 0, use LFSR(default); 1, use ring oscillator.");
|
||||
|
||||
struct hisi_rng {
|
||||
void __iomem *base;
|
||||
struct hwrng rng;
|
||||
};
|
||||
|
||||
static int hisi_rng_init(struct hwrng *rng)
|
||||
{
|
||||
struct hisi_rng *hrng = to_hisi_rng(rng);
|
||||
int val = RNG_EN;
|
||||
u32 seed;
|
||||
|
||||
/* get a random number as initial seed */
|
||||
get_random_bytes(&seed, sizeof(seed));
|
||||
|
||||
writel_relaxed(seed, hrng->base + RNG_SEED);
|
||||
|
||||
/**
|
||||
* The seed is reload periodically, there are two choice
|
||||
* of seeds, default seed using the value from LFSR, or
|
||||
* will use seed generated by ring oscillator.
|
||||
*/
|
||||
if (seed_sel == 1)
|
||||
val |= RNG_RING_EN | RNG_SEED_SEL;
|
||||
|
||||
writel_relaxed(val, hrng->base + RNG_CTRL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hisi_rng_cleanup(struct hwrng *rng)
|
||||
{
|
||||
struct hisi_rng *hrng = to_hisi_rng(rng);
|
||||
|
||||
writel_relaxed(0, hrng->base + RNG_CTRL);
|
||||
}
|
||||
|
||||
static int hisi_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
|
||||
{
|
||||
struct hisi_rng *hrng = to_hisi_rng(rng);
|
||||
u32 *data = buf;
|
||||
|
||||
*data = readl_relaxed(hrng->base + RNG_RAN_NUM);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int hisi_rng_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct hisi_rng *rng;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
|
||||
if (!rng)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, rng);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
rng->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(rng->base))
|
||||
return PTR_ERR(rng->base);
|
||||
|
||||
rng->rng.name = pdev->name;
|
||||
rng->rng.init = hisi_rng_init;
|
||||
rng->rng.cleanup = hisi_rng_cleanup;
|
||||
rng->rng.read = hisi_rng_read;
|
||||
|
||||
ret = devm_hwrng_register(&pdev->dev, &rng->rng);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register hwrng\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id hisi_rng_dt_ids[] = {
|
||||
{ .compatible = "hisilicon,hip04-rng" },
|
||||
{ .compatible = "hisilicon,hip05-rng" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, hisi_rng_dt_ids);
|
||||
|
||||
static struct platform_driver hisi_rng_driver = {
|
||||
.probe = hisi_rng_probe,
|
||||
.driver = {
|
||||
.name = "hisi-rng",
|
||||
.of_match_table = of_match_ptr(hisi_rng_dt_ids),
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(hisi_rng_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kefeng Wang <wangkefeng.wang@huawei>");
|
||||
MODULE_DESCRIPTION("Hisilicon random number generator driver");
|
||||
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Generic PowerPC 44x RNG driver
|
||||
*
|
||||
* Copyright 2011 IBM Corporation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
#define PPC4XX_TRNG_DEV_CTRL 0x60080
|
||||
|
||||
#define PPC4XX_TRNGE 0x00020000
|
||||
#define PPC4XX_TRNG_CTRL 0x0008
|
||||
#define PPC4XX_TRNG_CTRL_DALM 0x20
|
||||
#define PPC4XX_TRNG_STAT 0x0004
|
||||
#define PPC4XX_TRNG_STAT_B 0x1
|
||||
#define PPC4XX_TRNG_DATA 0x0000
|
||||
|
||||
#define MODULE_NAME "ppc4xx_rng"
|
||||
|
||||
static int ppc4xx_rng_data_present(struct hwrng *rng, int wait)
|
||||
{
|
||||
void __iomem *rng_regs = (void __iomem *) rng->priv;
|
||||
int busy, i, present = 0;
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B);
|
||||
if (!busy || !wait) {
|
||||
present = 1;
|
||||
break;
|
||||
}
|
||||
udelay(10);
|
||||
}
|
||||
return present;
|
||||
}
|
||||
|
||||
static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data)
|
||||
{
|
||||
void __iomem *rng_regs = (void __iomem *) rng->priv;
|
||||
*data = in_le32(rng_regs + PPC4XX_TRNG_DATA);
|
||||
return 4;
|
||||
}
|
||||
|
||||
static int ppc4xx_rng_enable(int enable)
|
||||
{
|
||||
struct device_node *ctrl;
|
||||
void __iomem *ctrl_reg;
|
||||
int err = 0;
|
||||
u32 val;
|
||||
|
||||
/* Find the main crypto device node and map it to turn the TRNG on */
|
||||
ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto");
|
||||
if (!ctrl)
|
||||
return -ENODEV;
|
||||
|
||||
ctrl_reg = of_iomap(ctrl, 0);
|
||||
if (!ctrl_reg) {
|
||||
err = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL);
|
||||
|
||||
if (enable)
|
||||
val |= PPC4XX_TRNGE;
|
||||
else
|
||||
val = val & ~PPC4XX_TRNGE;
|
||||
|
||||
out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val);
|
||||
iounmap(ctrl_reg);
|
||||
|
||||
out:
|
||||
of_node_put(ctrl);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct hwrng ppc4xx_rng = {
|
||||
.name = MODULE_NAME,
|
||||
.data_present = ppc4xx_rng_data_present,
|
||||
.data_read = ppc4xx_rng_data_read,
|
||||
};
|
||||
|
||||
static int ppc4xx_rng_probe(struct platform_device *dev)
|
||||
{
|
||||
void __iomem *rng_regs;
|
||||
int err = 0;
|
||||
|
||||
rng_regs = of_iomap(dev->dev.of_node, 0);
|
||||
if (!rng_regs)
|
||||
return -ENODEV;
|
||||
|
||||
err = ppc4xx_rng_enable(1);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM);
|
||||
ppc4xx_rng.priv = (unsigned long) rng_regs;
|
||||
|
||||
err = hwrng_register(&ppc4xx_rng);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ppc4xx_rng_remove(struct platform_device *dev)
|
||||
{
|
||||
void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv;
|
||||
|
||||
hwrng_unregister(&ppc4xx_rng);
|
||||
ppc4xx_rng_enable(0);
|
||||
iounmap(rng_regs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id ppc4xx_rng_match[] = {
|
||||
{ .compatible = "ppc4xx-rng", },
|
||||
{ .compatible = "amcc,ppc460ex-rng", },
|
||||
{ .compatible = "amcc,ppc440epx-rng", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ppc4xx_rng_match);
|
||||
|
||||
static struct platform_driver ppc4xx_rng_driver = {
|
||||
.driver = {
|
||||
.name = MODULE_NAME,
|
||||
.of_match_table = ppc4xx_rng_match,
|
||||
},
|
||||
.probe = ppc4xx_rng_probe,
|
||||
.remove = ppc4xx_rng_remove,
|
||||
};
|
||||
|
||||
module_platform_driver(ppc4xx_rng_driver);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
|
||||
MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors");
|
||||
+23
-4
@@ -279,6 +279,14 @@ config CRYPTO_DEV_PPC4XX
|
||||
help
|
||||
This option allows you to have support for AMCC crypto acceleration.
|
||||
|
||||
config HW_RANDOM_PPC4XX
|
||||
bool "PowerPC 4xx generic true random number generator support"
|
||||
depends on CRYPTO_DEV_PPC4XX && HW_RANDOM
|
||||
default y
|
||||
---help---
|
||||
This option provides the kernel-side support for the TRNG hardware
|
||||
found in the security function of some PowerPC 4xx SoCs.
|
||||
|
||||
config CRYPTO_DEV_OMAP_SHAM
|
||||
tristate "Support for OMAP MD5/SHA1/SHA2 hw accelerator"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
@@ -302,15 +310,16 @@ config CRYPTO_DEV_OMAP_AES
|
||||
want to use the OMAP module for AES algorithms.
|
||||
|
||||
config CRYPTO_DEV_OMAP_DES
|
||||
tristate "Support for OMAP DES3DES hw engine"
|
||||
tristate "Support for OMAP DES/3DES hw engine"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
select CRYPTO_DES
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_ENGINE
|
||||
help
|
||||
OMAP processors have DES/3DES module accelerator. Select this if you
|
||||
want to use the OMAP module for DES and 3DES algorithms. Currently
|
||||
the ECB and CBC modes of operation supported by the driver. Also
|
||||
accesses made on unaligned boundaries are also supported.
|
||||
the ECB and CBC modes of operation are supported by the driver. Also
|
||||
accesses made on unaligned boundaries are supported.
|
||||
|
||||
config CRYPTO_DEV_PICOXCELL
|
||||
tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
|
||||
@@ -340,9 +349,19 @@ config CRYPTO_DEV_SAHARA
|
||||
This option enables support for the SAHARA HW crypto accelerator
|
||||
found in some Freescale i.MX chips.
|
||||
|
||||
config CRYPTO_DEV_MXC_SCC
|
||||
tristate "Support for Freescale Security Controller (SCC)"
|
||||
depends on ARCH_MXC && OF
|
||||
select CRYPTO_BLKCIPHER
|
||||
select CRYPTO_DES
|
||||
help
|
||||
This option enables support for the Security Controller (SCC)
|
||||
found in Freescale i.MX25 chips.
|
||||
|
||||
config CRYPTO_DEV_S5P
|
||||
tristate "Support for Samsung S5PV210/Exynos crypto accelerator"
|
||||
depends on ARCH_S5PV210 || ARCH_EXYNOS
|
||||
depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
|
||||
depends on HAS_IOMEM && HAS_DMA
|
||||
select CRYPTO_AES
|
||||
select CRYPTO_BLKCIPHER
|
||||
help
|
||||
|
||||
@@ -23,6 +23,7 @@ obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
|
||||
obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_SAHARA) += sahara.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_MXC_SCC) += mxc-scc.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
|
||||
obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
|
||||
obj-$(CONFIG_CRYPTO_DEV_QAT) += qat/
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o
|
||||
crypto4xx-y := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
|
||||
crypto4xx-$(CONFIG_HW_RANDOM_PPC4XX) += crypto4xx_trng.o
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user