Re: [PATCH v6 0/6] crypto: Add Qcom PRNG support
On 16-07-18, 11:20, Vinod Koul wrote: > This series removes the hwrng qcom driver and replaces it with crypto qcom > driver and then adds support for Execution Environment (EE) found in v2 > version of the hardware and ACPI support for these Stephan, Herbert Any chance this could make it for 4.19. It has been here for a while and I haven't heard any objections. > > Changes in v6: > - Fix a typo in kconfig. Remove of_device.h and add of.h header > - Add review and tested tags > > Changes in v5: > - Update ACPI check and use generic driver data API > > Changes in v4: > - Use memcpy for data copy > - Fix trailing bytes copy > - Fix ACPI ID table name > > Timur Tabi (1): > crypto: qcom: Add ACPI support > > Vinod Koul (5): > hwrng: remove msm hw_random driver > dt-bindings: crypto: Move prng binding to crypto > crypto: Add Qcom prng driver > dt-bindings: crypto: Add new compatible qcom,prng-ee > crypto: qcom: Add support for prng-ee > > .../bindings/{rng => crypto}/qcom,prng.txt | 4 +- > drivers/char/hw_random/Kconfig | 13 -- > drivers/char/hw_random/Makefile| 1 - > drivers/char/hw_random/msm-rng.c | 183 > drivers/crypto/Kconfig | 11 + > drivers/crypto/Makefile| 1 + > drivers/crypto/qcom-rng.c | 229 > + > 7 files changed, 244 insertions(+), 198 deletions(-) > rename Documentation/devicetree/bindings/{rng => crypto}/qcom,prng.txt (73%) > delete mode 100644 drivers/char/hw_random/msm-rng.c > create mode 100644 drivers/crypto/qcom-rng.c > > -- > 2.14.4 -- ~Vinod
[PATCH 3/3] crypto: ablkcipher - fix crash flushing dcache in error path
From: Eric Biggers Like the skcipher_walk and blkcipher_walk cases: scatterwalk_done() is only meant to be called after a nonzero number of bytes have been processed, since scatterwalk_pagedone() will flush the dcache of the *previous* page. But in the error case of ablkcipher_walk_done(), e.g. if the input wasn't an integer number of blocks, scatterwalk_done() was actually called after advancing 0 bytes. This caused a crash ("BUG: unable to handle kernel paging request") during '!PageSlab(page)' on architectures like arm and arm64 that define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was page-aligned as in that case walk->offset == 0. Fix it by reorganizing ablkcipher_walk_done() to skip the scatterwalk_advance() and scatterwalk_done() if an error has occurred. Reported-by: Liu Chao Fixes: bf06099db18a ("crypto: skcipher - Add ablkcipher_walk interfaces") Cc: # v2.6.35+ Signed-off-by: Eric Biggers --- crypto/ablkcipher.c | 57 + 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 1edb5000d783..8882e90e868e 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -71,11 +71,9 @@ static inline u8 *ablkcipher_get_spot(u8 *start, unsigned int len) return max(start, end_page); } -static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk, - unsigned int bsize) +static inline void ablkcipher_done_slow(struct ablkcipher_walk *walk, + unsigned int n) { - unsigned int n = bsize; - for (;;) { unsigned int len_this_page = scatterwalk_pagelen(>out); @@ -87,17 +85,13 @@ static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk, n -= len_this_page; scatterwalk_start(>out, sg_next(walk->out.sg)); } - - return bsize; } -static inline unsigned int ablkcipher_done_fast(struct ablkcipher_walk *walk, - unsigned int n) +static inline void ablkcipher_done_fast(struct ablkcipher_walk *walk, + unsigned int n) { scatterwalk_advance(>in, n); scatterwalk_advance(>out, n); - - return n; } static int ablkcipher_walk_next(struct ablkcipher_request *req, @@ -107,39 +101,40 @@ int ablkcipher_walk_done(struct ablkcipher_request *req, struct ablkcipher_walk *walk, int err) { struct crypto_tfm *tfm = req->base.tfm; - unsigned int nbytes = 0; + unsigned int n; /* bytes processed */ + bool more; - if (likely(err >= 0)) { - unsigned int n = walk->nbytes - err; + if (unlikely(err < 0)) + goto finish; - if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) - n = ablkcipher_done_fast(walk, n); - else if (WARN_ON(err)) { - err = -EINVAL; - goto err; - } else - n = ablkcipher_done_slow(walk, n); + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); - nbytes = walk->total - n; - err = 0; + if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) { + ablkcipher_done_fast(walk, n); + } else { + if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ + err = -EINVAL; + goto finish; + } + ablkcipher_done_slow(walk, n); } - scatterwalk_done(>in, 0, nbytes); - scatterwalk_done(>out, 1, nbytes); - -err: - walk->total = nbytes; - walk->nbytes = nbytes; + scatterwalk_done(>in, 0, more); + scatterwalk_done(>out, 1, more); - if (nbytes) { + if (more) { crypto_yield(req->base.flags); return ablkcipher_walk_next(req, walk); } - + err = 0; +finish: + walk->nbytes = 0; if (walk->iv != req->info) memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize); kfree(walk->iv_buffer); - return err; } EXPORT_SYMBOL_GPL(ablkcipher_walk_done); -- 2.18.0.233.g985f88cf7e-goog
[PATCH 2/3] crypto: blkcipher - fix crash flushing dcache in error path
From: Eric Biggers Like the skcipher_walk case: scatterwalk_done() is only meant to be called after a nonzero number of bytes have been processed, since scatterwalk_pagedone() will flush the dcache of the *previous* page. But in the error case of blkcipher_walk_done(), e.g. if the input wasn't an integer number of blocks, scatterwalk_done() was actually called after advancing 0 bytes. This caused a crash ("BUG: unable to handle kernel paging request") during '!PageSlab(page)' on architectures like arm and arm64 that define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was page-aligned as in that case walk->offset == 0. Fix it by reorganizing blkcipher_walk_done() to skip the scatterwalk_advance() and scatterwalk_done() if an error has occurred. This bug was found by syzkaller fuzzing. Reproducer, assuming ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE: #include #include #include int main() { struct sockaddr_alg addr = { .salg_type = "skcipher", .salg_name = "ecb(aes-generic)", }; char buffer[4096] __attribute__((aligned(4096))) = { 0 }; int fd; fd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(fd, (void *), sizeof(addr)); setsockopt(fd, SOL_ALG, ALG_SET_KEY, buffer, 16); fd = accept(fd, NULL, NULL); write(fd, buffer, 15); read(fd, buffer, 15); } Reported-by: Liu Chao Fixes: 5cde0af2a982 ("[CRYPTO] cipher: Added block cipher type") Cc: # v2.6.19+ Signed-off-by: Eric Biggers --- crypto/blkcipher.c | 54 ++ 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index dd4dcab3766a..f93abf13b5d4 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -70,19 +70,18 @@ static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len) return max(start, end_page); } -static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk, - unsigned int bsize) +static inline void blkcipher_done_slow(struct blkcipher_walk *walk, + unsigned int bsize) { u8 *addr; addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1); addr = blkcipher_get_spot(addr, bsize); scatterwalk_copychunks(addr, >out, bsize, 1); - return bsize; } -static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, - unsigned int n) +static inline void blkcipher_done_fast(struct blkcipher_walk *walk, + unsigned int n) { if (walk->flags & BLKCIPHER_WALK_COPY) { blkcipher_map_dst(walk); @@ -96,49 +95,48 @@ static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, scatterwalk_advance(>in, n); scatterwalk_advance(>out, n); - - return n; } int blkcipher_walk_done(struct blkcipher_desc *desc, struct blkcipher_walk *walk, int err) { - unsigned int nbytes = 0; + unsigned int n; /* bytes processed */ + bool more; - if (likely(err >= 0)) { - unsigned int n = walk->nbytes - err; + if (unlikely(err < 0)) + goto finish; - if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) - n = blkcipher_done_fast(walk, n); - else if (WARN_ON(err)) { - err = -EINVAL; - goto err; - } else - n = blkcipher_done_slow(walk, n); + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); - nbytes = walk->total - n; - err = 0; + if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) { + blkcipher_done_fast(walk, n); + } else { + if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ + err = -EINVAL; + goto finish; + } + blkcipher_done_slow(walk, n); } - scatterwalk_done(>in, 0, nbytes); - scatterwalk_done(>out, 1, nbytes); + scatterwalk_done(>in, 0, more); + scatterwalk_done(>out, 1, more); -err: - walk->total = nbytes; - walk->nbytes = nbytes; - - if (nbytes) { + if (more) { crypto_yield(desc->flags); return blkcipher_walk_next(desc, walk); } - + err = 0; +finish: + walk->nbytes = 0; if (walk->iv != desc->info) memcpy(desc->info, walk->iv, walk->ivsize); if (walk->buffer != walk->page) kfree(walk->buffer); if (walk->page)
[PATCH 1/3] crypto: skcipher - fix crash flushing dcache in error path
From: Eric Biggers scatterwalk_done() is only meant to be called after a nonzero number of bytes have been processed, since scatterwalk_pagedone() will flush the dcache of the *previous* page. But in the error case of skcipher_walk_done(), e.g. if the input wasn't an integer number of blocks, scatterwalk_done() was actually called after advancing 0 bytes. This caused a crash ("BUG: unable to handle kernel paging request") during '!PageSlab(page)' on architectures like arm and arm64 that define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE, provided that the input was page-aligned as in that case walk->offset == 0. Fix it by reorganizing skcipher_walk_done() to skip the scatterwalk_advance() and scatterwalk_done() if an error has occurred. This bug was found by syzkaller fuzzing. Reproducer, assuming ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE: #include #include #include int main() { struct sockaddr_alg addr = { .salg_type = "skcipher", .salg_name = "cbc(aes-generic)", }; char buffer[4096] __attribute__((aligned(4096))) = { 0 }; int fd; fd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(fd, (void *), sizeof(addr)); setsockopt(fd, SOL_ALG, ALG_SET_KEY, buffer, 16); fd = accept(fd, NULL, NULL); write(fd, buffer, 15); read(fd, buffer, 15); } Reported-by: Liu Chao Fixes: b286d8b1a690 ("crypto: skcipher - Add skcipher walk interface") Cc: # v4.10+ Signed-off-by: Eric Biggers --- crypto/skcipher.c | 53 --- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 7d6a49fe3047..5f7017b36d75 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -95,7 +95,7 @@ static inline u8 *skcipher_get_spot(u8 *start, unsigned int len) return max(start, end_page); } -static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize) +static void skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize) { u8 *addr; @@ -103,23 +103,24 @@ static int skcipher_done_slow(struct skcipher_walk *walk, unsigned int bsize) addr = skcipher_get_spot(addr, bsize); scatterwalk_copychunks(addr, >out, bsize, (walk->flags & SKCIPHER_WALK_PHYS) ? 2 : 1); - return 0; } int skcipher_walk_done(struct skcipher_walk *walk, int err) { - unsigned int n = walk->nbytes - err; - unsigned int nbytes; - - nbytes = walk->total - n; - - if (unlikely(err < 0)) { - nbytes = 0; - n = 0; - } else if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS | - SKCIPHER_WALK_SLOW | - SKCIPHER_WALK_COPY | - SKCIPHER_WALK_DIFF { + unsigned int n; /* bytes processed */ + bool more; + + if (unlikely(err < 0)) + goto finish; + + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); + + if (likely(!(walk->flags & (SKCIPHER_WALK_PHYS | + SKCIPHER_WALK_SLOW | + SKCIPHER_WALK_COPY | + SKCIPHER_WALK_DIFF { unmap_src: skcipher_unmap_src(walk); } else if (walk->flags & SKCIPHER_WALK_DIFF) { @@ -131,28 +132,28 @@ int skcipher_walk_done(struct skcipher_walk *walk, int err) skcipher_unmap_dst(walk); } else if (unlikely(walk->flags & SKCIPHER_WALK_SLOW)) { if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ err = -EINVAL; - nbytes = 0; - } else - n = skcipher_done_slow(walk, n); + goto finish; + } + skcipher_done_slow(walk, n); + goto already_advanced; } - if (err > 0) - err = 0; - - walk->total = nbytes; - walk->nbytes = nbytes; - scatterwalk_advance(>in, n); scatterwalk_advance(>out, n); - scatterwalk_done(>in, 0, nbytes); - scatterwalk_done(>out, 1, nbytes); +already_advanced: + scatterwalk_done(>in, 0, more); + scatterwalk_done(>out, 1, more); - if (nbytes) { + if (more) { crypto_yield(walk->flags & SKCIPHER_WALK_SLEEP ? CRYPTO_TFM_REQ_MAY_SLEEP : 0); return skcipher_walk_next(walk); } + err = 0; +finish: + walk->nbytes = 0; /* Short-circuit for the common/fast path. */ if (!((unsigned long)walk->buffer | (unsigned long)walk->page)) --
[PATCH 0/3] crypto: fix crash in scatterwalk_pagedone()
From: Eric Biggers This series fixes the bug reported by Liu Chao (found using syzkaller) where a crash occurs in scatterwalk_pagedone() on architectures such as arm and arm64 that implement flush_dcache_page(), due to an invalid page pointer when walk->offset == 0. This series attempts to address the underlying problem which is that scatterwalk_pagedone() shouldn't have been called at all in that case. Eric Biggers (3): crypto: skcipher - fix crash flushing dcache in error path crypto: blkcipher - fix crash flushing dcache in error path crypto: ablkcipher - fix crash flushing dcache in error path crypto/ablkcipher.c | 57 + crypto/blkcipher.c | 54 +- crypto/skcipher.c | 53 - 3 files changed, 79 insertions(+), 85 deletions(-) -- 2.18.0.233.g985f88cf7e-goog
[PATCH] crypto: skcipher - remove unnecessary setting of walk->nbytes
From: Eric Biggers Setting 'walk->nbytes = walk->total' in skcipher_walk_first() doesn't make sense because actually walk->nbytes needs to be set to the length of the first step in the walk, which may be less than walk->total. This is done by skcipher_walk_next() which is called immediately afterwards. Also walk->nbytes was already set to 0 in skcipher_walk_skcipher(), which is a better default value in case it's forgotten to be set later. Therefore, remove the unnecessary assignment to walk->nbytes. Signed-off-by: Eric Biggers --- crypto/skcipher.c | 1 - 1 file changed, 1 deletion(-) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 7d6a49fe3047..9f7d229827b5 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -436,7 +436,6 @@ static int skcipher_walk_first(struct skcipher_walk *walk) } walk->page = NULL; - walk->nbytes = walk->total; return skcipher_walk_next(walk); } -- 2.18.0.233.g985f88cf7e-goog
[PATCH] crypto: scatterwalk - remove scatterwalk_samebuf()
From: Eric Biggers scatterwalk_samebuf() is never used. Remove it. Signed-off-by: Eric Biggers --- include/crypto/scatterwalk.h | 7 --- 1 file changed, 7 deletions(-) diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h index eac72840a7d2..a66c127a20ed 100644 --- a/include/crypto/scatterwalk.h +++ b/include/crypto/scatterwalk.h @@ -30,13 +30,6 @@ static inline void scatterwalk_crypto_chain(struct scatterlist *head, sg_mark_end(head); } -static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in, - struct scatter_walk *walk_out) -{ - return !(((sg_page(walk_in->sg) - sg_page(walk_out->sg)) << PAGE_SHIFT) + -(int)(walk_in->offset - walk_out->offset)); -} - static inline unsigned int scatterwalk_pagelen(struct scatter_walk *walk) { unsigned int len = walk->sg->offset + walk->sg->length - walk->offset; -- 2.18.0.233.g985f88cf7e-goog
[PATCH] crypto: scatterwalk - remove 'chain' argument from scatterwalk_crypto_chain()
From: Eric Biggers All callers pass chain=0 to scatterwalk_crypto_chain(). Remove this unneeded parameter. Signed-off-by: Eric Biggers --- crypto/lrw.c | 4 ++-- crypto/scatterwalk.c | 2 +- crypto/xts.c | 4 ++-- include/crypto/scatterwalk.h | 8 +--- net/tls/tls_device_fallback.c | 2 +- 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/crypto/lrw.c b/crypto/lrw.c index 954a7064a179..393a782679c7 100644 --- a/crypto/lrw.c +++ b/crypto/lrw.c @@ -188,7 +188,7 @@ static int post_crypt(struct skcipher_request *req) if (rctx->dst != sg) { rctx->dst[0] = *sg; sg_unmark_end(rctx->dst); - scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 0, 2); + scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 2); } rctx->dst[0].length -= offset - sg->offset; rctx->dst[0].offset = offset; @@ -265,7 +265,7 @@ static int pre_crypt(struct skcipher_request *req) if (rctx->src != sg) { rctx->src[0] = *sg; sg_unmark_end(rctx->src); - scatterwalk_crypto_chain(rctx->src, sg_next(sg), 0, 2); + scatterwalk_crypto_chain(rctx->src, sg_next(sg), 2); } rctx->src[0].length -= offset - sg->offset; rctx->src[0].offset = offset; diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c index c16c94f88733..d0b92c1cd6e9 100644 --- a/crypto/scatterwalk.c +++ b/crypto/scatterwalk.c @@ -91,7 +91,7 @@ struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2], sg_init_table(dst, 2); sg_set_page(dst, sg_page(src), src->length - len, src->offset + len); - scatterwalk_crypto_chain(dst, sg_next(src), 0, 2); + scatterwalk_crypto_chain(dst, sg_next(src), 2); return dst; } diff --git a/crypto/xts.c b/crypto/xts.c index 12284183bd20..ccf55fbb8bc2 100644 --- a/crypto/xts.c +++ b/crypto/xts.c @@ -138,7 +138,7 @@ static int post_crypt(struct skcipher_request *req) if (rctx->dst != sg) { rctx->dst[0] = *sg; sg_unmark_end(rctx->dst); - scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 0, 2); + scatterwalk_crypto_chain(rctx->dst, sg_next(sg), 2); } rctx->dst[0].length -= offset - sg->offset; rctx->dst[0].offset = offset; @@ -204,7 +204,7 @@ static int pre_crypt(struct skcipher_request *req) if (rctx->src != sg) { rctx->src[0] = *sg; sg_unmark_end(rctx->src); - scatterwalk_crypto_chain(rctx->src, sg_next(sg), 0, 2); + scatterwalk_crypto_chain(rctx->src, sg_next(sg), 2); } rctx->src[0].length -= offset - sg->offset; rctx->src[0].offset = offset; diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h index 880e6be9e95e..eac72840a7d2 100644 --- a/include/crypto/scatterwalk.h +++ b/include/crypto/scatterwalk.h @@ -22,14 +22,8 @@ #include static inline void scatterwalk_crypto_chain(struct scatterlist *head, - struct scatterlist *sg, - int chain, int num) + struct scatterlist *sg, int num) { - if (chain) { - head->length += sg->length; - sg = sg_next(sg); - } - if (sg) sg_chain(head, num, sg); else diff --git a/net/tls/tls_device_fallback.c b/net/tls/tls_device_fallback.c index 748914abdb60..4e1ec12bc0fb 100644 --- a/net/tls/tls_device_fallback.c +++ b/net/tls/tls_device_fallback.c @@ -42,7 +42,7 @@ static void chain_to_walk(struct scatterlist *sg, struct scatter_walk *walk) sg_set_page(sg, sg_page(src), src->length - diff, walk->offset); - scatterwalk_crypto_chain(sg, sg_next(src), 0, 2); + scatterwalk_crypto_chain(sg, sg_next(src), 2); } static int tls_enc_record(struct aead_request *aead_req, -- 2.18.0.233.g985f88cf7e-goog
[PATCH] crypto: skcipher - fix aligning block size in skcipher_copy_iv()
From: Eric Biggers The ALIGN() macro needs to be passed the alignment, not the alignmask (which is the alignment minus 1). Fixes: b286d8b1a690 ("crypto: skcipher - Add skcipher walk interface") Cc: # v4.10+ Signed-off-by: Eric Biggers --- crypto/skcipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/skcipher.c b/crypto/skcipher.c index 7d6a49fe3047..4f6b8dadaceb 100644 --- a/crypto/skcipher.c +++ b/crypto/skcipher.c @@ -398,7 +398,7 @@ static int skcipher_copy_iv(struct skcipher_walk *walk) unsigned size; u8 *iv; - aligned_bs = ALIGN(bs, alignmask); + aligned_bs = ALIGN(bs, alignmask + 1); /* Minimum size to align buffer by alignmask. */ size = alignmask & ~a; -- 2.18.0.233.g985f88cf7e-goog
[PATCH 2/3] crypto: hisilicon SEC security accelerator driver
This accelerator is found inside hisilicon hip06 and hip07 SoCs. Each instance provides a number of queues which feed a different number of backend acceleration units. The queues are operating in an out of order mode in the interests of throughput. The silicon does not do tracking of dependencies between multiple 'messages' or update of the IVs as appropriate for training. Hence where relevant we need to do this in software. Signed-off-by: Jonathan Cameron --- drivers/crypto/Kconfig |2 + drivers/crypto/Makefile |1 + drivers/crypto/hisilicon/Kconfig| 14 + drivers/crypto/hisilicon/Makefile |2 + drivers/crypto/hisilicon/sec/Makefile |3 + drivers/crypto/hisilicon/sec/sec_algs.c | 1122 ++ drivers/crypto/hisilicon/sec/sec_drv.c | 1323 +++ drivers/crypto/hisilicon/sec/sec_drv.h | 428 ++ 8 files changed, 2895 insertions(+) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index d1ea1a07cecb..d0b80d0d1f8b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -750,4 +750,6 @@ config CRYPTO_DEV_CCREE cryptographic operations on the system REE. If unsure say Y. +source "drivers/crypto/hisilicon/Kconfig" + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 7ae87b4f6c8d..ee43aed8cb69 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -45,3 +45,4 @@ obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/ obj-$(CONFIG_CRYPTO_DEV_BCM_SPU) += bcm/ obj-$(CONFIG_CRYPTO_DEV_SAFEXCEL) += inside-secure/ obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/ +obj-y += hisilicon/ diff --git a/drivers/crypto/hisilicon/Kconfig b/drivers/crypto/hisilicon/Kconfig new file mode 100644 index ..8ca9c503bcb0 --- /dev/null +++ b/drivers/crypto/hisilicon/Kconfig @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 + +config CRYPTO_DEV_HISI_SEC + tristate "Support for Hisilicon SEC crypto block cipher accelerator" + select CRYPTO_BLKCIPHER + select CRYPTO_ALGAPI + select SG_SPLIT + depends on ARM64 || COMPILE_TEST + depends on HAS_IOMEM + help + Support for Hisilicon SEC Engine in Hip06 and Hip07 + + To compile this as a module, choose M here: the module + will be called hisi_sec. diff --git a/drivers/crypto/hisilicon/Makefile b/drivers/crypto/hisilicon/Makefile new file mode 100644 index ..463f46ace182 --- /dev/null +++ b/drivers/crypto/hisilicon/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += sec/ diff --git a/drivers/crypto/hisilicon/sec/Makefile b/drivers/crypto/hisilicon/sec/Makefile new file mode 100644 index ..a55b698e0c27 --- /dev/null +++ b/drivers/crypto/hisilicon/sec/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CRYPTO_DEV_HISI_SEC) += hisi_sec.o +hisi_sec-y = sec_algs.o sec_drv.o diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c new file mode 100644 index ..d69d3ce358b0 --- /dev/null +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -0,0 +1,1122 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2016-2017 Hisilicon Limited. */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "sec_drv.h" + +#define SEC_MAX_CIPHER_KEY 64 +#define SEC_REQ_LIMIT SZ_32M + +struct sec_c_alg_cfg { + unsigned c_alg : 3; + unsigned c_mode : 3; + unsigned key_len: 2; + unsigned c_width: 2; +}; + +static const struct sec_c_alg_cfg sec_c_alg_cfgs[] = { + [SEC_C_DES_ECB_64] = { + .c_alg = SEC_C_ALG_DES, + .c_mode = SEC_C_MODE_ECB, + .key_len = SEC_KEY_LEN_DES, + }, + [SEC_C_DES_CBC_64] = { + .c_alg = SEC_C_ALG_DES, + .c_mode = SEC_C_MODE_CBC, + .key_len = SEC_KEY_LEN_DES, + }, + [SEC_C_3DES_ECB_192_3KEY] = { + .c_alg = SEC_C_ALG_3DES, + .c_mode = SEC_C_MODE_ECB, + .key_len = SEC_KEY_LEN_3DES_3_KEY, + }, + [SEC_C_3DES_ECB_192_2KEY] = { + .c_alg = SEC_C_ALG_3DES, + .c_mode = SEC_C_MODE_ECB, + .key_len = SEC_KEY_LEN_3DES_2_KEY, + }, + [SEC_C_3DES_CBC_192_3KEY] = { + .c_alg = SEC_C_ALG_3DES, + .c_mode = SEC_C_MODE_CBC, + .key_len = SEC_KEY_LEN_3DES_3_KEY, + }, + [SEC_C_3DES_CBC_192_2KEY] = { + .c_alg = SEC_C_ALG_3DES, + .c_mode = SEC_C_MODE_CBC, + .key_len = SEC_KEY_LEN_3DES_2_KEY, + }, + [SEC_C_AES_ECB_128] = { + .c_alg = SEC_C_ALG_AES, + .c_mode = SEC_C_MODE_ECB, + .key_len =
[PATCH V2 0/3] Hisilicon SEC crypto driver (hip06 / hip07)
The driver provides in kernel support for the Hisilicon SEC accelerator found in the hip06 and hip07 SoCs. There are 4 such units on the D05 board for which an appropriate DT binding has been provided. ACPI also works with an appropriate UEFI build. The hardware does not update the IV in chaining or counting modes. This is done in the drive ron completion of the cipher operation. The driver support AES, DES and 3DES block ciphers in a range of modes (others to follow). Hash and AAED support to follow. Sorry for the delay on this one, other priorities and all that... Changes since V1. 1) DT binding fixes suggested by Rob Herring in patches 1 and 3. 2) Added XTS key check as suggested by Stephan Muller. 3) A trivial use after free found during testing of the above. Changes since RFC. 1) Addition of backlog queuing as needed to support dm-crypt usecases. 2) iommu presence tests now done as Robin Murphy suggested. 3) Hardware limiation to 32MB requests worked aroud in driver so it will now support very large requests (512*32MB). Larger request handling than this would require a longer queue with the associate overheads and is considered unlikely to be necessary. 4) The specific handling related to the inline IV patch set from Stephan has been dropped for now. 5) Interrupt handler was previous more complex than necessary so has been reworked. 6) Use of the bounce buffer for small packeets is dropped for now. This is a performance optimization that made the code harder to review and can be reintroduced as necessary at a later date. 7) Restructuring of some code to simplify hash and aaed (hash implemented but not ready fo upstream at this time) 8) Various minor fixes and reworks of the code * several off by one errors in the cleanup paths * single template for enc and dec * drop dec_key as not used (enc_key was used in both cases) * drop dma pool for IVs as it breaks chaining. * lots of spinlocks changed to mutexes as not taken in atomic context. * nasty memory leak cleaned up. Jonathan Cameron (3): dt-bindings: Add bindings for Hisilicon SEC crypto accelerators. crypto: hisilicon SEC security accelerator driver arm64: dts: hisi: add SEC crypto accelerator nodes for hip07 SoC .../bindings/crypto/hisilicon,hip07-sec.txt| 67 + arch/arm64/boot/dts/hisilicon/hip07.dtsi | 284 + drivers/crypto/Kconfig |2 + drivers/crypto/Makefile|1 + drivers/crypto/hisilicon/Kconfig | 14 + drivers/crypto/hisilicon/Makefile |2 + drivers/crypto/hisilicon/sec/Makefile |3 + drivers/crypto/hisilicon/sec/sec_algs.c| 1122 + drivers/crypto/hisilicon/sec/sec_drv.c | 1323 drivers/crypto/hisilicon/sec/sec_drv.h | 428 +++ 10 files changed, 3246 insertions(+) create mode 100644 Documentation/devicetree/bindings/crypto/hisilicon,hip07-sec.txt create mode 100644 drivers/crypto/hisilicon/Kconfig create mode 100644 drivers/crypto/hisilicon/Makefile create mode 100644 drivers/crypto/hisilicon/sec/Makefile create mode 100644 drivers/crypto/hisilicon/sec/sec_algs.c create mode 100644 drivers/crypto/hisilicon/sec/sec_drv.c create mode 100644 drivers/crypto/hisilicon/sec/sec_drv.h -- 2.16.2
[PATCH 3/3] arm64: dts: hisi: add SEC crypto accelerator nodes for hip07 SoC
Enable all 4 SEC units available on d05 boards. Signed-off-by: Jonathan Cameron --- arch/arm64/boot/dts/hisilicon/hip07.dtsi | 284 +++ 1 file changed, 284 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi index 0600a6a84ab7..6d046f4f7019 100644 --- a/arch/arm64/boot/dts/hisilicon/hip07.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi @@ -1049,7 +1049,74 @@ num-pins = <2>; }; }; + p0_mbigen_alg_a:interrupt-controller@d008 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x0 0xd008 0x0 0x1>; + p0_mbigen_sec_a: intc_sec { + msi-parent = <_its_dsa_a 0x40400>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <33>; + }; + p0_mbigen_smmu_alg_a: intc_smmu_alg { + msi-parent = <_its_dsa_a 0x40b1b>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <3>; + }; + }; + p0_mbigen_alg_b:interrupt-controller@8,d008 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x8 0xd008 0x0 0x1>; + + p0_mbigen_sec_b: intc_sec { + msi-parent = <_its_dsa_b 0x42400>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <33>; + }; + p0_mbigen_smmu_alg_b: intc_smmu_alg { + msi-parent = <_its_dsa_b 0x42b1b>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <3>; + }; + }; + p1_mbigen_alg_a:interrupt-controller@400,d008 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x400 0xd008 0x0 0x1>; + + p1_mbigen_sec_a: intc_sec { + msi-parent = <_its_dsa_a 0x44400>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <33>; + }; + p1_mbigen_smmu_alg_a: intc_smmu_alg { + msi-parent = <_its_dsa_a 0x44b1b>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <3>; + }; + }; + p1_mbigen_alg_b:interrupt-controller@408,d008 { + compatible = "hisilicon,mbigen-v2"; + reg = <0x408 0xd008 0x0 0x1>; + + p1_mbigen_sec_b: intc_sec { + msi-parent = <_its_dsa_b 0x46400>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <33>; + }; + p1_mbigen_smmu_alg_b: intc_smmu_alg { + msi-parent = <_its_dsa_b 0x46b1b>; + interrupt-controller; + #interrupt-cells = <2>; + num-pins = <3>; + }; + }; p0_mbigen_dsa_a: interrupt-controller@c008 { compatible = "hisilicon,mbigen-v2"; reg = <0x0 0xc008 0x0 0x1>; @@ -1107,6 +1174,58 @@ hisilicon,broken-prefetch-cmd; status = "disabled"; }; + p0_smmu_alg_a: smmu_alg@d004 { + compatible = "arm,smmu-v3"; + reg = <0x0 0xd004 0x0 0x2>; + interrupt-parent = <_mbigen_smmu_alg_a>; + interrupts = <733 1>, + <734 1>, + <735 1>; + interrupt-names = "eventq", "gerror", "priq"; + #iommu-cells = <1>; + dma-coherent; + hisilicon,broken-prefetch-cmd; + /* smmu-cb-memtype = <0x0 0x1>;*/ + }; + p0_smmu_alg_b: smmu_alg@8,d004 { + compatible = "arm,smmu-v3"; + reg = <0x8 0xd004 0x0 0x2>; + interrupt-parent = <_mbigen_smmu_alg_b>; + interrupts = <733 1>, + <734 1>, + <735 1>; + interrupt-names = "eventq", "gerror", "priq"; + #iommu-cells = <1>; + dma-coherent; + hisilicon,broken-prefetch-cmd; + /* smmu-cb-memtype = <0x0 0x1>;*/ + }; + p1_smmu_alg_a: smmu_alg@400,d004 { + compatible = "arm,smmu-v3"; + reg = <0x400 0xd004 0x0 0x2>; + interrupt-parent = <_mbigen_smmu_alg_a>; + interrupts = <733 1>, + <734 1>, + <735 1>; + interrupt-names = "eventq", "gerror", "priq";
[PATCH 1/3] dt-bindings: Add bindings for Hisilicon SEC crypto accelerators.
The hip06 and hip07 SoCs contain a number of these crypto units which accelerate AES and DES operations. Signed-off-by: Jonathan Cameron --- .../bindings/crypto/hisilicon,hip07-sec.txt| 67 ++ 1 file changed, 67 insertions(+) diff --git a/Documentation/devicetree/bindings/crypto/hisilicon,hip07-sec.txt b/Documentation/devicetree/bindings/crypto/hisilicon,hip07-sec.txt new file mode 100644 index ..78d2db9d4de5 --- /dev/null +++ b/Documentation/devicetree/bindings/crypto/hisilicon,hip07-sec.txt @@ -0,0 +1,67 @@ +* Hisilicon hip07 Security Accelerator (SEC) + +Required properties: +- compatible: Must contain one of + - "hisilicon,hip06-sec" + - "hisilicon,hip07-sec" +- reg: Memory addresses and lengths of the memory regions through which + this device is controlled. + Region 0 has registers to control the backend processing engines. + Region 1 has registers for functionality common to all queues. + Regions 2-18 have registers for the 16 individual queues which are isolated + both in hardware and within the driver. +- interrupts: Interrupt specifiers. + Refer to interrupt-controller/interrupts.txt for generic interrupt client node + bindings. + Interrupt 0 is for the SEC unit error queue. + Interrupt 2N + 1 is the completion interrupt for queue N. + Interrupt 2N + 2 is the error interrupt for queue N. +- dma-coherent: The driver assumes coherent dma is possible. + +Optional properties: +- iommus: The SEC units are behind smmu-v3 iommus. + Refer to iommu/arm,smmu-v3.txt for more information. + +Example: + +p1_sec_a: crypto@400,d200 { + compatible = "hisilicon,hip07-sec"; + reg = <0x400 0xd000 0x0 0x1 + 0x400 0xd200 0x0 0x1 + 0x400 0xd201 0x0 0x1 + 0x400 0xd202 0x0 0x1 + 0x400 0xd203 0x0 0x1 + 0x400 0xd204 0x0 0x1 + 0x400 0xd205 0x0 0x1 + 0x400 0xd206 0x0 0x1 + 0x400 0xd207 0x0 0x1 + 0x400 0xd208 0x0 0x1 + 0x400 0xd209 0x0 0x1 + 0x400 0xd20a 0x0 0x1 + 0x400 0xd20b 0x0 0x1 + 0x400 0xd20c 0x0 0x1 + 0x400 0xd20d 0x0 0x1 + 0x400 0xd20e 0x0 0x1 + 0x400 0xd20f 0x0 0x1 + 0x400 0xd210 0x0 0x1>; + interrupt-parent = <_mbigen_sec_a>; + iommus = <_smmu_alg_a 0x600>; + dma-coherent; + interrupts = <576 4>, +<577 1>, <578 4>, +<579 1>, <580 4>, +<581 1>, <582 4>, +<583 1>, <584 4>, +<585 1>, <586 4>, +<587 1>, <588 4>, +<589 1>, <590 4>, +<591 1>, <592 4>, +<593 1>, <594 4>, +<595 1>, <596 4>, +<597 1>, <598 4>, +<599 1>, <600 4>, +<601 1>, <602 4>, +<603 1>, <604 4>, +<605 1>, <606 4>, +<607 1>, <608 4>; +}; -- 2.16.2
Re: [PATCH 2/3] crypto: hisilicon SEC security accelerator driver
On Fri, 20 Jul 2018 20:17:22 +0200 Stephan Müller wrote: > Am Montag, 16. Juli 2018, 12:43:41 CEST schrieb Jonathan Cameron: > > Hi Jonathan, > > > +static int sec_alg_skcipher_setkey_aes_xts(struct crypto_skcipher *tfm, > > + const u8 *key, unsigned int > > keylen) +{ > > + enum sec_cipher_alg alg; > > + > > + switch (keylen) { > > + case AES_KEYSIZE_128 * 2: > > + alg = SEC_C_AES_XTS_128; > > + break; > > + case AES_KEYSIZE_256 * 2: > > + alg = SEC_C_AES_XTS_256; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + return sec_alg_skcipher_setkey(tfm, key, keylen, alg); > > +} > > Can you please call the function xts_check_key or xts_verify_key before > setting the key? > Will do. Thanks, Jonathan
[PATCH] crypto: tcrypt - reschedule during speed tests
Avoid RCU stalls in the case of non-preemptible kernel and lengthy speed tests by rescheduling when advancing from one block size to another. Signed-off-by: Horia Geantă --- crypto/tcrypt.c | 36 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 078ec36007bf..bdde95e8d369 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -415,12 +415,14 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, } - if (secs) + if (secs) { ret = test_mb_aead_jiffies(data, enc, *b_size, secs, num_mb); - else + cond_resched(); + } else { ret = test_mb_aead_cycles(data, enc, *b_size, num_mb); + } if (ret) { pr_err("%s() failed return code=%d\n", e, ret); @@ -660,11 +662,13 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, *b_size + (enc ? 0 : authsize), iv); - if (secs) + if (secs) { ret = test_aead_jiffies(req, enc, *b_size, secs); - else + cond_resched(); + } else { ret = test_aead_cycles(req, enc, *b_size); + } if (ret) { pr_err("%s() failed return code=%d\n", e, ret); @@ -876,11 +880,13 @@ static void test_mb_ahash_speed(const char *algo, unsigned int secs, i, speed[i].blen, speed[i].plen, speed[i].blen / speed[i].plen); - if (secs) + if (secs) { ret = test_mb_ahash_jiffies(data, speed[i].blen, secs, num_mb); - else + cond_resched(); + } else { ret = test_mb_ahash_cycles(data, speed[i].blen, num_mb); + } if (ret) { @@ -1103,12 +1109,14 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, ahash_request_set_crypt(req, sg, output, speed[i].plen); - if (secs) + if (secs) { ret = test_ahash_jiffies(req, speed[i].blen, speed[i].plen, output, secs); - else + cond_resched(); + } else { ret = test_ahash_cycles(req, speed[i].blen, speed[i].plen, output); + } if (ret) { pr_err("hashing failed ret=%d\n", ret); @@ -1367,13 +1375,15 @@ static void test_mb_skcipher_speed(const char *algo, int enc, int secs, iv); } - if (secs) + if (secs) { ret = test_mb_acipher_jiffies(data, enc, *b_size, secs, num_mb); - else + cond_resched(); + } else { ret = test_mb_acipher_cycles(data, enc, *b_size, num_mb); + } if (ret) { pr_err("%s() failed flags=%x\n", e, @@ -1581,12 +1591,14 @@ static void test_skcipher_speed(const char *algo, int enc, unsigned int secs, skcipher_request_set_crypt(req, sg, sg, *b_size, iv); - if (secs) + if (secs) { ret = test_acipher_jiffies(req, enc, *b_size, secs); - else + cond_resched(); + } else { ret = test_acipher_cycles(req, enc, *b_size); + } if (ret) { pr_err("%s() failed flags=%x\n", e, -- 2.16.2