Re: [PATCH 2/4] crypto: aesni - Enable one-sided zero copy for gcm(aes) request buffers
Am Dienstag, 23. Januar 2018, 00:04:01 CET schrieb Junaid Shahid: Hi Junaid, > gcmaes_encrypt/decrypt perform zero-copy crypto if both the source and > destination satisfy certain conditions (single sglist entry located in > low-mem or within a single high-mem page). But two copies are done > otherwise, even if one of source or destination still satisfies the > zero-copy conditions. This optimization is now extended to avoid the > copy on the side that does satisfy the zero-copy conditions. > > Signed-off-by: Junaid Shahid> --- > arch/x86/crypto/aesni-intel_glue.c | 256 > +++-- 1 file changed, 134 insertions(+), > 122 deletions(-) > > diff --git a/arch/x86/crypto/aesni-intel_glue.c > b/arch/x86/crypto/aesni-intel_glue.c index 3bf3dcf29825..a46eb2d25f71 > 100644 > --- a/arch/x86/crypto/aesni-intel_glue.c > +++ b/arch/x86/crypto/aesni-intel_glue.c > @@ -744,136 +744,148 @@ static int generic_gcmaes_set_authsize(struct > crypto_aead *tfm, return 0; > } > > +static bool is_mappable(struct scatterlist *sgl, unsigned long len) > +{ > + return (!PageHighMem(sg_page(sgl)) || sgl->offset + len <= PAGE_SIZE) > +&& len <= sgl->length; Please integrate the patch https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg30542.html @Herbert: If this patch series goes in, then the mentioned patch would not be needed for the current implementation, but only for stable. Ciao Stephan
Re: [PATCH] crypto: chelsio - Delete stray tabs in create_authenc_wr()
On 22-01-2018 15:51, Dan Carpenter wrote: > We removed some if statements but left these statements indented too > far. HI Dan, Change already applied to cryptodev tree. https://www.mail-archive.com/linux-crypto@vger.kernel.org/msg30560.html > > Signed-off-by: Dan Carpenter> > diff --git a/drivers/crypto/chelsio/chcr_algo.c > b/drivers/crypto/chelsio/chcr_algo.c > index a9c894bf9c01..34a02d690548 100644 > --- a/drivers/crypto/chelsio/chcr_algo.c > +++ b/drivers/crypto/chelsio/chcr_algo.c > @@ -2112,11 +2112,11 @@ static struct sk_buff *create_authenc_wr(struct > aead_request *req, > error = chcr_aead_common_init(req, op_type); > if (error) > return ERR_PTR(error); > - dnents = sg_nents_xlen(req->dst, assoclen, CHCR_DST_SG_SIZE, 0); > - dnents += sg_nents_xlen(req->dst, req->cryptlen + > - (op_type ? -authsize : authsize), CHCR_DST_SG_SIZE, > - req->assoclen); > - dnents += MIN_AUTH_SG; // For IV > + dnents = sg_nents_xlen(req->dst, assoclen, CHCR_DST_SG_SIZE, 0); > + dnents += sg_nents_xlen(req->dst, req->cryptlen + > + (op_type ? -authsize : authsize), CHCR_DST_SG_SIZE, > + req->assoclen); > + dnents += MIN_AUTH_SG; // For IV > > dst_size = get_space_for_phys_dsgl(dnents); > kctx_len = (ntohl(KEY_CONTEXT_CTX_LEN_V(aeadctx->key_ctx_hdr)) << 4)
[PATCH -next] hwrng: make symbol imx_rngc_pm_ops static
Fixes the following sparse warnings: drivers/char/hw_random/imx-rngc.c:303:1: warning: symbol 'imx_rngc_pm_ops' was not declared. Should it be static? Signed-off-by: Wei Yongjun--- drivers/char/hw_random/imx-rngc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/hw_random/imx-rngc.c b/drivers/char/hw_random/imx-rngc.c index eca8724..250123b 100644 --- a/drivers/char/hw_random/imx-rngc.c +++ b/drivers/char/hw_random/imx-rngc.c @@ -300,7 +300,7 @@ static int __maybe_unused imx_rngc_resume(struct device *dev) return 0; } -SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); +static SIMPLE_DEV_PM_OPS(imx_rngc_pm_ops, imx_rngc_suspend, imx_rngc_resume); static const struct of_device_id imx_rngc_dt_ids[] = { { .compatible = "fsl,imx25-rngb", .data = NULL, },
Re: [PATCH -next] hwrng: bcm2835 - Remove redundant dev_err call in bcm2835_rng_probe()
On 01/17/2018 03:40 AM, Wei Yongjun wrote: > There is a error message within devm_ioremap_resource > already, so remove the dev_err call to avoid redundant > error message. > > Signed-off-by: Wei YongjunAcked-by: Florian Fainelli -- Florian
[PATCH 0/4] crypto: aesni - Use zero-copy for gcm(aes) buffers that are partially contiguous
Currently, the AESNI gcm(aes) implementation uses zero-copy only when the entire src and dest request buffers, including the AAD, the data and the Auth Tag are contiguous. This series enables the use of zero-copy even if the AAD and/or Auth Tag are in different buffers than the actual data, as long as each of them individually satisfies the zero-copy conditions (i.e. the entire buffer is either in low-mem or within a single high-mem page). Furthermore, it also enables the use of zero-copy even if only one of src and dest satisfies these conditions rather than only when both of them do. Junaid Shahid (4): crypto: aesni - Fix out-of-bounds access of the AAD buffer in AVX gcm-aesni crypto: aesni - Enable one-sided zero copy for gcm(aes) request buffers crypto: aesni - Directly use kmap_atomic instead of scatter_walk object in gcm(aes) crypto: aesni - Use zero-copy for gcm(aes) even if the AAD/Data/AuthTag are separate arch/x86/crypto/aesni-intel_avx-x86_64.S | 154 +--- arch/x86/crypto/aesni-intel_glue.c | 307 +++ 2 files changed, 227 insertions(+), 234 deletions(-) -- 2.16.0.rc1.238.g530d649a79-goog
[PATCH 2/4] crypto: aesni - Enable one-sided zero copy for gcm(aes) request buffers
gcmaes_encrypt/decrypt perform zero-copy crypto if both the source and destination satisfy certain conditions (single sglist entry located in low-mem or within a single high-mem page). But two copies are done otherwise, even if one of source or destination still satisfies the zero-copy conditions. This optimization is now extended to avoid the copy on the side that does satisfy the zero-copy conditions. Signed-off-by: Junaid Shahid--- arch/x86/crypto/aesni-intel_glue.c | 256 +++-- 1 file changed, 134 insertions(+), 122 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 3bf3dcf29825..a46eb2d25f71 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -744,136 +744,148 @@ static int generic_gcmaes_set_authsize(struct crypto_aead *tfm, return 0; } +static bool is_mappable(struct scatterlist *sgl, unsigned long len) +{ + return (!PageHighMem(sg_page(sgl)) || sgl->offset + len <= PAGE_SIZE) + && len <= sgl->length; +} + +/* + * Maps the sglist buffer and returns a pointer to the mapped buffer in + * data_buf. + * + * If direct mapping is not feasible, then allocates a bounce buffer if one + * isn't already available in bounce_buf, and returns a pointer to the bounce + * buffer in data_buf. + * + * When the buffer is no longer needed, put_request_buffer() should be called on + * the data_buf and the bounce_buf should be freed using kfree(). + */ +static int get_request_buffer(struct scatterlist *sgl, + struct scatter_walk *sg_walk, + unsigned long bounce_buf_size, + u8 **data_buf, u8 **bounce_buf, bool *mapped) +{ + if (sg_is_last(sgl) && is_mappable(sgl, sgl->length)) { + *mapped = true; + scatterwalk_start(sg_walk, sgl); + *data_buf = scatterwalk_map(sg_walk); + return 0; + } + + *mapped = false; + + if (*bounce_buf == NULL) { + *bounce_buf = kmalloc(bounce_buf_size, GFP_ATOMIC); + if (unlikely(*bounce_buf == NULL)) + return -ENOMEM; + } + + *data_buf = *bounce_buf; + return 0; +} + +static void put_request_buffer(u8 *data_buf, unsigned long len, bool mapped, + struct scatter_walk *sg_walk, bool output) +{ + if (mapped) { + scatterwalk_unmap(data_buf); + scatterwalk_advance(sg_walk, len); + scatterwalk_done(sg_walk, output, 0); + } +} + +/* + * Performs the encryption/decryption operation for the given request. The src + * and dst sglists in the request are directly mapped if possible. Otherwise, a + * bounce buffer is allocated and used to copy the data from the src or to the + * dst, or both. + */ +static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, + u8 *hash_subkey, u8 *iv, void *aes_ctx, bool decrypt) +{ + u8 *src, *dst, *assoc, *bounce_buf = NULL; + bool src_mapped = false, dst_mapped = false; + struct crypto_aead *tfm = crypto_aead_reqtfm(req); + unsigned long auth_tag_len = crypto_aead_authsize(tfm); + unsigned long data_len = req->cryptlen - (decrypt ? auth_tag_len : 0); + struct scatter_walk src_sg_walk; + struct scatter_walk dst_sg_walk = {}; + int retval = 0; + unsigned long bounce_buf_size = data_len + auth_tag_len + req->assoclen; + + if (auth_tag_len > 16) + return -EINVAL; + + retval = get_request_buffer(req->src, _sg_walk, bounce_buf_size, + , _buf, _mapped); + if (retval) + goto exit; + + src = assoc + req->assoclen; + + if (req->src == req->dst) { + dst = src; + dst_mapped = src_mapped; + } else { + retval = get_request_buffer(req->dst, _sg_walk, + bounce_buf_size, , _buf, + _mapped); + if (retval) + goto exit; + + dst += req->assoclen; + } + + if (!src_mapped) + scatterwalk_map_and_copy(bounce_buf, req->src, 0, +req->assoclen + req->cryptlen, 0); + + kernel_fpu_begin(); + + if (decrypt) { + u8 gen_auth_tag[16]; + + aesni_gcm_dec_tfm(aes_ctx, dst, src, data_len, iv, + hash_subkey, assoc, assoclen, + gen_auth_tag, auth_tag_len); + /* Compare generated tag with passed in tag. */ + if (crypto_memneq(src + data_len, gen_auth_tag, auth_tag_len)) + retval = -EBADMSG; + + } else + aesni_gcm_enc_tfm(aes_ctx, dst,
[PATCH 1/4] crypto: aesni - Fix out-of-bounds access of the AAD buffer in AVX gcm-aesni
The AVX/AVX2 versions of gcm-aes encryption/decryption functions can access memory after the end of the AAD buffer if the AAD length is not a multiple of 4 bytes. It didn't matter as long as the AAD and data buffers were always contiguous, since the AVX version are not used for small data sizes and hence enough data bytes were always present to cover the over-run. However, now that we have support for non-contiguous AAD and data buffers, that is no longer the case. This can potentially result in accessing a page that is not mapped and thus causing the machine to crash. This patch fixes that by reading the last <16 byte block of the AAD byte-by-byte and optionally via an 8-byte load if the block was at least 8 bytes. Signed-off-by: Junaid Shahid--- arch/x86/crypto/aesni-intel_avx-x86_64.S | 154 +-- 1 file changed, 42 insertions(+), 112 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_avx-x86_64.S b/arch/x86/crypto/aesni-intel_avx-x86_64.S index faecb1518bf8..97029059dc1a 100644 --- a/arch/x86/crypto/aesni-intel_avx-x86_64.S +++ b/arch/x86/crypto/aesni-intel_avx-x86_64.S @@ -106,14 +106,6 @@ ## ##AAD Format with 64-bit Extended Sequence Number ## -## -## aadLen: -## from the definition of the spec, aadLen can only be 8 or 12 bytes. -## The code additionally supports aadLen of length 16 bytes. -## -## TLen: -## from the definition of the spec, TLen can only be 8, 12 or 16 bytes. -## ## poly = x^128 + x^127 + x^126 + x^121 + 1 ## throughout the code, one tab and two tab indentations are used. one tab is ## for GHASH part, two tabs is for AES part. @@ -155,30 +147,6 @@ SHIFT_MASK: .octa 0x0f0e0d0c0b0a09080706050403020100 ALL_F: .octa 0x .octa 0x -.section .rodata -.align 16 -.type aad_shift_arr, @object -.size aad_shift_arr, 272 -aad_shift_arr: -.octa 0x -.octa 0xff0C -.octa 0x0D0C -.octa 0xff0E0D0C -.octa 0x0F0E0D0C -.octa 0xff0C0B0A0908 -.octa 0x0D0C0B0A0908 -.octa 0xff0E0D0C0B0A0908 -.octa 0x0F0E0D0C0B0A0908 -.octa 0xff0C0B0A090807060504 -.octa 0x0D0C0B0A090807060504 -.octa 0xff0E0D0C0B0A090807060504 -.octa 0x0F0E0D0C0B0A090807060504 -.octa 0xff0C0B0A09080706050403020100 -.octa 0x0D0C0B0A09080706050403020100 -.octa 0xff0E0D0C0B0A09080706050403020100 -.octa 0x0F0E0D0C0B0A09080706050403020100 - - .text @@ -280,6 +248,36 @@ VARIABLE_OFFSET = 16*8 vaesenclast 16*10(arg1), \XMM0, \XMM0 .endm +# Reads DLEN bytes starting at DPTR and stores in XMMDst +# where 0 < DLEN < 16 +# Clobbers %rax, DLEN and XMM1 +.macro READ_PARTIAL_BLOCK DPTR DLEN XMM1 XMMDst +cmp $8, \DLEN +jl _read_lt8_\@ +movq (\DPTR), \XMMDst +sub $8, \DLEN +jz _done_read_partial_block_\@ + xor %eax, %eax +_read_next_byte_\@: +shl $8, %rax +mov 7(\DPTR, \DLEN, 1), %al +dec \DLEN +jnz _read_next_byte_\@ +movq %rax, \XMM1 + pslldq $8, \XMM1 +por \XMM1, \XMMDst + jmp _done_read_partial_block_\@ +_read_lt8_\@: + xor %eax, %eax +_read_next_byte_lt8_\@: +shl $8, %rax +mov -1(\DPTR, \DLEN, 1), %al +dec \DLEN +jnz _read_next_byte_lt8_\@ +movq %rax, \XMMDst +_done_read_partial_block_\@: +.endm + #ifdef CONFIG_AS_AVX ### # GHASH_MUL MACRO to implement: Data*HashKey mod (128,127,126,121,0) @@ -400,63 +398,29 @@ VARIABLE_OFFSET = 16*8 setreg mov arg6, %r10 # r10 = AAD - mov arg7, %r12 # r12 = aadLen - - - mov %r12, %r11 + mov arg7, %r11 # r11 = aadLen vpxor reg_j, reg_j, reg_j vpxor reg_i, reg_i, reg_i cmp $16, %r11 - jl _get_AAD_rest8\@ + jl _get_AAD_rest\@ _get_AAD_blocks\@: vmovdqu (%r10), reg_i vpshufb SHUF_MASK(%rip), reg_i, reg_i vpxor reg_i, reg_j, reg_j GHASH_MUL_AVX reg_j, \T2, \T1, \T3, \T4, \T5, \T6 add $16, %r10 - sub $16, %r12 sub $16, %r11 cmp $16, %r11 jge _get_AAD_blocks\@ vmovdqu reg_j, reg_i + + /* read the last <16B of AAD. */ +_get_AAD_rest\@: cmp $0, %r11 je _get_AAD_done\@ - vpxor reg_i, reg_i, reg_i - - /* read the
[PATCH 3/4] crypto: aesni - Directly use kmap_atomic instead of scatter_walk object in gcm(aes)
gcmaes_crypt uses a scatter_walk object to map and unmap the crypto request sglists. But the only purpose that appears to serve here is to allow the D-Cache to be flushed at the end for pages that were used as output. However, that is not applicable on x86, so we can avoid using the scatter_walk object for simplicity. Signed-off-by: Junaid Shahid--- arch/x86/crypto/aesni-intel_glue.c | 36 +++- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index a46eb2d25f71..03892dd80a12 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -750,6 +750,11 @@ static bool is_mappable(struct scatterlist *sgl, unsigned long len) && len <= sgl->length; } +static u8 *map_buffer(struct scatterlist *sgl) +{ + return kmap_atomic(sg_page(sgl)) + sgl->offset; +} + /* * Maps the sglist buffer and returns a pointer to the mapped buffer in * data_buf. @@ -762,14 +767,12 @@ static bool is_mappable(struct scatterlist *sgl, unsigned long len) * the data_buf and the bounce_buf should be freed using kfree(). */ static int get_request_buffer(struct scatterlist *sgl, - struct scatter_walk *sg_walk, unsigned long bounce_buf_size, u8 **data_buf, u8 **bounce_buf, bool *mapped) { if (sg_is_last(sgl) && is_mappable(sgl, sgl->length)) { *mapped = true; - scatterwalk_start(sg_walk, sgl); - *data_buf = scatterwalk_map(sg_walk); + *data_buf = map_buffer(sgl); return 0; } @@ -785,14 +788,10 @@ static int get_request_buffer(struct scatterlist *sgl, return 0; } -static void put_request_buffer(u8 *data_buf, unsigned long len, bool mapped, - struct scatter_walk *sg_walk, bool output) +static void put_request_buffer(u8 *data_buf, bool mapped) { - if (mapped) { - scatterwalk_unmap(data_buf); - scatterwalk_advance(sg_walk, len); - scatterwalk_done(sg_walk, output, 0); - } + if (mapped) + kunmap_atomic(data_buf); } /* @@ -809,16 +808,14 @@ static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, struct crypto_aead *tfm = crypto_aead_reqtfm(req); unsigned long auth_tag_len = crypto_aead_authsize(tfm); unsigned long data_len = req->cryptlen - (decrypt ? auth_tag_len : 0); - struct scatter_walk src_sg_walk; - struct scatter_walk dst_sg_walk = {}; int retval = 0; unsigned long bounce_buf_size = data_len + auth_tag_len + req->assoclen; if (auth_tag_len > 16) return -EINVAL; - retval = get_request_buffer(req->src, _sg_walk, bounce_buf_size, - , _buf, _mapped); + retval = get_request_buffer(req->src, bounce_buf_size, , + _buf, _mapped); if (retval) goto exit; @@ -828,9 +825,8 @@ static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, dst = src; dst_mapped = src_mapped; } else { - retval = get_request_buffer(req->dst, _sg_walk, - bounce_buf_size, , _buf, - _mapped); + retval = get_request_buffer(req->dst, bounce_buf_size, , + _buf, _mapped); if (retval) goto exit; @@ -866,11 +862,9 @@ static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, 1); exit: if (req->dst != req->src) - put_request_buffer(dst - req->assoclen, req->dst->length, - dst_mapped, _sg_walk, true); + put_request_buffer(dst - req->assoclen, dst_mapped); - put_request_buffer(assoc, req->src->length, src_mapped, _sg_walk, - false); + put_request_buffer(assoc, src_mapped); kfree(bounce_buf); return retval; -- 2.16.0.rc1.238.g530d649a79-goog
[PATCH 4/4] crypto: aesni - Use zero-copy for gcm(aes) even if the AAD/Data/AuthTag are separate
Enable the use of zero-copy even if the AAD and/or Auth Tag are in different buffers than the actual data, as long as each of them individually satisfies the zero-copy conditions (i.e. the entire buffer is either in low-mem or within a single high-mem page). Signed-off-by: Junaid Shahid--- arch/x86/crypto/aesni-intel_glue.c | 121 +++-- 1 file changed, 89 insertions(+), 32 deletions(-) diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 03892dd80a12..2a44285ed66c 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c @@ -756,42 +756,91 @@ static u8 *map_buffer(struct scatterlist *sgl) } /* - * Maps the sglist buffer and returns a pointer to the mapped buffer in - * data_buf. + * Maps the sglist buffer and returns pointers to the mapped buffers in assoc, + * data and (optionally) auth_tag. * * If direct mapping is not feasible, then allocates a bounce buffer if one - * isn't already available in bounce_buf, and returns a pointer to the bounce - * buffer in data_buf. + * isn't already available in bounce_buf, and returns pointers within the bounce + * buffer in assoc, data and auth_tag. * - * When the buffer is no longer needed, put_request_buffer() should be called on - * the data_buf and the bounce_buf should be freed using kfree(). + * When the buffers are no longer needed, put_request_buffers() should be called + * and the bounce_buf should be freed using kfree(). */ -static int get_request_buffer(struct scatterlist *sgl, - unsigned long bounce_buf_size, - u8 **data_buf, u8 **bounce_buf, bool *mapped) +static int get_request_buffers(struct scatterlist *sgl, + unsigned long assoc_len, unsigned long data_len, + unsigned long auth_tag_len, + u8 **assoc, u8 **data, u8 **auth_tag, + u8 **bounce_buf, bool *mapped) { - if (sg_is_last(sgl) && is_mappable(sgl, sgl->length)) { + struct scatterlist sgl_data_chain[2], sgl_auth_tag_chain[2]; + struct scatterlist *sgl_data, *sgl_auth_tag; + + sgl_data = scatterwalk_ffwd(sgl_data_chain, sgl, assoc_len); + sgl_auth_tag = scatterwalk_ffwd(sgl_auth_tag_chain, sgl, + assoc_len + data_len); + + if (is_mappable(sgl, assoc_len) && is_mappable(sgl_data, data_len) && + (auth_tag == NULL || is_mappable(sgl_auth_tag, auth_tag_len))) { *mapped = true; - *data_buf = map_buffer(sgl); + + *assoc = map_buffer(sgl); + + if (sgl->length >= assoc_len + data_len) + *data = *assoc + assoc_len; + else + *data = map_buffer(sgl_data); + + if (auth_tag != NULL) { + if (sgl_data->length >= data_len + auth_tag_len) + *auth_tag = *data + data_len; + else + *auth_tag = map_buffer(sgl_auth_tag); + } + return 0; } *mapped = false; if (*bounce_buf == NULL) { - *bounce_buf = kmalloc(bounce_buf_size, GFP_ATOMIC); + *bounce_buf = kmalloc(assoc_len + data_len + auth_tag_len, + GFP_ATOMIC); if (unlikely(*bounce_buf == NULL)) return -ENOMEM; } - *data_buf = *bounce_buf; + *assoc = *bounce_buf; + *data = *assoc + assoc_len; + + if (auth_tag != NULL) + *auth_tag = *data + data_len; + return 0; } -static void put_request_buffer(u8 *data_buf, bool mapped) +static void put_request_buffers(struct scatterlist *sgl, bool mapped, + u8 *assoc, u8 *data, u8 *auth_tag, + unsigned long assoc_len, + unsigned long data_len, + unsigned long auth_tag_len) { - if (mapped) - kunmap_atomic(data_buf); + struct scatterlist sgl_data_chain[2]; + struct scatterlist *sgl_data; + + if (!mapped) + return; + + sgl_data = scatterwalk_ffwd(sgl_data_chain, sgl, assoc_len); + + /* The unmaps need to be done in reverse order of the maps. */ + + if (auth_tag != NULL && sgl_data->length < data_len + auth_tag_len) + kunmap_atomic(auth_tag); + + if (sgl->length < assoc_len + data_len) + kunmap_atomic(data); + + kunmap_atomic(assoc); } /* @@ -803,34 +852,38 @@ static void put_request_buffer(u8 *data_buf, bool mapped) static int gcmaes_crypt(struct aead_request *req, unsigned int assoclen, u8 *hash_subkey, u8 *iv, void *aes_ctx, bool decrypt) { -
Re: [PATCH 0/8] crypto: arm64+generic - SHA3/SHA-512/SM-3 roundup
On 22 January 2018 at 20:51, Arnd Bergmannwrote: > On Mon, Jan 22, 2018 at 3:54 PM, Arnd Bergmann wrote: >> On Fri, Jan 19, 2018 at 1:04 PM, Ard Biesheuvel >> I'm doing a little more randconfig build testing here now, will write back by >> the end of today in the unlikely case that if I find anything else wrong. > > Did a few hundred randconfig builds, everything fine as expected. > Thanks Arnd
Re: [PATCH 0/8] crypto: arm64+generic - SHA3/SHA-512/SM-3 roundup
On Mon, Jan 22, 2018 at 3:54 PM, Arnd Bergmannwrote: > On Fri, Jan 19, 2018 at 1:04 PM, Ard Biesheuvel > I'm doing a little more randconfig build testing here now, will write back by > the end of today in the unlikely case that if I find anything else wrong. Did a few hundred randconfig builds, everything fine as expected. Arnd
Re: [PATCH 0/8] crypto: arm64+generic - SHA3/SHA-512/SM-3 roundup
On Fri, Jan 19, 2018 at 1:04 PM, Ard Biesheuvelwrote: > This supersedes all outstanding patches from me related to SHA-3, SHA-512 > or SM-3. > > - fix a correctness issue in the SHA-3 code (#1) and a performance issue (#2), > the first one is definitely a -stable candidate, the second one potentially > as well > - patches #3 and #4 make the generic SHA-3 code reusable as a fallback for the > accelerated code introduced in #6 > - patch #5 adds some SHA-3 test cases > - patch #6 implements SHA-3 using special arm64 instructions > - patch #7 implements the Chinese SM3 secure hash algorithm using special > arm64 instructions > - patch #8 contains some fixes for the recently queued SHA-512 arm64 code. > > Ard Biesheuvel (8): > crypto/generic: sha3 - fixes for alignment and big endian operation > crypto/generic: sha3: rewrite KECCAK transform to help the compiler > optimize > crypto/generic: sha3 - simplify code > crypto/generic: sha3 - export init/update/final routines > crypto/testmgr: sha3 - add new testcases > crypto/arm64: sha3 - new v8.2 Crypto Extensions implementation > crypto/arm64: sm3 - new v8.2 Crypto Extensions implementation > crypto/arm64: sha512 - fix/improve new v8.2 Crypto Extensions code I can confirm that patch 8 fixes the issues I saw earlier, it would be good to have that merged quickly. I'm doing a little more randconfig build testing here now, will write back by the end of today in the unlikely case that if I find anything else wrong. Arnd
Re: [PATCH] crypto: AF_ALG - inline IV support
On Mon, 22 Jan 2018 15:30:39 +0100 Stephan Muellerwrote: > Am Montag, 22. Januar 2018, 15:11:53 CET schrieb Jonathan Cameron: > > Hi Jonathan, Hi Stephan, > > > On Mon, 15 Jan 2018 10:35:34 +0100 > > > > Stephan Mueller wrote: > > > The kernel crypto API requires the caller to set an IV in the request > > > data structure. That request data structure shall define one particular > > > cipher operation. During the cipher operation, the IV is read by the > > > cipher implementation and eventually the potentially updated IV (e.g. > > > in case of CBC) is written back to the memory location the request data > > > structure points to. > > > > > > AF_ALG allows setting the IV with a sendmsg request, where the IV is > > > stored in the AF_ALG context that is unique to one particular AF_ALG > > > socket. Note the analogy: an AF_ALG socket is like a TFM where one > > > recvmsg operation uses one request with the TFM from the socket. > > > > > > AF_ALG these days supports AIO operations with multiple IOCBs. I.e. > > > with one recvmsg call, multiple IOVECs can be specified. Each > > > individual IOCB (derived from one IOVEC) implies that one request data > > > structure is created with the data to be processed by the cipher > > > implementation. The IV that was set with the sendmsg call is registered > > > with the request data structure before the cipher operation. > > > > > > In case of an AIO operation, the cipher operation invocation returns > > > immediately, queuing the request to the hardware. While the AIO request > > > is processed by the hardware, recvmsg processes the next IOVEC for > > > which another request is created. Again, the IV buffer from the AF_ALG > > > socket context is registered with the new request and the cipher > > > operation is invoked. > > > > > > You may now see that there is a potential race condition regarding the > > > IV handling, because there is *no* separate IV buffer for the different > > > requests. This is nicely demonstrated with libkcapi using the following > > > command which creates an AIO request with two IOCBs each encrypting one > > > AES block in CBC mode: > > > > > > kcapi -d 2 -x 9 -e -c "cbc(aes)" -k > > > 8d7dd9b0170ce0b5f2f8e1aa768e01e91da8bfc67fd486d081b28254c99eb423 -i > > > 7fbc02ebf5b93322329df9bfccb635af -p 48981da18e4bb9ef7e2e3162d16b1910 > > > > > > When the first AIO request finishes before the 2nd AIO request is > > > processed, the returned value is: > > > > > > 8b19050f66582cb7f7e4b6c873819b7108afa0eaa7de29bac7d903576b674c32 > > > > > > I.e. two blocks where the IV output from the first request is the IV input > > > to the 2nd block. > > > > > > In case the first AIO request is not completed before the 2nd request > > > commences, the result is two identical AES blocks (i.e. both use the > > > same IV): > > > > > > 8b19050f66582cb7f7e4b6c873819b718b19050f66582cb7f7e4b6c873819b71 > > > > > > This inconsistent result may even lead to the conclusion that there can > > > be a memory corruption in the IV buffer if both AIO requests write to > > > the IV buffer at the same time. > > > > > > The solution is to allow providing the IV data supplied as part of the > > > plaintext/ciphertext. To do so, the AF_ALG interface treats the > > > ALG_SET_OP flag usable with sendmsg as a bit-array allowing to set the > > > cipher operation together with the flag whether the operation should > > > enable support for inline IV handling. > > > > > > If inline IV handling is enabled, the IV is expected to be the first > > > part of the input plaintext/ciphertext. This IV is only used for one > > > cipher operation and will not retained in the kernel for subsequent > > > cipher operations. > > > > > > The AEAD support required a slight re-arragning of the code, because > > > obtaining the IV implies that ctx->used is updated. Thus, the ctx->used > > > access in _aead_recvmsg must be moved below the IV gathering. > > > > > > The AEAD code to find the first SG with data in the TX SGL is moved to a > > > common function as it is required by the IV gathering function as well. > > > > > > This patch does not change the existing interface where user space is > > > allowed to provide an IV via sendmsg. It only extends the interface by > > > giving the user the choice to provide the IV either via sendmsg (the > > > current approach) or as part of the data (the additional approach). > > > > > > Signed-off-by: Stephan Mueller > > > > Firstly it works > > Tested-by: Jonathan Cameron > > Thank you. > > > > Now to be really useful for my particular hardware (which doesn't do > > dependency tracking in its out of order queues) what I need to know is > > whether I need to let previous queued up entries finish before I can run > > this one or not. > > > > Now there is an obvious 'hack' I can use, which is that the above only > > matters is if the IV is still 'in
Re: [PATCH] crypto: AF_ALG - inline IV support
Am Montag, 22. Januar 2018, 15:11:53 CET schrieb Jonathan Cameron: Hi Jonathan, > On Mon, 15 Jan 2018 10:35:34 +0100 > > Stephan Muellerwrote: > > The kernel crypto API requires the caller to set an IV in the request > > data structure. That request data structure shall define one particular > > cipher operation. During the cipher operation, the IV is read by the > > cipher implementation and eventually the potentially updated IV (e.g. > > in case of CBC) is written back to the memory location the request data > > structure points to. > > > > AF_ALG allows setting the IV with a sendmsg request, where the IV is > > stored in the AF_ALG context that is unique to one particular AF_ALG > > socket. Note the analogy: an AF_ALG socket is like a TFM where one > > recvmsg operation uses one request with the TFM from the socket. > > > > AF_ALG these days supports AIO operations with multiple IOCBs. I.e. > > with one recvmsg call, multiple IOVECs can be specified. Each > > individual IOCB (derived from one IOVEC) implies that one request data > > structure is created with the data to be processed by the cipher > > implementation. The IV that was set with the sendmsg call is registered > > with the request data structure before the cipher operation. > > > > In case of an AIO operation, the cipher operation invocation returns > > immediately, queuing the request to the hardware. While the AIO request > > is processed by the hardware, recvmsg processes the next IOVEC for > > which another request is created. Again, the IV buffer from the AF_ALG > > socket context is registered with the new request and the cipher > > operation is invoked. > > > > You may now see that there is a potential race condition regarding the > > IV handling, because there is *no* separate IV buffer for the different > > requests. This is nicely demonstrated with libkcapi using the following > > command which creates an AIO request with two IOCBs each encrypting one > > AES block in CBC mode: > > > > kcapi -d 2 -x 9 -e -c "cbc(aes)" -k > > 8d7dd9b0170ce0b5f2f8e1aa768e01e91da8bfc67fd486d081b28254c99eb423 -i > > 7fbc02ebf5b93322329df9bfccb635af -p 48981da18e4bb9ef7e2e3162d16b1910 > > > > When the first AIO request finishes before the 2nd AIO request is > > processed, the returned value is: > > > > 8b19050f66582cb7f7e4b6c873819b7108afa0eaa7de29bac7d903576b674c32 > > > > I.e. two blocks where the IV output from the first request is the IV input > > to the 2nd block. > > > > In case the first AIO request is not completed before the 2nd request > > commences, the result is two identical AES blocks (i.e. both use the > > same IV): > > > > 8b19050f66582cb7f7e4b6c873819b718b19050f66582cb7f7e4b6c873819b71 > > > > This inconsistent result may even lead to the conclusion that there can > > be a memory corruption in the IV buffer if both AIO requests write to > > the IV buffer at the same time. > > > > The solution is to allow providing the IV data supplied as part of the > > plaintext/ciphertext. To do so, the AF_ALG interface treats the > > ALG_SET_OP flag usable with sendmsg as a bit-array allowing to set the > > cipher operation together with the flag whether the operation should > > enable support for inline IV handling. > > > > If inline IV handling is enabled, the IV is expected to be the first > > part of the input plaintext/ciphertext. This IV is only used for one > > cipher operation and will not retained in the kernel for subsequent > > cipher operations. > > > > The AEAD support required a slight re-arragning of the code, because > > obtaining the IV implies that ctx->used is updated. Thus, the ctx->used > > access in _aead_recvmsg must be moved below the IV gathering. > > > > The AEAD code to find the first SG with data in the TX SGL is moved to a > > common function as it is required by the IV gathering function as well. > > > > This patch does not change the existing interface where user space is > > allowed to provide an IV via sendmsg. It only extends the interface by > > giving the user the choice to provide the IV either via sendmsg (the > > current approach) or as part of the data (the additional approach). > > > > Signed-off-by: Stephan Mueller > > Firstly it works > Tested-by: Jonathan Cameron Thank you. > > Now to be really useful for my particular hardware (which doesn't do > dependency tracking in its out of order queues) what I need to know is > whether I need to let previous queued up entries finish before I can run > this one or not. > > Now there is an obvious 'hack' I can use, which is that the above only > matters is if the IV is still 'in flight'. Given it is still inflight the > memory is in use. Thus until it is finished it's address is clearly only > being used by 'this IV'. > > Hence I can just compare against the address of the IV for the previous > packet. If it changed we know there is no need to wait for previous
Re: [PATCH] crypto: AF_ALG - inline IV support
On Mon, 15 Jan 2018 10:35:34 +0100 Stephan Muellerwrote: > The kernel crypto API requires the caller to set an IV in the request > data structure. That request data structure shall define one particular > cipher operation. During the cipher operation, the IV is read by the > cipher implementation and eventually the potentially updated IV (e.g. > in case of CBC) is written back to the memory location the request data > structure points to. > > AF_ALG allows setting the IV with a sendmsg request, where the IV is > stored in the AF_ALG context that is unique to one particular AF_ALG > socket. Note the analogy: an AF_ALG socket is like a TFM where one > recvmsg operation uses one request with the TFM from the socket. > > AF_ALG these days supports AIO operations with multiple IOCBs. I.e. > with one recvmsg call, multiple IOVECs can be specified. Each > individual IOCB (derived from one IOVEC) implies that one request data > structure is created with the data to be processed by the cipher > implementation. The IV that was set with the sendmsg call is registered > with the request data structure before the cipher operation. > > In case of an AIO operation, the cipher operation invocation returns > immediately, queuing the request to the hardware. While the AIO request > is processed by the hardware, recvmsg processes the next IOVEC for > which another request is created. Again, the IV buffer from the AF_ALG > socket context is registered with the new request and the cipher > operation is invoked. > > You may now see that there is a potential race condition regarding the > IV handling, because there is *no* separate IV buffer for the different > requests. This is nicely demonstrated with libkcapi using the following > command which creates an AIO request with two IOCBs each encrypting one > AES block in CBC mode: > > kcapi -d 2 -x 9 -e -c "cbc(aes)" -k > 8d7dd9b0170ce0b5f2f8e1aa768e01e91da8bfc67fd486d081b28254c99eb423 -i > 7fbc02ebf5b93322329df9bfccb635af -p 48981da18e4bb9ef7e2e3162d16b1910 > > When the first AIO request finishes before the 2nd AIO request is > processed, the returned value is: > > 8b19050f66582cb7f7e4b6c873819b7108afa0eaa7de29bac7d903576b674c32 > > I.e. two blocks where the IV output from the first request is the IV input > to the 2nd block. > > In case the first AIO request is not completed before the 2nd request > commences, the result is two identical AES blocks (i.e. both use the > same IV): > > 8b19050f66582cb7f7e4b6c873819b718b19050f66582cb7f7e4b6c873819b71 > > This inconsistent result may even lead to the conclusion that there can > be a memory corruption in the IV buffer if both AIO requests write to > the IV buffer at the same time. > > The solution is to allow providing the IV data supplied as part of the > plaintext/ciphertext. To do so, the AF_ALG interface treats the > ALG_SET_OP flag usable with sendmsg as a bit-array allowing to set the > cipher operation together with the flag whether the operation should > enable support for inline IV handling. > > If inline IV handling is enabled, the IV is expected to be the first > part of the input plaintext/ciphertext. This IV is only used for one > cipher operation and will not retained in the kernel for subsequent > cipher operations. > > The AEAD support required a slight re-arragning of the code, because > obtaining the IV implies that ctx->used is updated. Thus, the ctx->used > access in _aead_recvmsg must be moved below the IV gathering. > > The AEAD code to find the first SG with data in the TX SGL is moved to a > common function as it is required by the IV gathering function as well. > > This patch does not change the existing interface where user space is > allowed to provide an IV via sendmsg. It only extends the interface by > giving the user the choice to provide the IV either via sendmsg (the > current approach) or as part of the data (the additional approach). > > Signed-off-by: Stephan Mueller Firstly it works Tested-by: Jonathan Cameron Now to be really useful for my particular hardware (which doesn't do dependency tracking in its out of order queues) what I need to know is whether I need to let previous queued up entries finish before I can run this one or not. Now there is an obvious 'hack' I can use, which is that the above only matters is if the IV is still 'in flight'. Given it is still inflight the memory is in use. Thus until it is finished it's address is clearly only being used by 'this IV'. Hence I can just compare against the address of the IV for the previous packet. If it changed we know there is no need to wait for previous packets to finish. I'll still have to be a little careful to avoid DoS issues if we flip from one mode to the other but I can do that by ensuring my software queue is empty before pushing to the hardware queue. Anyhow using the address does seem a little fragile, any suggestions for a better
[PATCH] crypto: chelsio - Delete stray tabs in create_authenc_wr()
We removed some if statements but left these statements indented too far. Signed-off-by: Dan Carpenterdiff --git a/drivers/crypto/chelsio/chcr_algo.c b/drivers/crypto/chelsio/chcr_algo.c index a9c894bf9c01..34a02d690548 100644 --- a/drivers/crypto/chelsio/chcr_algo.c +++ b/drivers/crypto/chelsio/chcr_algo.c @@ -2112,11 +2112,11 @@ static struct sk_buff *create_authenc_wr(struct aead_request *req, error = chcr_aead_common_init(req, op_type); if (error) return ERR_PTR(error); - dnents = sg_nents_xlen(req->dst, assoclen, CHCR_DST_SG_SIZE, 0); - dnents += sg_nents_xlen(req->dst, req->cryptlen + - (op_type ? -authsize : authsize), CHCR_DST_SG_SIZE, - req->assoclen); - dnents += MIN_AUTH_SG; // For IV + dnents = sg_nents_xlen(req->dst, assoclen, CHCR_DST_SG_SIZE, 0); + dnents += sg_nents_xlen(req->dst, req->cryptlen + + (op_type ? -authsize : authsize), CHCR_DST_SG_SIZE, + req->assoclen); + dnents += MIN_AUTH_SG; // For IV dst_size = get_space_for_phys_dsgl(dnents); kctx_len = (ntohl(KEY_CONTEXT_CTX_LEN_V(aeadctx->key_ctx_hdr)) << 4)
[PATCH v2 3/7] crypto: ccree: add skcipher support
Add CryptoCell skcipher support Signed-off-by: Gilad Ben-Yossef--- drivers/crypto/ccree/Makefile|2 +- drivers/crypto/ccree/cc_buffer_mgr.c | 125 drivers/crypto/ccree/cc_buffer_mgr.h |8 + drivers/crypto/ccree/cc_cipher.c | 1130 ++ drivers/crypto/ccree/cc_cipher.h | 59 ++ drivers/crypto/ccree/cc_driver.c | 11 + drivers/crypto/ccree/cc_driver.h |6 +- 7 files changed, 1339 insertions(+), 2 deletions(-) create mode 100644 drivers/crypto/ccree/cc_cipher.c create mode 100644 drivers/crypto/ccree/cc_cipher.h diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile index 6b204ab..a7fecad 100644 --- a/drivers/crypto/ccree/Makefile +++ b/drivers/crypto/ccree/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o -ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_ivgen.o cc_sram_mgr.o +ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_ivgen.o cc_sram_mgr.o ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c index 4c67579..46be101 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.c +++ b/drivers/crypto/ccree/cc_buffer_mgr.c @@ -8,6 +8,7 @@ #include "cc_buffer_mgr.h" #include "cc_lli_defs.h" +#include "cc_cipher.h" enum dma_buffer_type { DMA_NULL_TYPE = -1, @@ -347,6 +348,130 @@ static int cc_map_sg(struct device *dev, struct scatterlist *sg, return 0; } +void cc_unmap_cipher_request(struct device *dev, void *ctx, +unsigned int ivsize, struct scatterlist *src, +struct scatterlist *dst) +{ + struct cipher_req_ctx *req_ctx = (struct cipher_req_ctx *)ctx; + + if (req_ctx->gen_ctx.iv_dma_addr) { + dev_dbg(dev, "Unmapped iv: iv_dma_addr=%pad iv_size=%u\n", + _ctx->gen_ctx.iv_dma_addr, ivsize); + dma_unmap_single(dev, req_ctx->gen_ctx.iv_dma_addr, +ivsize, +req_ctx->is_giv ? DMA_BIDIRECTIONAL : +DMA_TO_DEVICE); + } + /* Release pool */ + if (req_ctx->dma_buf_type == CC_DMA_BUF_MLLI && + req_ctx->mlli_params.mlli_virt_addr) { + dma_pool_free(req_ctx->mlli_params.curr_pool, + req_ctx->mlli_params.mlli_virt_addr, + req_ctx->mlli_params.mlli_dma_addr); + } + + dma_unmap_sg(dev, src, req_ctx->in_nents, DMA_BIDIRECTIONAL); + dev_dbg(dev, "Unmapped req->src=%pK\n", sg_virt(src)); + + if (src != dst) { + dma_unmap_sg(dev, dst, req_ctx->out_nents, DMA_BIDIRECTIONAL); + dev_dbg(dev, "Unmapped req->dst=%pK\n", sg_virt(dst)); + } +} + +int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx, + unsigned int ivsize, unsigned int nbytes, + void *info, struct scatterlist *src, + struct scatterlist *dst, gfp_t flags) +{ + struct cipher_req_ctx *req_ctx = (struct cipher_req_ctx *)ctx; + struct mlli_params *mlli_params = _ctx->mlli_params; + struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle; + struct device *dev = drvdata_to_dev(drvdata); + struct buffer_array sg_data; + u32 dummy = 0; + int rc = 0; + u32 mapped_nents = 0; + + req_ctx->dma_buf_type = CC_DMA_BUF_DLLI; + mlli_params->curr_pool = NULL; + sg_data.num_of_buffers = 0; + + /* Map IV buffer */ + if (ivsize) { + dump_byte_array("iv", (u8 *)info, ivsize); + req_ctx->gen_ctx.iv_dma_addr = + dma_map_single(dev, (void *)info, + ivsize, + req_ctx->is_giv ? DMA_BIDIRECTIONAL : + DMA_TO_DEVICE); + if (dma_mapping_error(dev, req_ctx->gen_ctx.iv_dma_addr)) { + dev_err(dev, "Mapping iv %u B at va=%pK for DMA failed\n", + ivsize, info); + return -ENOMEM; + } + dev_dbg(dev, "Mapped iv %u B at va=%pK to dma=%pad\n", + ivsize, info, _ctx->gen_ctx.iv_dma_addr); + } else { + req_ctx->gen_ctx.iv_dma_addr = 0; + } + + /* Map the src SGL */ + rc = cc_map_sg(dev, src, nbytes, DMA_BIDIRECTIONAL, _ctx->in_nents, + LLI_MAX_NUM_OF_DATA_ENTRIES, , _nents); + if (rc) { + rc = -ENOMEM; + goto cipher_exit; + } + if (mapped_nents > 1) + req_ctx->dma_buf_type = CC_DMA_BUF_MLLI; + + if (src == dst) { + /* Handle
[PATCH v2 1/7] staging: ccree: rename staging ver and mark as broken
Rename the Kconfig var of the staging tree version of the driver in preparation of introducing the final version of the driver into the cryptodev tree to avoid link time symbol collisions. Signed-off-by: Gilad Ben-Yossef--- drivers/staging/ccree/Kconfig | 4 ++-- drivers/staging/ccree/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/ccree/Kconfig b/drivers/staging/ccree/Kconfig index 0b3092b..a84b6ab 100644 --- a/drivers/staging/ccree/Kconfig +++ b/drivers/staging/ccree/Kconfig @@ -1,6 +1,6 @@ -config CRYPTO_DEV_CCREE +config CRYPTO_DEV_CCREE_OLD tristate "Support for ARM TrustZone CryptoCell C7XX family of Crypto accelerators" - depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA + depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA && BROKEN default n select CRYPTO_HASH select CRYPTO_BLKCIPHER diff --git a/drivers/staging/ccree/Makefile b/drivers/staging/ccree/Makefile index ae702f3..1e7d105 100644 --- a/drivers/staging/ccree/Makefile +++ b/drivers/staging/ccree/Makefile @@ -1,3 +1,3 @@ -obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o +obj-$(CONFIG_CRYPTO_DEV_CCREE_OLD) := ccree.o ccree-y := ssi_driver.o ssi_sysfs.o ssi_buffer_mgr.o ssi_request_mgr.o ssi_cipher.o ssi_hash.o ssi_aead.o ssi_ivgen.o ssi_sram_mgr.o ssi_pm.o ccree-$(CONFIG_CRYPTO_FIPS) += ssi_fips.o -- 2.7.4
[PATCH v2 0/7] crypto: ccree: Introduce Arm TrustZone CryptoCell
Arm TrustZone CryptoCell is a security hardware IP that includes support for hardware based hash, digest, cipher and AEAD operations. This driver provides support for these as part of the Linux Crypto sub-system. The driver spent some time now in the staging tree being cleaned up and is now submitted for review for the purpose of moving into the crypto tree. The first patch therefore renames its copy in the staging directory Kconfig define and marks it broken, otherwise there is a build failure due to global symbols collisions. Please note that the driver include stubs for yet unexposed functionality (ivgen and secure HW keys), which will be added later. Signed-off-by: Gilad Ben-YossefChanges from v1: - Use KConfig directive to stop staging tree version to not collide during link time as opposed to deleting it as indicated by Greg KH. - Switched from legacy ablkcipher to skcipher interface as indicated by Corentin Labbe. - Removed unused zero_buff struct as indicated by Corentin Labbe. - Moved to kzfree for all IV/key buffers as indicated by Corentin Labbe. - Moved to using __des3_ede_setkey() in lieu of home grown version as indicated by Stephan Mueller. - Fixed multiple small coding style from Dan Carpenter and others. - Fixed pointer signedness sparse warnings as indicated by Jeremy Sowden. - Rename all registered algs driver name to -ccree prefix Gilad Ben-Yossef (7): staging: ccree: rename staging ver and mark as broken crypto: ccree: introduce CryptoCell driver crypto: ccree: add skcipher support crypto: ccree: add ahash support crypto: ccree: add AEAD support crypto: ccree: add FIPS support MAINTAINERS: update ccree entry MAINTAINERS |5 +- drivers/crypto/Kconfig | 27 + drivers/crypto/Makefile |1 + drivers/crypto/ccree/Makefile |7 + drivers/crypto/ccree/cc_aead.c | 2702 +++ drivers/crypto/ccree/cc_aead.h | 109 ++ drivers/crypto/ccree/cc_buffer_mgr.c| 1651 +++ drivers/crypto/ccree/cc_buffer_mgr.h| 72 + drivers/crypto/ccree/cc_cipher.c| 1130 + drivers/crypto/ccree/cc_cipher.h| 59 + drivers/crypto/ccree/cc_crypto_ctx.h| 170 ++ drivers/crypto/ccree/cc_debugfs.c | 101 ++ drivers/crypto/ccree/cc_debugfs.h | 32 + drivers/crypto/ccree/cc_driver.c| 476 ++ drivers/crypto/ccree/cc_driver.h| 194 +++ drivers/crypto/ccree/cc_fips.c | 111 ++ drivers/crypto/ccree/cc_fips.h | 37 + drivers/crypto/ccree/cc_hash.c | 2296 ++ drivers/crypto/ccree/cc_hash.h | 114 ++ drivers/crypto/ccree/cc_host_regs.h | 142 ++ drivers/crypto/ccree/cc_hw_queue_defs.h | 590 +++ drivers/crypto/ccree/cc_ivgen.c | 280 drivers/crypto/ccree/cc_ivgen.h | 55 + drivers/crypto/ccree/cc_kernel_regs.h | 167 ++ drivers/crypto/ccree/cc_lli_defs.h | 59 + drivers/crypto/ccree/cc_pm.c| 122 ++ drivers/crypto/ccree/cc_pm.h| 57 + drivers/crypto/ccree/cc_request_mgr.c | 713 drivers/crypto/ccree/cc_request_mgr.h | 51 + drivers/crypto/ccree/cc_sram_mgr.c | 107 ++ drivers/crypto/ccree/cc_sram_mgr.h | 65 + drivers/staging/ccree/Kconfig |4 +- drivers/staging/ccree/Makefile |2 +- 33 files changed, 11702 insertions(+), 6 deletions(-) create mode 100644 drivers/crypto/ccree/Makefile create mode 100644 drivers/crypto/ccree/cc_aead.c create mode 100644 drivers/crypto/ccree/cc_aead.h create mode 100644 drivers/crypto/ccree/cc_buffer_mgr.c create mode 100644 drivers/crypto/ccree/cc_buffer_mgr.h create mode 100644 drivers/crypto/ccree/cc_cipher.c create mode 100644 drivers/crypto/ccree/cc_cipher.h create mode 100644 drivers/crypto/ccree/cc_crypto_ctx.h create mode 100644 drivers/crypto/ccree/cc_debugfs.c create mode 100644 drivers/crypto/ccree/cc_debugfs.h create mode 100644 drivers/crypto/ccree/cc_driver.c create mode 100644 drivers/crypto/ccree/cc_driver.h create mode 100644 drivers/crypto/ccree/cc_fips.c create mode 100644 drivers/crypto/ccree/cc_fips.h create mode 100644 drivers/crypto/ccree/cc_hash.c create mode 100644 drivers/crypto/ccree/cc_hash.h create mode 100644 drivers/crypto/ccree/cc_host_regs.h create mode 100644 drivers/crypto/ccree/cc_hw_queue_defs.h create mode 100644 drivers/crypto/ccree/cc_ivgen.c create mode 100644 drivers/crypto/ccree/cc_ivgen.h create mode 100644 drivers/crypto/ccree/cc_kernel_regs.h create mode 100644 drivers/crypto/ccree/cc_lli_defs.h create mode 100644 drivers/crypto/ccree/cc_pm.c create mode 100644 drivers/crypto/ccree/cc_pm.h create mode 100644 drivers/crypto/ccree/cc_request_mgr.c create mode 100644 drivers/crypto/ccree/cc_request_mgr.h create mode 100644 drivers/crypto/ccree/cc_sram_mgr.c create mode
[PATCH v2 2/7] crypto: ccree: introduce CryptoCell driver
Introduce basic low level Arm TrustZone CryptoCell HW support. This first patch doesn't actually register any Crypto API transformations, these will follow up in the next patch. This first revision supports the CC 712 REE component. Signed-off-by: Gilad Ben-Yossef--- drivers/crypto/Kconfig | 27 ++ drivers/crypto/Makefile | 1 + drivers/crypto/ccree/Makefile | 6 + drivers/crypto/ccree/cc_buffer_mgr.c| 387 + drivers/crypto/ccree/cc_buffer_mgr.h| 60 +++ drivers/crypto/ccree/cc_crypto_ctx.h| 170 drivers/crypto/ccree/cc_debugfs.c | 101 + drivers/crypto/ccree/cc_debugfs.h | 32 ++ drivers/crypto/ccree/cc_driver.c| 417 +++ drivers/crypto/ccree/cc_driver.h| 186 + drivers/crypto/ccree/cc_host_regs.h | 142 +++ drivers/crypto/ccree/cc_hw_queue_defs.h | 590 ++ drivers/crypto/ccree/cc_ivgen.c | 280 + drivers/crypto/ccree/cc_ivgen.h | 55 +++ drivers/crypto/ccree/cc_kernel_regs.h | 167 drivers/crypto/ccree/cc_lli_defs.h | 59 +++ drivers/crypto/ccree/cc_pm.c| 118 ++ drivers/crypto/ccree/cc_pm.h| 57 +++ drivers/crypto/ccree/cc_request_mgr.c | 713 drivers/crypto/ccree/cc_request_mgr.h | 51 +++ drivers/crypto/ccree/cc_sram_mgr.c | 107 + drivers/crypto/ccree/cc_sram_mgr.h | 65 +++ 22 files changed, 3791 insertions(+) create mode 100644 drivers/crypto/ccree/Makefile create mode 100644 drivers/crypto/ccree/cc_buffer_mgr.c create mode 100644 drivers/crypto/ccree/cc_buffer_mgr.h create mode 100644 drivers/crypto/ccree/cc_crypto_ctx.h create mode 100644 drivers/crypto/ccree/cc_debugfs.c create mode 100644 drivers/crypto/ccree/cc_debugfs.h create mode 100644 drivers/crypto/ccree/cc_driver.c create mode 100644 drivers/crypto/ccree/cc_driver.h create mode 100644 drivers/crypto/ccree/cc_host_regs.h create mode 100644 drivers/crypto/ccree/cc_hw_queue_defs.h create mode 100644 drivers/crypto/ccree/cc_ivgen.c create mode 100644 drivers/crypto/ccree/cc_ivgen.h create mode 100644 drivers/crypto/ccree/cc_kernel_regs.h create mode 100644 drivers/crypto/ccree/cc_lli_defs.h create mode 100644 drivers/crypto/ccree/cc_pm.c create mode 100644 drivers/crypto/ccree/cc_pm.h create mode 100644 drivers/crypto/ccree/cc_request_mgr.c create mode 100644 drivers/crypto/ccree/cc_request_mgr.h create mode 100644 drivers/crypto/ccree/cc_sram_mgr.c create mode 100644 drivers/crypto/ccree/cc_sram_mgr.h diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 47ec920..ed912bf 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -731,4 +731,31 @@ config CRYPTO_DEV_ARTPEC6 To compile this driver as a module, choose M here. +config CRYPTO_DEV_CCREE + tristate "Support for ARM TrustZone CryptoCell family of security processors" + depends on CRYPTO && CRYPTO_HW && OF && HAS_DMA + default n + select CRYPTO_HASH + select CRYPTO_BLKCIPHER + select CRYPTO_DES + select CRYPTO_AEAD + select CRYPTO_AUTHENC + select CRYPTO_SHA1 + select CRYPTO_MD5 + select CRYPTO_SHA256 + select CRYPTO_SHA512 + select CRYPTO_HMAC + select CRYPTO_AES + select CRYPTO_CBC + select CRYPTO_ECB + select CRYPTO_CTR + select CRYPTO_XTS + help + Say 'Y' to enable a driver for the Arm TrustZone CryptoCell + family of processors. Currently only the CryptoCell 712 REE + is supported. + Choose this if you wish to use hardware acceleration of + cryptographic operations on the system REE. + If unsure say Y. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 2513d13..ee5ec5c9 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_CRYPTO_DEV_ATMEL_ECC) += atmel-ecc.o obj-$(CONFIG_CRYPTO_DEV_BFIN_CRC) += bfin_crc.o obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += cavium/ obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/ +obj-$(CONFIG_CRYPTO_DEV_CCREE) += ccree/ obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/ obj-$(CONFIG_CRYPTO_DEV_CPT) += cavium/cpt/ obj-$(CONFIG_CRYPTO_DEV_NITROX) += cavium/nitrox/ diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile new file mode 100644 index 000..6b204ab --- /dev/null +++ b/drivers/crypto/ccree/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o +ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_ivgen.o cc_sram_mgr.o +ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o +ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c new file mode 100644 index 000..4c67579 --- /dev/null +++
[PATCH v2 5/7] crypto: ccree: add AEAD support
Add CryptoCell AEAD support Signed-off-by: Gilad Ben-Yossef--- drivers/crypto/ccree/Makefile|2 +- drivers/crypto/ccree/cc_aead.c | 2702 ++ drivers/crypto/ccree/cc_aead.h | 109 ++ drivers/crypto/ccree/cc_buffer_mgr.c | 882 +++ drivers/crypto/ccree/cc_buffer_mgr.h |4 + drivers/crypto/ccree/cc_driver.c | 10 + drivers/crypto/ccree/cc_driver.h |2 + 7 files changed, 3710 insertions(+), 1 deletion(-) create mode 100644 drivers/crypto/ccree/cc_aead.c create mode 100644 drivers/crypto/ccree/cc_aead.h diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile index 1109480..7cb3082 100644 --- a/drivers/crypto/ccree/Makefile +++ b/drivers/crypto/ccree/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o -ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_ivgen.o cc_sram_mgr.o +ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_aead.o cc_ivgen.o cc_sram_mgr.o ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_aead.c b/drivers/crypto/ccree/cc_aead.c new file mode 100644 index 000..3e1046a --- /dev/null +++ b/drivers/crypto/ccree/cc_aead.c @@ -0,0 +1,2702 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cc_driver.h" +#include "cc_buffer_mgr.h" +#include "cc_aead.h" +#include "cc_request_mgr.h" +#include "cc_hash.h" +#include "cc_sram_mgr.h" + +#define template_aead template_u.aead + +#define MAX_AEAD_SETKEY_SEQ 12 +#define MAX_AEAD_PROCESS_SEQ 23 + +#define MAX_HMAC_DIGEST_SIZE (SHA256_DIGEST_SIZE) +#define MAX_HMAC_BLOCK_SIZE (SHA256_BLOCK_SIZE) + +#define AES_CCM_RFC4309_NONCE_SIZE 3 +#define MAX_NONCE_SIZE CTR_RFC3686_NONCE_SIZE + +/* Value of each ICV_CMP byte (of 8) in case of success */ +#define ICV_VERIF_OK 0x01 + +struct cc_aead_handle { + cc_sram_addr_t sram_workspace_addr; + struct list_head aead_list; +}; + +struct cc_hmac_s { + u8 *padded_authkey; + u8 *ipad_opad; /* IPAD, OPAD*/ + dma_addr_t padded_authkey_dma_addr; + dma_addr_t ipad_opad_dma_addr; +}; + +struct cc_xcbc_s { + u8 *xcbc_keys; /* K1,K2,K3 */ + dma_addr_t xcbc_keys_dma_addr; +}; + +struct cc_aead_ctx { + struct cc_drvdata *drvdata; + u8 ctr_nonce[MAX_NONCE_SIZE]; /* used for ctr3686 iv and aes ccm */ + u8 *enckey; + dma_addr_t enckey_dma_addr; + union { + struct cc_hmac_s hmac; + struct cc_xcbc_s xcbc; + } auth_state; + unsigned int enc_keylen; + unsigned int auth_keylen; + unsigned int authsize; /* Actual (reduced?) size of the MAC/ICv */ + enum drv_cipher_mode cipher_mode; + enum cc_flow_mode flow_mode; + enum drv_hash_mode auth_mode; +}; + +static inline bool valid_assoclen(struct aead_request *req) +{ + return ((req->assoclen == 16) || (req->assoclen == 20)); +} + +static void cc_aead_exit(struct crypto_aead *tfm) +{ + struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm); + struct device *dev = drvdata_to_dev(ctx->drvdata); + + dev_dbg(dev, "Clearing context @%p for %s\n", crypto_aead_ctx(tfm), + crypto_tfm_alg_name(>base)); + + /* Unmap enckey buffer */ + if (ctx->enckey) { + dma_free_coherent(dev, AES_MAX_KEY_SIZE, ctx->enckey, + ctx->enckey_dma_addr); + dev_dbg(dev, "Freed enckey DMA buffer enckey_dma_addr=%pad\n", + >enckey_dma_addr); + ctx->enckey_dma_addr = 0; + ctx->enckey = NULL; + } + + if (ctx->auth_mode == DRV_HASH_XCBC_MAC) { /* XCBC authetication */ + struct cc_xcbc_s *xcbc = >auth_state.xcbc; + + if (xcbc->xcbc_keys) { + dma_free_coherent(dev, CC_AES_128_BIT_KEY_SIZE * 3, + xcbc->xcbc_keys, + xcbc->xcbc_keys_dma_addr); + } + dev_dbg(dev, "Freed xcbc_keys DMA buffer xcbc_keys_dma_addr=%pad\n", + >xcbc_keys_dma_addr); + xcbc->xcbc_keys_dma_addr = 0; + xcbc->xcbc_keys = NULL; + } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC auth. */ + struct cc_hmac_s *hmac = >auth_state.hmac; + + if (hmac->ipad_opad) { + dma_free_coherent(dev, 2 * MAX_HMAC_DIGEST_SIZE, + hmac->ipad_opad, + hmac->ipad_opad_dma_addr); + dev_dbg(dev, "Freed ipad_opad DMA buffer ipad_opad_dma_addr=%pad\n", +
[PATCH v2 4/7] crypto: ccree: add ahash support
Add CryptoCell async. hash and HMAC support. Signed-off-by: Gilad Ben-Yossef--- drivers/crypto/ccree/Makefile|2 +- drivers/crypto/ccree/cc_buffer_mgr.c | 261 +++- drivers/crypto/ccree/cc_driver.c | 13 + drivers/crypto/ccree/cc_driver.h |1 + drivers/crypto/ccree/cc_hash.c | 2296 ++ drivers/crypto/ccree/cc_hash.h | 114 ++ drivers/crypto/ccree/cc_pm.c |4 + 7 files changed, 2688 insertions(+), 3 deletions(-) create mode 100644 drivers/crypto/ccree/cc_hash.c create mode 100644 drivers/crypto/ccree/cc_hash.h diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile index a7fecad..1109480 100644 --- a/drivers/crypto/ccree/Makefile +++ b/drivers/crypto/ccree/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o -ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_ivgen.o cc_sram_mgr.o +ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_ivgen.o cc_sram_mgr.o ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_buffer_mgr.c b/drivers/crypto/ccree/cc_buffer_mgr.c index 46be101..bb306b4 100644 --- a/drivers/crypto/ccree/cc_buffer_mgr.c +++ b/drivers/crypto/ccree/cc_buffer_mgr.c @@ -9,6 +9,7 @@ #include "cc_buffer_mgr.h" #include "cc_lli_defs.h" #include "cc_cipher.h" +#include "cc_hash.h" enum dma_buffer_type { DMA_NULL_TYPE = -1, @@ -348,9 +349,33 @@ static int cc_map_sg(struct device *dev, struct scatterlist *sg, return 0; } +static int cc_set_hash_buf(struct device *dev, struct ahash_req_ctx *areq_ctx, + u8 *curr_buff, u32 curr_buff_cnt, + struct buffer_array *sg_data) +{ + dev_dbg(dev, " handle curr buff %x set to DLLI\n", curr_buff_cnt); + /* create sg for the current buffer */ + sg_init_one(areq_ctx->buff_sg, curr_buff, curr_buff_cnt); + if (dma_map_sg(dev, areq_ctx->buff_sg, 1, DMA_TO_DEVICE) != 1) { + dev_err(dev, "dma_map_sg() src buffer failed\n"); + return -ENOMEM; + } + dev_dbg(dev, "Mapped curr_buff: dma_address=%pad page=%p addr=%pK offset=%u length=%u\n", + _dma_address(areq_ctx->buff_sg), sg_page(areq_ctx->buff_sg), + sg_virt(areq_ctx->buff_sg), areq_ctx->buff_sg->offset, + areq_ctx->buff_sg->length); + areq_ctx->data_dma_buf_type = CC_DMA_BUF_DLLI; + areq_ctx->curr_sg = areq_ctx->buff_sg; + areq_ctx->in_nents = 0; + /* prepare for case of MLLI */ + cc_add_sg_entry(dev, sg_data, 1, areq_ctx->buff_sg, curr_buff_cnt, 0, + false, NULL); + return 0; +} + void cc_unmap_cipher_request(struct device *dev, void *ctx, -unsigned int ivsize, struct scatterlist *src, -struct scatterlist *dst) + unsigned int ivsize, struct scatterlist *src, + struct scatterlist *dst) { struct cipher_req_ctx *req_ctx = (struct cipher_req_ctx *)ctx; @@ -472,6 +497,238 @@ int cc_map_cipher_request(struct cc_drvdata *drvdata, void *ctx, return rc; } +int cc_map_hash_request_final(struct cc_drvdata *drvdata, void *ctx, + struct scatterlist *src, unsigned int nbytes, + bool do_update, gfp_t flags) +{ + struct ahash_req_ctx *areq_ctx = (struct ahash_req_ctx *)ctx; + struct device *dev = drvdata_to_dev(drvdata); + u8 *curr_buff = cc_hash_buf(areq_ctx); + u32 *curr_buff_cnt = cc_hash_buf_cnt(areq_ctx); + struct mlli_params *mlli_params = _ctx->mlli_params; + struct buffer_array sg_data; + struct buff_mgr_handle *buff_mgr = drvdata->buff_mgr_handle; + u32 dummy = 0; + u32 mapped_nents = 0; + + dev_dbg(dev, "final params : curr_buff=%pK curr_buff_cnt=0x%X nbytes = 0x%X src=%pK curr_index=%u\n", + curr_buff, *curr_buff_cnt, nbytes, src, areq_ctx->buff_index); + /* Init the type of the dma buffer */ + areq_ctx->data_dma_buf_type = CC_DMA_BUF_NULL; + mlli_params->curr_pool = NULL; + sg_data.num_of_buffers = 0; + areq_ctx->in_nents = 0; + + if (nbytes == 0 && *curr_buff_cnt == 0) { + /* nothing to do */ + return 0; + } + + /*TODO: copy data in case that buffer is enough for operation */ + /* map the previous buffer */ + if (*curr_buff_cnt) { + if (cc_set_hash_buf(dev, areq_ctx, curr_buff, *curr_buff_cnt, + _data)) { + return -ENOMEM; + } + } + + if (src && nbytes > 0 && do_update) { + if (cc_map_sg(dev, src, nbytes, DMA_TO_DEVICE, +
[PATCH v2 7/7] MAINTAINERS: update ccree entry
Update Arm TrustZone CryptoCell driver entry move into drivers/crypto/ Signed-off-by: Gilad Ben-Yossef--- MAINTAINERS | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1082846..560e068 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3273,12 +3273,11 @@ F: drivers/net/ieee802154/cc2520.c F: include/linux/spi/cc2520.h F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt -CCREE ARM TRUSTZONE CRYPTOCELL 700 REE DRIVER +CCREE ARM TRUSTZONE CRYPTOCELL REE DRIVER M: Gilad Ben-Yossef L: linux-crypto@vger.kernel.org -L: driverdev-de...@linuxdriverproject.org S: Supported -F: drivers/staging/ccree/ +F: drivers/crypto/ccree/ W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family CEC FRAMEWORK -- 2.7.4
[PATCH v2 6/7] crypto: ccree: add FIPS support
Add FIPS mode support to CryptoCell driver Signed-off-by: Gilad Ben-Yossef--- drivers/crypto/ccree/Makefile| 1 + drivers/crypto/ccree/cc_driver.c | 29 +- drivers/crypto/ccree/cc_driver.h | 1 + drivers/crypto/ccree/cc_fips.c | 111 +++ drivers/crypto/ccree/cc_fips.h | 37 + 5 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 drivers/crypto/ccree/cc_fips.c create mode 100644 drivers/crypto/ccree/cc_fips.h diff --git a/drivers/crypto/ccree/Makefile b/drivers/crypto/ccree/Makefile index 7cb3082..bdc2797 100644 --- a/drivers/crypto/ccree/Makefile +++ b/drivers/crypto/ccree/Makefile @@ -2,5 +2,6 @@ obj-$(CONFIG_CRYPTO_DEV_CCREE) := ccree.o ccree-y := cc_driver.o cc_buffer_mgr.o cc_request_mgr.o cc_cipher.o cc_hash.o cc_aead.o cc_ivgen.o cc_sram_mgr.o +ccree-$(CONFIG_CRYPTO_FIPS) += cc_fips.o ccree-$(CONFIG_DEBUG_FS) += cc_debugfs.o ccree-$(CONFIG_PM) += cc_pm.o diff --git a/drivers/crypto/ccree/cc_driver.c b/drivers/crypto/ccree/cc_driver.c index 8a530a4..827e329 100644 --- a/drivers/crypto/ccree/cc_driver.c +++ b/drivers/crypto/ccree/cc_driver.c @@ -25,6 +25,7 @@ #include "cc_ivgen.h" #include "cc_sram_mgr.h" #include "cc_pm.h" +#include "cc_fips.h" bool cc_dump_desc; module_param_named(dump_desc, cc_dump_desc, bool, 0600); @@ -78,7 +79,17 @@ static irqreturn_t cc_isr(int irq, void *dev_id) irr &= ~CC_COMP_IRQ_MASK; complete_request(drvdata); } - +#ifdef CONFIG_CRYPTO_FIPS + /* TEE FIPS interrupt */ + if (irr & CC_GPR0_IRQ_MASK) { + /* Mask interrupt - will be unmasked in Deferred service +* handler +*/ + cc_iowrite(drvdata, CC_REG(HOST_IMR), imr | CC_GPR0_IRQ_MASK); + irr &= ~CC_GPR0_IRQ_MASK; + fips_handler(drvdata); + } +#endif /* AXI error interrupt */ if (irr & CC_AXI_ERR_IRQ_MASK) { u32 axi_err; @@ -243,10 +254,15 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_regs_err; } + rc = cc_fips_init(new_drvdata); + if (rc) { + dev_err(dev, "CC_FIPS_INIT failed 0x%x\n", rc); + goto post_debugfs_err; + } rc = cc_sram_mgr_init(new_drvdata); if (rc) { dev_err(dev, "cc_sram_mgr_init failed\n"); - goto post_debugfs_err; + goto post_fips_init_err; } new_drvdata->mlli_sram_addr = @@ -301,6 +317,12 @@ static int init_cc_resources(struct platform_device *plat_dev) goto post_hash_err; } + /* If we got here and FIPS mode is enabled +* it means all FIPS test passed, so let TEE +* know we're good. +*/ + cc_set_ree_fips_status(new_drvdata, true); + return 0; post_hash_err: @@ -317,6 +339,8 @@ static int init_cc_resources(struct platform_device *plat_dev) cc_req_mgr_fini(new_drvdata); post_sram_mgr_err: cc_sram_mgr_fini(new_drvdata); +post_fips_init_err: + cc_fips_fini(new_drvdata); post_debugfs_err: cc_debugfs_fini(new_drvdata); post_regs_err: @@ -345,6 +369,7 @@ static void cleanup_cc_resources(struct platform_device *plat_dev) cc_buffer_mgr_fini(drvdata); cc_req_mgr_fini(drvdata); cc_sram_mgr_fini(drvdata); + cc_fips_fini(drvdata); cc_debugfs_fini(drvdata); fini_cc_regs(drvdata); cc_clk_off(drvdata); diff --git a/drivers/crypto/ccree/cc_driver.h b/drivers/crypto/ccree/cc_driver.h index 0109c64..9cc488f 100644 --- a/drivers/crypto/ccree/cc_driver.h +++ b/drivers/crypto/ccree/cc_driver.h @@ -116,6 +116,7 @@ struct cc_drvdata { void *hash_handle; void *aead_handle; void *request_mgr_handle; + void *fips_handle; void *ivgen_handle; void *sram_mgr_handle; void *debugfs; diff --git a/drivers/crypto/ccree/cc_fips.c b/drivers/crypto/ccree/cc_fips.c new file mode 100644 index 000..de08af9 --- /dev/null +++ b/drivers/crypto/ccree/cc_fips.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2012-2018 ARM Limited or its affiliates. */ + +#include +#include + +#include "cc_driver.h" +#include "cc_fips.h" + +static void fips_dsr(unsigned long devarg); + +struct cc_fips_handle { + struct tasklet_struct tasklet; +}; + +/* The function called once at driver entry point to check + * whether TEE FIPS error occurred. + */ +static bool cc_get_tee_fips_status(struct cc_drvdata *drvdata) +{ + u32 reg; + + reg = cc_ioread(drvdata, CC_REG(GPR_HOST)); + return (reg == (CC_FIPS_SYNC_TEE_STATUS | CC_FIPS_SYNC_MODULE_OK)); +} + +/* + * This function should push the FIPS REE library status towards the TEE library + * by writing the error state to HOST_GPR0 register. + */ +void cc_set_ree_fips_status(struct