This serie fixes and improves the talitos crypto driver.
First 6 patchs are fixes of failures reported by the new tests in the
kernel crypto test manager.
The 8 following patches are cleanups and simplifications.
The last 4 ones are performance improvement. The main improvement is
in the one before the last, it divides by 2 the time needed for a md5
hash on the SEC1.
Christophe Leroy (18):
crypto: talitos - fix AEAD test failures
crypto: talitos - fix memory corruption on SEC2
crypto: talitos - fix setkey to check key weakness
crypto: talitos - fix AEAD for sha224 on non sha224 capable chips
crypto: talitos - fix use of sg_link_tbl_len
crypto: talitos - fix ctr-aes-talitos
crypto: talitos - zeroize the descriptor with memset()
crypto: talitos - declare local functions static
crypto: talitos - use devm_kmalloc()
crypto: talitos - use of_property_read_u32()
crypto: talitos - use devm_ioremap()
crypto: talitos - don't check the number of channels at each interrupt
crypto: talitos - remove to_talitos_ptr_len()
crypto: talitos - simplify tests in ipsec_esp()
crypto: talitos - DMA map key in setkey()
crypto: talitos - do hw_context DMA mapping outside the requests
crypto: talitos - chain in buffered data for ahash on SEC1
crypto: talitos - avoid useless copy
drivers/crypto/talitos.c | 544 ++++++++++++++++++++++++++++++-----------------
drivers/crypto/talitos.h | 7 +-
2 files changed, 356 insertions(+), 195 deletions(-)
--
2.13.3
Crypto manager test report the following failures:
[ 3.061081] alg: skcipher: setkey failed on test 5 for ecb-des-talitos: flags=100
[ 3.069342] alg: skcipher-ddst: setkey failed on test 5 for ecb-des-talitos: flags=100
[ 3.077754] alg: skcipher-ddst: setkey failed on test 5 for ecb-des-talitos: flags=100
This is due to setkey being expected to detect weak keys.
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 8 ++++++++
1 file changed, 8 insertions(+)
@@ -1247,14 +1247,15 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,dma_map_sg(dev,areq->dst,sg_count,DMA_FROM_DEVICE);}-sg_count=talitos_sg_map(dev,areq->dst,cryptlen,edesc,-&desc->ptr[5],sg_count,areq->assoclen,-tbl_off);+ret=talitos_sg_map(dev,areq->dst,cryptlen,edesc,&desc->ptr[5],+sg_count,areq->assoclen,tbl_off);if(desc->hdr&DESC_HDR_TYPE_IPSEC_ESP)to_talitos_ptr_ext_or(&desc->ptr[5],authsize,is_sec1);-if(sg_count>1){+/* ICV data */+if(ret>1){+tbl_off+=ret;edesc->icv_ool=true;sync_needed=true;
@@ -1264,9 +1265,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,sizeof(structtalitos_ptr)+authsize;/* Add an entry to the link table for ICV data */-tbl_ptr+=sg_count-1;-to_talitos_ptr_ext_set(tbl_ptr,0,is_sec1);-tbl_ptr++;+to_talitos_ptr_ext_set(tbl_ptr-1,0,is_sec1);to_talitos_ptr_ext_set(tbl_ptr,DESC_PTR_LNKTBL_RETURN,is_sec1);to_talitos_ptr_len(tbl_ptr,authsize,is_sec1);
@@ -1274,18 +1273,33 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,/* icv data follows link tables */to_talitos_ptr(tbl_ptr,edesc->dma_link_tbl+offset,is_sec1);+}else{+dma_addr_taddr=edesc->dma_link_tbl;++if(is_sec1)+addr+=areq->assoclen+cryptlen;+else+addr+=sizeof(structtalitos_ptr)*tbl_off;++to_talitos_ptr(&desc->ptr[6],addr,is_sec1);+to_talitos_ptr_len(&desc->ptr[6],authsize,is_sec1);+}+}elseif(!(desc->hdr&DESC_HDR_TYPE_IPSEC_ESP)){+ret=talitos_sg_map(dev,areq->dst,authsize,edesc,+&desc->ptr[6],sg_count,areq->assoclen++cryptlen,+tbl_off);+if(ret>1){+tbl_off+=ret;+edesc->icv_ool=true;+sync_needed=true;+}else{+edesc->icv_ool=false;}}else{edesc->icv_ool=false;}-/* ICV data */-if(!(desc->hdr&DESC_HDR_TYPE_IPSEC_ESP)){-to_talitos_ptr_len(&desc->ptr[6],authsize,is_sec1);-to_talitos_ptr(&desc->ptr[6],edesc->dma_link_tbl+-areq->assoclen+cryptlen,is_sec1);-}-/* iv out */if(desc->hdr&DESC_HDR_TYPE_IPSEC_ESP)map_single_talitos_ptr(dev,&desc->ptr[6],ivsize,ctx->iv,
talitos_handle_buggy_hash() and talitos_sg_map() are only used
locally, make them static
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
to_talitos_ptr() and to_talitos_ptr_len() are always called together
in order to fully set a ptr, so lets merge them into a single
helper.
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 56 ++++++++++++++++++------------------------------
1 file changed, 21 insertions(+), 35 deletions(-)
dma_map_single() is an heavy operation which doesn't need to
be done at each request as the key doesn't change.
Instead of DMA mapping the key at every request, this patch maps it
once in setkey()
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 56 +++++++++++++++++++++++++++++++++---------------
1 file changed, 39 insertions(+), 17 deletions(-)
@@ -160,6 +160,10 @@ static int reset_channel(struct device *dev, int ch)/* set 36-bit addressing, done writeback enable and done IRQ enable */setbits32(priv->chan[ch].reg+TALITOS_CCCR_LO,TALITOS_CCCR_LO_EAE|TALITOS_CCCR_LO_CDWE|TALITOS_CCCR_LO_CDIE);+/* enable chaining descriptors */+if(is_sec1)+setbits32(priv->chan[ch].reg+TALITOS_CCCR_LO,+TALITOS_CCCR_LO_NE);/* and ICCR writeback, if available */if(priv->features&TALITOS_FTR_HW_AUTH_CHECK)
@@ -333,7 +337,12 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)/* descriptors with their done bits set don't get the error */rmb();-hdr=is_sec1?request->desc->hdr1:request->desc->hdr;+if(!is_sec1)+hdr=request->desc->hdr;+elseif(request->desc->next_desc)+hdr=(request->desc+1)->hdr1;+else+hdr=request->desc->hdr1;if((hdr&DESC_HDR_DONE)==DESC_HDR_DONE)status=0;
@@ -454,7 +463,8 @@ static u32 current_desc_hdr(struct device *dev, int ch)tail=priv->chan[ch].tail;iter=tail;-while(priv->chan[ch].fifo[iter].dma_desc!=cur_desc){+while(priv->chan[ch].fifo[iter].dma_desc!=cur_desc&&+priv->chan[ch].fifo[iter].desc->next_desc!=cur_desc){iter=(iter+1)&(priv->fifo_len-1);if(iter==tail){dev_err(dev,"couldn't locate current descriptor\n");
@@ -1380,6 +1394,10 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,alloc_len+=icv_stashing?authsize:0;}+/* if its a ahash, add space for a second desc next to the first one */+if(is_sec1&&!dst)+alloc_len+=sizeof(structtalitos_desc);+edesc=kmalloc(alloc_len,GFP_DMA|flags);if(!edesc){dev_err(dev,"could not allocate edescriptor\n");
@@ -1808,6 +1879,8 @@ static int ahash_init(struct ahash_request *areq)structdevice*dev=ctx->dev;structtalitos_ahash_req_ctx*req_ctx=ahash_request_ctx(areq);unsignedintsize;+structtalitos_private*priv=dev_get_drvdata(dev);+boolis_sec1=has_ftr_sec1(priv);/* Initialize the context */req_ctx->nbuf=0;
@@ -1823,6 +1896,13 @@ static int ahash_init(struct ahash_request *areq)DMA_BIDIRECTIONAL);ctx->dma_hw_context=dma_map_single(dev,req_ctx->hw_context,size,DMA_BIDIRECTIONAL);+if(ctx->dma_buf)+dma_unmap_single(dev,ctx->dma_buf,sizeof(req_ctx->buf),+DMA_TO_DEVICE);+if(is_sec1)+ctx->dma_buf=dma_map_single(dev,req_ctx->buf,+sizeof(req_ctx->buf),+DMA_TO_DEVICE);return0;}
@@ -1871,6 +1951,10 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)unsignedintto_hash_later;unsignedintnsg;intnents;+structdevice*dev=ctx->dev;+structtalitos_private*priv=dev_get_drvdata(dev);+boolis_sec1=has_ftr_sec1(priv);+intoffset=0;if(!req_ctx->last&&(nbytes+req_ctx->nbuf<=blocksize)){/* Buffer up to one whole block */
@@ -1901,13 +1985,27 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)}/* Chain in any previously buffered data */-if(req_ctx->nbuf){+if(!is_sec1&&req_ctx->nbuf){nsg=(req_ctx->nbuf<nbytes_to_hash)?2:1;sg_init_table(req_ctx->bufsl,nsg);sg_set_buf(req_ctx->bufsl,req_ctx->buf,req_ctx->nbuf);if(nsg>1)sg_chain(req_ctx->bufsl,2,areq->src);req_ctx->psrc=req_ctx->bufsl;+}elseif(is_sec1&&req_ctx->nbuf&&req_ctx->nbuf<blocksize){+if(nbytes_to_hash>blocksize)+offset=blocksize-req_ctx->nbuf;+else+offset=nbytes_to_hash-req_ctx->nbuf;+nents=sg_nents_for_len(areq->src,offset);+if(nents<0){+dev_err(ctx->dev,"Invalid number of src SG.\n");+returnnents;+}+sg_copy_to_buffer(areq->src,nents,+req_ctx->buf+req_ctx->nbuf,offset);+req_ctx->nbuf+=offset;+req_ctx->psrc=areq->src;}elsereq_ctx->psrc=areq->src;
@@ -1940,6 +2038,9 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)/* request SEC to INIT hash. */if(req_ctx->first&&!req_ctx->swinit)edesc->desc.hdr|=DESC_HDR_MODE0_MDEU_INIT;+if(is_sec1)+dma_sync_single_for_device(dev,ctx->dma_buf,+req_ctx->nbuf,DMA_TO_DEVICE);/* When the tfm context has a keylen, it's an HMAC.*Afirstorlast(ie.notmiddle)descriptormustrequestHMAC.
@@ -1947,7 +2048,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)if(ctx->keylen&&(req_ctx->first||req_ctx->last))edesc->desc.hdr|=DESC_HDR_MODE0_MDEU_HMAC;-returncommon_nonsnoop_hash(edesc,areq,nbytes_to_hash,+returncommon_nonsnoop_hash(edesc,areq,nbytes_to_hash,offset,ahash_done);}
This patch avoids copy of buffered data to hash from bufnext to buf
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 36 ++++++++++++++++++++++--------------
1 file changed, 22 insertions(+), 14 deletions(-)
@@ -1709,7 +1709,7 @@ static void ahash_done(struct device *dev,if(!req_ctx->last&&req_ctx->to_hash_later){/* Position any partial block for next update/final/finup */-memcpy(req_ctx->buf,req_ctx->bufnext,req_ctx->to_hash_later);+req_ctx->buf_idx=(req_ctx->buf_idx+1)&1;req_ctx->nbuf=req_ctx->to_hash_later;}common_nonsnoop_hash_unmap(dev,edesc,areq);
@@ -1789,8 +1789,10 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,*datain*/if(is_sec1&&req_ctx->nbuf){-to_talitos_ptr(&desc->ptr[3],ctx->dma_buf,req_ctx->nbuf,-is_sec1);+dma_addr_tdma_buf=ctx->dma_buf+req_ctx->buf_idx*+HASH_MAX_BLOCK_SIZE;++to_talitos_ptr(&desc->ptr[3],dma_buf,req_ctx->nbuf,is_sec1);}else{sg_count=talitos_sg_map(dev,req_ctx->psrc,length,edesc,&desc->ptr[3],sg_count,offset,0);
@@ -1883,6 +1885,7 @@ static int ahash_init(struct ahash_request *areq)boolis_sec1=has_ftr_sec1(priv);/* Initialize the context */+req_ctx->buf_idx=0;req_ctx->nbuf=0;req_ctx->first=1;/* first indicates h/w must init its context */req_ctx->swinit=0;/* assume h/w init of context */
@@ -1955,6 +1958,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)structtalitos_private*priv=dev_get_drvdata(dev);boolis_sec1=has_ftr_sec1(priv);intoffset=0;+u8*ctx_buf=req_ctx->buf[req_ctx->buf_idx];if(!req_ctx->last&&(nbytes+req_ctx->nbuf<=blocksize)){/* Buffer up to one whole block */
@@ -1964,7 +1968,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)returnnents;}sg_copy_to_buffer(areq->src,nents,-req_ctx->buf+req_ctx->nbuf,nbytes);+ctx_buf+req_ctx->nbuf,nbytes);req_ctx->nbuf+=nbytes;return0;}
@@ -1988,7 +1992,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)if(!is_sec1&&req_ctx->nbuf){nsg=(req_ctx->nbuf<nbytes_to_hash)?2:1;sg_init_table(req_ctx->bufsl,nsg);-sg_set_buf(req_ctx->bufsl,req_ctx->buf,req_ctx->nbuf);+sg_set_buf(req_ctx->bufsl,ctx_buf,req_ctx->nbuf);if(nsg>1)sg_chain(req_ctx->bufsl,2,areq->src);req_ctx->psrc=req_ctx->bufsl;
@@ -2003,7 +2007,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)returnnents;}sg_copy_to_buffer(areq->src,nents,-req_ctx->buf+req_ctx->nbuf,offset);+ctx_buf+req_ctx->nbuf,offset);req_ctx->nbuf+=offset;req_ctx->psrc=areq->src;}else
@@ -2016,7 +2020,7 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)returnnents;}sg_pcopy_to_buffer(areq->src,nents,-req_ctx->bufnext,+req_ctx->buf[(req_ctx->buf_idx+1)&1],to_hash_later,nbytes-to_hash_later);}
@@ -2038,9 +2042,13 @@ static int ahash_process_req(struct ahash_request *areq, unsigned int nbytes)/* request SEC to INIT hash. */if(req_ctx->first&&!req_ctx->swinit)edesc->desc.hdr|=DESC_HDR_MODE0_MDEU_INIT;-if(is_sec1)-dma_sync_single_for_device(dev,ctx->dma_buf,+if(is_sec1){+dma_addr_tdma_buf=ctx->dma_buf+req_ctx->buf_idx*+HASH_MAX_BLOCK_SIZE;++dma_sync_single_for_device(dev,dma_buf,req_ctx->nbuf,DMA_TO_DEVICE);+}/* When the tfm context has a keylen, it's an HMAC.*Afirstorlast(ie.notmiddle)descriptormustrequestHMAC.
At every request, we map and unmap the same hash hw_context.
This patch moves the dma mapping/unmapping in functions ahash_init()
and ahash_import().
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 80 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 57 insertions(+), 23 deletions(-)
@@ -1663,18 +1664,9 @@ static void common_nonsnoop_hash_unmap(struct device *dev,structahash_request*areq){structtalitos_ahash_req_ctx*req_ctx=ahash_request_ctx(areq);-structtalitos_private*priv=dev_get_drvdata(dev);-boolis_sec1=has_ftr_sec1(priv);--unmap_single_talitos_ptr(dev,&edesc->desc.ptr[5],DMA_FROM_DEVICE);talitos_sg_unmap(dev,edesc,req_ctx->psrc,NULL,0,0);-/* When using hashctx-in, must unmap it. */-if(from_talitos_ptr_len(&edesc->desc.ptr[1],is_sec1))-unmap_single_talitos_ptr(dev,&edesc->desc.ptr[1],-DMA_TO_DEVICE);-if(edesc->dma_len)dma_unmap_single(dev,edesc->dma_link_tbl,edesc->dma_len,DMA_BIDIRECTIONAL);
@@ -1744,10 +1736,8 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,/* hash context in */if(!req_ctx->first||req_ctx->swinit){-map_single_talitos_ptr(dev,&desc->ptr[1],-req_ctx->hw_context_size,-(char*)req_ctx->hw_context,-DMA_TO_DEVICE);+to_talitos_ptr(&desc->ptr[1],ctx->dma_hw_context,+req_ctx->hw_context_size,is_sec1);req_ctx->swinit=0;}/* Indicate next op is not the first. */
@@ -1780,9 +1770,8 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,crypto_ahash_digestsize(tfm),areq->result,DMA_FROM_DEVICE);else-map_single_talitos_ptr(dev,&desc->ptr[5],-req_ctx->hw_context_size,-req_ctx->hw_context,DMA_FROM_DEVICE);+to_talitos_ptr(&desc->ptr[5],ctx->dma_hw_context,+req_ctx->hw_context_size,is_sec1);/* last DWORD empty */
@@ -1815,17 +1804,25 @@ static struct talitos_edesc *ahash_edesc_alloc(struct ahash_request *areq,staticintahash_init(structahash_request*areq){structcrypto_ahash*tfm=crypto_ahash_reqtfm(areq);+structtalitos_ctx*ctx=crypto_ahash_ctx(tfm);+structdevice*dev=ctx->dev;structtalitos_ahash_req_ctx*req_ctx=ahash_request_ctx(areq);+unsignedintsize;/* Initialize the context */req_ctx->nbuf=0;req_ctx->first=1;/* first indicates h/w must init its context */req_ctx->swinit=0;/* assume h/w init of context */-req_ctx->hw_context_size=-(crypto_ahash_digestsize(tfm)<=SHA256_DIGEST_SIZE)+size=(crypto_ahash_digestsize(tfm)<=SHA256_DIGEST_SIZE)?TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256:TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;+req_ctx->hw_context_size=size;+if(ctx->dma_hw_context)+dma_unmap_single(dev,ctx->dma_hw_context,size,+DMA_BIDIRECTIONAL);+ctx->dma_hw_context=dma_map_single(dev,req_ctx->hw_context,size,+DMA_BIDIRECTIONAL);return0;}
@@ -1836,6 +1833,9 @@ static int ahash_init(struct ahash_request *areq)staticintahash_init_sha224_swinit(structahash_request*areq){structtalitos_ahash_req_ctx*req_ctx=ahash_request_ctx(areq);+structcrypto_ahash*tfm=crypto_ahash_reqtfm(areq);+structtalitos_ctx*ctx=crypto_ahash_ctx(tfm);+structdevice*dev=ctx->dev;ahash_init(areq);req_ctx->swinit=1;/* prevent h/w initting context with sha256 values*/
@@ -1853,6 +1853,9 @@ static int ahash_init_sha224_swinit(struct ahash_request *areq)req_ctx->hw_context[8]=0;req_ctx->hw_context[9]=0;+dma_sync_single_for_device(dev,ctx->dma_hw_context,+req_ctx->hw_context_size,DMA_TO_DEVICE);+return0;}
@@ -1277,7 +1275,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,}/* iv out */-if(desc->hdr&DESC_HDR_TYPE_IPSEC_ESP)+if(is_ipsec_esp)map_single_talitos_ptr(dev,&desc->ptr[6],ivsize,ctx->iv,DMA_FROM_DEVICE);
The number of channels is known from the beginning, no need to
test it everytime.
This patch defines two additional done functions handling only channel 0.
Then the probe registers the correct one based on the number of channels.
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 27 +++++++++++++++------------
drivers/crypto/talitos.h | 4 ++++
2 files changed, 19 insertions(+), 12 deletions(-)
@@ -390,8 +390,6 @@ static void talitos1_done_##name(unsigned long data) \\if(ch_done_mask&0x10000000)\flush_channel(dev,0,0,0);\-if(priv->num_channels==1)\-gotoout;\if(ch_done_mask&0x40000000)\flush_channel(dev,1,0,0);\if(ch_done_mask&0x00010000)\
@@ -399,7 +397,6 @@ static void talitos1_done_##name(unsigned long data) \if(ch_done_mask&0x00040000)\flush_channel(dev,3,0,0);\\-out:\/* At this point, all completed channels have been processed */\/* Unmask done interrupts for channels completed later on. */\spin_lock_irqsave(&priv->reg_lock,flags);\
@@ -419,8 +417,6 @@ static void talitos2_done_##name(unsigned long data) \\if(ch_done_mask&1)\flush_channel(dev,0,0,0);\-if(priv->num_channels==1)\-gotoout;\if(ch_done_mask&(1<<2))\flush_channel(dev,1,0,0);\if(ch_done_mask&(1<<4))\
@@ -428,7 +424,6 @@ static void talitos2_done_##name(unsigned long data) \if(ch_done_mask&(1<<6))\flush_channel(dev,3,0,0);\\-out:\/* At this point, all completed channels have been processed */\/* Unmask done interrupts for channels completed later on. */\spin_lock_irqsave(&priv->reg_lock,flags);\
@@ -3158,7 +3158,6 @@ static int talitos_probe(struct platform_device *ofdev)structdevice*dev=&ofdev->dev;structdevice_node*np=ofdev->dev.of_node;structtalitos_private*priv;-constunsignedint*prop;inti,err;intstride;
@@ -3182,21 +3181,11 @@ static int talitos_probe(struct platform_device *ofdev)}/* get SEC version capabilities from device tree */-prop=of_get_property(np,"fsl,num-channels",NULL);-if(prop)-priv->num_channels=*prop;--prop=of_get_property(np,"fsl,channel-fifo-len",NULL);-if(prop)-priv->chfifo_len=*prop;--prop=of_get_property(np,"fsl,exec-units-mask",NULL);-if(prop)-priv->exec_units=*prop;--prop=of_get_property(np,"fsl,descriptor-types-mask",NULL);-if(prop)-priv->desc_types=*prop;+of_property_read_u32(np,"fsl,num-channels",&priv->num_channels);+of_property_read_u32(np,"fsl,channel-fifo-len",&priv->chfifo_len);+of_property_read_u32(np,"fsl,exec-units-mask",&priv->exec_units);+of_property_read_u32(np,"fsl,descriptor-types-mask",+&priv->desc_types);if(!is_power_of_2(priv->num_channels)||!priv->chfifo_len||!priv->exec_units||!priv->desc_types){
This patch zeroize the descriptor at allocation using memset().
This has two advantages:
- It reduces the number of places where data has to be set to 0
- It avoids reading memory and loading the cache with data that
will be entirely replaced.
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 19 +------------------
drivers/crypto/talitos.h | 2 --
2 files changed, 1 insertion(+), 20 deletions(-)
@@ -287,7 +285,6 @@ int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,/* map descriptor and save caller data */if(is_sec1){desc->hdr1=desc->hdr;-desc->next_desc=0;request->dma_desc=dma_map_single(dev,&desc->hdr1,TALITOS_DESC_SIZE,DMA_BIDIRECTIONAL);
@@ -1481,7 +1475,6 @@ static int aead_decrypt(struct aead_request *req)DESC_HDR_MODE1_MDEU_CICV;/* reset integrity check result bits */-edesc->desc.hdr_lo=0;returnipsec_esp(edesc,req,ipsec_esp_decrypt_hwauth_done);}
@@ -1576,12 +1569,10 @@ static int common_nonsnoop(struct talitos_edesc *edesc,boolis_sec1=has_ftr_sec1(priv);/* first DWORD empty */-desc->ptr[0]=zero_entry;/* cipher iv */to_talitos_ptr(&desc->ptr[1],edesc->iv_dma,is_sec1);to_talitos_ptr_len(&desc->ptr[1],ivsize,is_sec1);-to_talitos_ptr_ext_set(&desc->ptr[1],0,is_sec1);/* cipher key */map_single_talitos_ptr(dev,&desc->ptr[2],ctx->keylen,
@@ -1620,7 +1611,6 @@ static int common_nonsnoop(struct talitos_edesc *edesc,DMA_FROM_DEVICE);/* last DWORD empty */-desc->ptr[6]=zero_entry;if(sync_needed)dma_sync_single_for_device(dev,edesc->dma_link_tbl,
@@ -1766,7 +1756,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,intsg_count;/* first DWORD empty */-desc->ptr[0]=zero_entry;/* hash context in */if(!req_ctx->first||req_ctx->swinit){
@@ -1775,8 +1764,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,(char*)req_ctx->hw_context,DMA_TO_DEVICE);req_ctx->swinit=0;-}else{-desc->ptr[1]=zero_entry;}/* Indicate next op is not the first. */req_ctx->first=0;
@@ -1785,8 +1772,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,if(ctx->keylen)map_single_talitos_ptr(dev,&desc->ptr[2],ctx->keylen,(char*)&ctx->key,DMA_TO_DEVICE);-else-desc->ptr[2]=zero_entry;sg_count=edesc->src_nents?:1;if(is_sec1&&sg_count>1)
@@ -1803,7 +1788,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,sync_needed=true;/* fifth DWORD empty */-desc->ptr[4]=zero_entry;/* hash/HMAC out -or- hash context out */if(req_ctx->last)
@@ -1816,7 +1800,6 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,req_ctx->hw_context,DMA_FROM_DEVICE);/* last DWORD empty */-desc->ptr[6]=zero_entry;if(is_sec1&&from_talitos_ptr_len(&desc->ptr[3],true)==0)talitos_handle_buggy_hash(ctx,edesc,&desc->ptr[3]);
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2017-10-12 15:20:26
On Fri, Oct 06, 2017 at 03:04:31PM +0200, Christophe Leroy wrote:
This serie fixes and improves the talitos crypto driver.
First 6 patchs are fixes of failures reported by the new tests in the
kernel crypto test manager.
The 8 following patches are cleanups and simplifications.
The last 4 ones are performance improvement. The main improvement is
in the one before the last, it divides by 2 the time needed for a md5
hash on the SEC1.
Christophe Leroy (18):
crypto: talitos - fix AEAD test failures
crypto: talitos - fix memory corruption on SEC2
crypto: talitos - fix setkey to check key weakness
crypto: talitos - fix AEAD for sha224 on non sha224 capable chips
crypto: talitos - fix use of sg_link_tbl_len
crypto: talitos - fix ctr-aes-talitos
crypto: talitos - zeroize the descriptor with memset()
crypto: talitos - declare local functions static
crypto: talitos - use devm_kmalloc()
crypto: talitos - use of_property_read_u32()
crypto: talitos - use devm_ioremap()
crypto: talitos - don't check the number of channels at each interrupt
crypto: talitos - remove to_talitos_ptr_len()
crypto: talitos - simplify tests in ipsec_esp()
crypto: talitos - DMA map key in setkey()
crypto: talitos - do hw_context DMA mapping outside the requests
crypto: talitos - chain in buffered data for ahash on SEC1
crypto: talitos - avoid useless copy
On Fri, Oct 06, 2017 at 03:04:31PM +0200, Christophe Leroy wrote:=0A=
quoted
This serie fixes and improves the talitos crypto driver.=0A=
=0A=
First 6 patchs are fixes of failures reported by the new tests in the=0A=
kernel crypto test manager.=0A=
=0A=
Looks like these fixes are required also on older 4.9+ -stable kernels.=0A=
(I haven't seen them on latest 4.9.68-stable mail from Greg, even though=0A=
they are in main tree.)=0A=
=0A=
In case you agree, what would be the recommended way to add the patches=0A=
to -stable?=0A=
=0A=
Thanks,=0A=
Horia=0A=
=0A=
quoted
The 8 following patches are cleanups and simplifications.=0A=
=0A=
The last 4 ones are performance improvement. The main improvement is=0A=
in the one before the last, it divides by 2 the time needed for a md5=0A=
hash on the SEC1.=0A=
=0A=
Christophe Leroy (18):=0A=
crypto: talitos - fix AEAD test failures=0A=
crypto: talitos - fix memory corruption on SEC2=0A=
crypto: talitos - fix setkey to check key weakness=0A=
crypto: talitos - fix AEAD for sha224 on non sha224 capable chips=0A=
crypto: talitos - fix use of sg_link_tbl_len=0A=
crypto: talitos - fix ctr-aes-talitos=0A=
crypto: talitos - zeroize the descriptor with memset()=0A=
crypto: talitos - declare local functions static=0A=
crypto: talitos - use devm_kmalloc()=0A=
crypto: talitos - use of_property_read_u32()=0A=
crypto: talitos - use devm_ioremap()=0A=
crypto: talitos - don't check the number of channels at each interrupt=
=0A=
quoted
crypto: talitos - remove to_talitos_ptr_len()=0A=
crypto: talitos - simplify tests in ipsec_esp()=0A=
crypto: talitos - DMA map key in setkey()=0A=
crypto: talitos - do hw_context DMA mapping outside the requests=0A=
crypto: talitos - chain in buffered data for ahash on SEC1=0A=
crypto: talitos - avoid useless copy=0A=
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2017-12-11 11:08:28
On Fri, Dec 08, 2017 at 03:20:40PM +0000, Horia Geantă wrote:
On 10/12/2017 6:20 PM, Herbert Xu wrote:
quoted
On Fri, Oct 06, 2017 at 03:04:31PM +0200, Christophe Leroy wrote:
quoted
This serie fixes and improves the talitos crypto driver.
First 6 patchs are fixes of failures reported by the new tests in the
kernel crypto test manager.
Looks like these fixes are required also on older 4.9+ -stable kernels.
(I haven't seen them on latest 4.9.68-stable mail from Greg, even though
they are in main tree.)
In case you agree, what would be the recommended way to add the patches
to -stable?
At every request, we map and unmap the same hash hw_context.=0A=
=0A=
This patch moves the dma mapping/unmapping in functions ahash_init()=0A=
and ahash_import().=0A=
=0A=
Signed-off-by: Christophe Leroy <redacted>=0A=
---=0A=
drivers/crypto/talitos.c | 80 ++++++++++++++++++++++++++++++++++--------=
@@ -819,6 +819,7 @@ struct talitos_ctx {=0A= unsigned int keylen;=0A= unsigned int enckeylen;=0A= unsigned int authkeylen;=0A=+ dma_addr_t dma_hw_context;=0A=
This doesn't look correct.=0A=
=0A=
talitos_ctx structure is the tfm context.=0A=
dma_hw_context is the IOVA of hw_context, located in talitos_ahash_req_ctx=
=0A=
structure (request context).=0A=
=0A=
If there are multiple requests in flight for the same tfm, dma_hw_context w=
ill=0A=
be overwritten.=0A=
=0A=
dma_hw_context needs to be moved in request context (talitos_ahash_req_ctx =
struct).=0A=
=0A=
Thanks,=0A=
Horia=0A=
At every request, we map and unmap the same hash hw_context.
This patch moves the dma mapping/unmapping in functions ahash_init()
and ahash_import().
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 80 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 57 insertions(+), 23 deletions(-)
This doesn't look correct.
talitos_ctx structure is the tfm context.
dma_hw_context is the IOVA of hw_context, located in talitos_ahash_req_ctx
structure (request context).
Yes but I have now found how I can know that the request context is
being released in order to unmap() dma at that time.
It is tricky to use the tmf context I agree, but at least I know when
tmf context get destroyed, ie in talitos_cra_exit_ahash()
The request context is created by ahash_request_alloc() and released by
ahash_request_free(). I have not found the way to call dma_unmap()
before ahash_request_free() gets called.
If there are multiple requests in flight for the same tfm, dma_hw_context will
be overwritten.
Before overwritting dma_hw_context, it is always released, see
talitos_cra_exit_ahash(), ahash_init(), ahash_import()
dma_hw_context needs to be moved in request context (talitos_ahash_req_ctx struct).
Any suggestion then on how to handle the issue explained above ?
Thanks
Christophe
=0A=
=0A=
Le 07/02/2018 =E0 15:39, Horia Geant=E3 a =E9crit=A0:=0A=
quoted
On 10/6/2017 4:06 PM, Christophe Leroy wrote:=0A=
quoted
At every request, we map and unmap the same hash hw_context.=0A=
=0A=
This patch moves the dma mapping/unmapping in functions ahash_init()=0A=
and ahash_import().=0A=
=0A=
Signed-off-by: Christophe Leroy <redacted>=0A=
---=0A=
drivers/crypto/talitos.c | 80 ++++++++++++++++++++++++++++++++++-----=
@@ -819,6 +819,7 @@ struct talitos_ctx {=0A= unsigned int keylen;=0A= unsigned int enckeylen;=0A= unsigned int authkeylen;=0A=+ dma_addr_t dma_hw_context;=0A=
This doesn't look correct.=0A=
=0A=
talitos_ctx structure is the tfm context.=0A=
dma_hw_context is the IOVA of hw_context, located in talitos_ahash_req_c=
tx=0A=
quoted
structure (request context).=0A=
=0A=
Yes but I have now found how I can know that the request context is =0A=
being released in order to unmap() dma at that time.=0A=
It is tricky to use the tmf context I agree, but at least I know when =0A=
tmf context get destroyed, ie in talitos_cra_exit_ahash()=0A=
The request context is created by ahash_request_alloc() and released by=
=0A=
ahash_request_free(). I have not found the way to call dma_unmap() =0A=
before ahash_request_free() gets called.=0A=
=0A=
quoted
=0A=
If there are multiple requests in flight for the same tfm, dma_hw_contex=
t will=0A=
quoted
be overwritten.=0A=
=0A=
Before overwritting dma_hw_context, it is always released, see =0A=
talitos_cra_exit_ahash(), ahash_init(), ahash_import()=0A=
=0A=
The problem is not the unmapping.=0A=
If there are two requests for the same tfm, then given the following sequen=
ce=0A=
1. tfm->ahash_init(req1)=0A=
tfm_ctx->dma_hw_context points to req1_ctx->hw_context=0A=
2. tfm->ahash_init(req2)=0A=
tfm_ctx->dma_hw_context [unmapped, then] points to req2_ctx->hw_context=0A=
i.e. req1 will use the hw_context of req2.=0A=
=0A=
quoted
=0A=
dma_hw_context needs to be moved in request context (talitos_ahash_req_c=
tx struct).=0A=
=0A=
Any suggestion then on how to handle the issue explained above ?=0A=
=0A=
There is no ahash_exit() callback mirroring ahash_init().=0A=
=0A=
The clean-up of request ctx should be done in the last states of the hash f=
lows=0A=
described here:=0A=
https://www.kernel.org/doc/html/latest/crypto/devel-algos.html#cipher-defin=
ition-with-struct-shash-alg-and-ahash-alg=0A=
for e.g. in the final() callback.=0A=
=0A=
Hope this helps,=0A=
Horia=0A=
At every request, we map and unmap the same hash hw_context.
This patch moves the dma mapping/unmapping in functions ahash_init()
and ahash_import().
Signed-off-by: Christophe Leroy <redacted>
---
drivers/crypto/talitos.c | 80 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 57 insertions(+), 23 deletions(-)
This doesn't look correct.
talitos_ctx structure is the tfm context.
dma_hw_context is the IOVA of hw_context, located in talitos_ahash_req_ctx
structure (request context).
Yes but I have now found how I can know that the request context is
being released in order to unmap() dma at that time.
It is tricky to use the tmf context I agree, but at least I know when
tmf context get destroyed, ie in talitos_cra_exit_ahash()
The request context is created by ahash_request_alloc() and released by
ahash_request_free(). I have not found the way to call dma_unmap()
before ahash_request_free() gets called.
quoted
If there are multiple requests in flight for the same tfm, dma_hw_context will
be overwritten.
Before overwritting dma_hw_context, it is always released, see
talitos_cra_exit_ahash(), ahash_init(), ahash_import()
The problem is not the unmapping.
If there are two requests for the same tfm, then given the following sequence
1. tfm->ahash_init(req1)
tfm_ctx->dma_hw_context points to req1_ctx->hw_context
2. tfm->ahash_init(req2)
tfm_ctx->dma_hw_context [unmapped, then] points to req2_ctx->hw_context
i.e. req1 will use the hw_context of req2.
quoted
quoted
dma_hw_context needs to be moved in request context (talitos_ahash_req_ctx struct).
Any suggestion then on how to handle the issue explained above ?
Unfortunatly it seems that we can't rely on those finalising functions
being called all the time.
If you look into test_ahash_jiffies() for instance, in case of error the
call of crypto_hash_final() is skipped.
So at the time being, I can't see any place to put the unmapping to be
100% sure it will be done before the call of ahash_request_free()
Christophe
=0A=
Unfortunatly it seems that we can't rely on those finalising functions =
=0A=
being called all the time.=0A=
If you look into test_ahash_jiffies() for instance, in case of error the =
=0A=
call of crypto_hash_final() is skipped.=0A=
=0A=
If test_ahash_jiffies() errors before calling crypto_ahash_final(req), this=
=0A=
means a previous callback failed.=0A=
Accordingly, DMA unmapping should be performed also on the corresponding er=
rors=0A=
paths in the driver.=0A=
=0A=
Horia=0A=
Unfortunatly it seems that we can't rely on those finalising functions
being called all the time.
If you look into test_ahash_jiffies() for instance, in case of error the
call of crypto_hash_final() is skipped.
If test_ahash_jiffies() errors before calling crypto_ahash_final(req), this
means a previous callback failed.
Accordingly, DMA unmapping should be performed also on the corresponding errors
paths in the driver.
And what about ALGIF path from user space ?
What if the user never calls the last sendmsg() which will call
hash_finup() ?
Christophe
=0A=
Unfortunatly it seems that we can't rely on those finalising functions=
=0A=
quoted
quoted
being called all the time.=0A=
If you look into test_ahash_jiffies() for instance, in case of error th=
e=0A=
quoted
quoted
call of crypto_hash_final() is skipped.=0A=
=0A=
If test_ahash_jiffies() errors before calling crypto_ahash_final(req), t=
his=0A=
quoted
means a previous callback failed.=0A=
Accordingly, DMA unmapping should be performed also on the corresponding=
errors=0A=
quoted
paths in the driver.=0A=
=0A=
=0A=
And what about ALGIF path from user space ?=0A=
What if the user never calls the last sendmsg() which will call =0A=
hash_finup() ?=0A=
=0A=
User is expected to follow the rules of the crypto API.=0A=
Of course, kernel won't (or at least shouldn't) crash in case of misuse.=0A=
However, in these cases some resources might not be freed - it's unavoidabl=
e.=0A=
=0A=
Horia=0A=
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2018-02-20 10:34:57
On Mon, Feb 19, 2018 at 01:16:30PM +0000, Horia Geantă wrote:
quoted
And what about ALGIF path from user space ?
What if the user never calls the last sendmsg() which will call
hash_finup() ?
User is expected to follow the rules of the crypto API.
Of course, kernel won't (or at least shouldn't) crash in case of misuse.
However, in these cases some resources might not be freed - it's unavoidable.
the crypto API does not require the presence of a finalisation.
It is entirely optional. So leaving resources pinned down until
final/finup occurs is unacceptable, both from user-space and the
kernel.
Cheers,
--
Email: Herbert Xu [off-list ref]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
On Mon, Feb 19, 2018 at 01:16:30PM +0000, Horia Geant=E3 wrote:=0A=
quoted
=0A=
quoted
And what about ALGIF path from user space ?=0A=
What if the user never calls the last sendmsg() which will call =0A=
hash_finup() ?=0A=
=0A=
User is expected to follow the rules of the crypto API.=0A=
Of course, kernel won't (or at least shouldn't) crash in case of misuse.=
=0A=
quoted
However, in these cases some resources might not be freed - it's unavoid=
able.=0A=
=0A=
the crypto API does not require the presence of a finalisation.=0A=
It is entirely optional. So leaving resources pinned down until=0A=
final/finup occurs is unacceptable, both from user-space and the=0A=
kernel.=0A=
=0A=
If final/finup is optional, how is the final hash supposed to be retrieved?=
=0A=
=0A=
According to documentation, these are the accepted flows (with the option t=
o=0A=
export/import a partial hash b/w update and final/finup):=0A=
=0A=
.init() -> .update() -> .final()=0A=
^ | |=0A=
'----' '---> HASH=0A=
=0A=
.init() -> .update() -> .finup()=0A=
^ | |=0A=
'----' '---> HASH=0A=
=0A=
.digest()=0A=
|=0A=
'---------------> HASH=0A=
=0A=
Note that digest() is not an issue in the case we are discussing, since res=
ource=0A=
allocation happens only in init().=0A=
=0A=
Thanks,=0A=
Horia=0A=
On Tue, Feb 20, 2018 at 11:32:25AM +0000, Horia Geant=E3 wrote:=0A=
quoted
=0A=
If final/finup is optional, how is the final hash supposed to be retriev=
ed?=0A=
=0A=
Sometimes the computation ends with a partial hash, that's what=0A=
export is for. Also it is completely legal to abandon the hash=0A=
state entirely.=0A=
=0A=
Thanks for the explanation.=0A=
It's unintuitive to call .init() -> .update() and then not to call any of=
=0A=
.final(), .finup(), .export().=0A=
=0A=
Christophe,=0A=
=0A=
IIUC this means that there is no room for improvement.=0A=
This patch needs to be reverted, to restore previous behaviour when the=0A=
hw_context was mapped / unmapped for every request.=0A=
=0A=
Thanks,=0A=
Horia=0A=
From: Herbert Xu <herbert@gondor.apana.org.au> Date: 2018-02-22 13:46:40
On Thu, Feb 22, 2018 at 12:29:28PM +0000, Horia Geantă wrote:
IIUC this means that there is no room for improvement.
This patch needs to be reverted, to restore previous behaviour when the
hw_context was mapped / unmapped for every request.
In general we should avoid trying to do batching in drivers. Such
optimisations should instead be done at a higher level. For example,
for disk encryption we want to do the aggregation at the block layer
rather than the crypto API because that has innate knowledge of the
data layout which we can only guess.
Cheers,
--
Email: Herbert Xu [off-list ref]
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Where is desc->next_desc initialized for the !is_sec1 case?=0A=
Memory allocation is done using kmalloc(), and since desc->next_desc is che=
cked=0A=
in some cases also for SEC 2.x+, it should be initialized to 0.=0A=
=0A=
Thanks,=0A=
Horia=0A=
=0A=
Where is desc->next_desc initialized for the !is_sec1 case?
Memory allocation is done using kmalloc(), and since desc->next_desc is checked
in some cases also for SEC 2.x+, it should be initialized to 0.