Re: [PATCH v3] crypto: AF_ALG - remove locking in async callback
2017-11-10 13:20 GMT+01:00 Stephan Müller <smuel...@chronox.de>: > The code paths protected by the socket-lock do not use or modify the > socket in a non-atomic fashion. The actions pertaining the socket do not > even need to be handled as an atomic operation. Thus, the socket-lock > can be safely ignored. > > This fixes a bug regarding scheduling in atomic as the callback function > may be invoked in interrupt context. > > In addition, the sock_hold is moved before the AIO encrypt/decrypt > operation to ensure that the socket is always present. This avoids a > tiny race window where the socket is unprotected and yet used by the AIO > operation. > > Finally, the release of resources for a crypto operation is moved into a > common function of af_alg_free_resources. > > Fixes: e870456d8e7c8 ("crypto: algif_skcipher - overhaul memory management") > Fixes: d887c52d6ae43 ("crypto: algif_aead - overhaul memory management") > Reported-by: Romain Izard <romain.izard....@gmail.com> > Signed-off-by: Stephan Mueller <smuel...@chronox.de> Tested-by: Romain Izard <romain.izard@gmail.com> On 4.14-rc8, with some fuzzing when applying the patch. The deterministic crash is not reproduced. > --- > crypto/af_alg.c | 21 ++--- > crypto/algif_aead.c | 23 --- > crypto/algif_skcipher.c | 23 --- > include/crypto/if_alg.h | 1 + > 4 files changed, 39 insertions(+), 29 deletions(-) > > diff --git a/crypto/af_alg.c b/crypto/af_alg.c > index 85cea9de324a..358749c38894 100644 > --- a/crypto/af_alg.c > +++ b/crypto/af_alg.c > @@ -1021,6 +1021,18 @@ ssize_t af_alg_sendpage(struct socket *sock, struct > page *page, > EXPORT_SYMBOL_GPL(af_alg_sendpage); > > /** > + * af_alg_free_resources - release resources required for crypto request > + */ > +void af_alg_free_resources(struct af_alg_async_req *areq) > +{ > + struct sock *sk = areq->sk; > + > + af_alg_free_areq_sgls(areq); > + sock_kfree_s(sk, areq, areq->areqlen); > +} > +EXPORT_SYMBOL_GPL(af_alg_free_resources); > + > +/** > * af_alg_async_cb - AIO callback handler > * > * This handler cleans up the struct af_alg_async_req upon completion of the > @@ -1036,18 +1048,13 @@ void af_alg_async_cb(struct crypto_async_request > *_req, int err) > struct kiocb *iocb = areq->iocb; > unsigned int resultlen; > > - lock_sock(sk); > - > /* Buffer size written by crypto operation. */ > resultlen = areq->outlen; > > - af_alg_free_areq_sgls(areq); > - sock_kfree_s(sk, areq, areq->areqlen); > - __sock_put(sk); > + af_alg_free_resources(areq); > + sock_put(sk); > > iocb->ki_complete(iocb, err ? err : resultlen, 0); > - > - release_sock(sk); > } > EXPORT_SYMBOL_GPL(af_alg_async_cb); > > diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c > index aacae0837aff..db9378a45296 100644 > --- a/crypto/algif_aead.c > +++ b/crypto/algif_aead.c > @@ -268,12 +268,23 @@ static int _aead_recvmsg(struct socket *sock, struct > msghdr *msg, > > if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { > /* AIO operation */ > + sock_hold(sk); > areq->iocb = msg->msg_iocb; > aead_request_set_callback(>cra_u.aead_req, > CRYPTO_TFM_REQ_MAY_BACKLOG, > af_alg_async_cb, areq); > err = ctx->enc ? crypto_aead_encrypt(>cra_u.aead_req) : > crypto_aead_decrypt(>cra_u.aead_req); > + > + /* AIO operation in progress */ > + if (err == -EINPROGRESS || err == -EBUSY) { > + /* Remember output size that will be generated. */ > + areq->outlen = outlen; > + > + return -EIOCBQUEUED; > + } > + > + sock_put(sk); > } else { > /* Synchronous operation */ > aead_request_set_callback(>cra_u.aead_req, > @@ -285,19 +296,9 @@ static int _aead_recvmsg(struct socket *sock, struct > msghdr *msg, > >wait); > } > > - /* AIO operation in progress */ > - if (err == -EINPROGRESS) { > - sock_hold(sk); > - > - /* Remember output size that will be generated. */ > - areq->outlen = outlen; > - > - return -EIOCBQUEUED; > - } > > free: > -
Re: [PATCH 2/2] crypto: atmel-aes - Reset the controller before each use
2017-11-06 16:45 GMT+01:00 Tudor Ambarus <tudor.amba...@microchip.com>: > Hi, Romain, > > On 10/31/2017 05:25 PM, Romain Izard wrote: >> >> When using the rfc4543(gcm(aes))) mode, the registers of the hardware >> engine are not empty after use. If the engine is not reset before its >> next use, the following results will be invalid. >> >> Always reset the hardware engine. > > > Thanks for the fix! I could reproduce the issue only when running > rfc4543(gcm(aes))) and then, immediately after, ecb(aes). > > Have you encountered this bug with other combination of algorithms? > > I'm trying to isolate the bug so that we can have a more fine-grained > fix. I just ran the tcrypt tests because they were failing on the cts(cbc(aes)) transform and I observed this issue when the ecb test failed only on the second run. For me, the issue looks like the rfc4543 mode does not read all the registers from the AES engine, and the following operation fails because the registers are reused directly in the ECB mode. As the ECB mode is a rare case where we do not use an IV, this may be the reason why other modes do not display the issue. -- Romain Izard
[PATCH 1/2] crypto: atmel-aes - properly set IV after {en,de}crypt
Certain cipher modes like CTS expect the IV (req->info) of ablkcipher_request (or equivalently req->iv of skcipher_request) to contain the last ciphertext block when the {en,de}crypt operation is done. Fix this issue for the Atmel AES hardware engine. The tcrypt test case for cts(cbc(aes)) is now correctly passed. In the case of in-place decryption, copy the ciphertext in an intermediate buffer before decryption. Signed-off-by: Romain Izard <romain.izard@gmail.com> --- drivers/crypto/atmel-aes.c | 40 +--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 29e20c37f3a6..53432ab97d7e 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -110,6 +110,7 @@ struct atmel_aes_base_ctx { int keylen; u32 key[AES_KEYSIZE_256 / sizeof(u32)]; u16 block_size; + boolis_aead; }; struct atmel_aes_ctx { @@ -156,6 +157,7 @@ struct atmel_aes_authenc_ctx { struct atmel_aes_reqctx { unsigned long mode; + u32 lastc[AES_BLOCK_SIZE / sizeof(u32)]; }; #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC @@ -497,12 +499,34 @@ static void atmel_aes_authenc_complete(struct atmel_aes_dev *dd, int err); static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) { #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC - atmel_aes_authenc_complete(dd, err); + if (dd->ctx->is_aead) + atmel_aes_authenc_complete(dd, err); #endif clk_disable(dd->iclk); dd->flags &= ~AES_FLAGS_BUSY; + if (!dd->ctx->is_aead) { + struct ablkcipher_request *req = + ablkcipher_request_cast(dd->areq); + struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); + struct crypto_ablkcipher *ablkcipher = + crypto_ablkcipher_reqtfm(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + if (rctx->mode & AES_FLAGS_ENCRYPT) { + scatterwalk_map_and_copy(req->info, req->dst, + req->nbytes - ivsize, ivsize, 0); + } else { + if (req->src == req->dst) { + memcpy(req->info, rctx->lastc, ivsize); + } else { + scatterwalk_map_and_copy(req->info, req->src, + req->nbytes - ivsize, ivsize, 0); + } + } + } + if (dd->is_async) dd->areq->complete(dd->areq, err); @@ -1071,11 +1095,11 @@ static int atmel_aes_ctr_start(struct atmel_aes_dev *dd) static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode) { - struct atmel_aes_base_ctx *ctx; + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + struct atmel_aes_base_ctx *ctx = crypto_ablkcipher_ctx(ablkcipher); struct atmel_aes_reqctx *rctx; struct atmel_aes_dev *dd; - ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); switch (mode & AES_FLAGS_OPMODE_MASK) { case AES_FLAGS_CFB8: ctx->block_size = CFB8_BLOCK_SIZE; @@ -1097,6 +1121,7 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode) ctx->block_size = AES_BLOCK_SIZE; break; } + ctx->is_aead = false; dd = atmel_aes_find_dev(ctx); if (!dd) @@ -1105,6 +1130,13 @@ static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long mode) rctx = ablkcipher_request_ctx(req); rctx->mode = mode; + if (!(mode & AES_FLAGS_ENCRYPT) && (req->src == req->dst)) { + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + + scatterwalk_map_and_copy(rctx->lastc, req->src, + (req->nbytes - ivsize), ivsize, 0); + } + return atmel_aes_handle_queue(dd, >base); } @@ -1739,6 +1771,7 @@ static int atmel_aes_gcm_crypt(struct aead_request *req, ctx = crypto_aead_ctx(crypto_aead_reqtfm(req)); ctx->block_size = AES_BLOCK_SIZE; + ctx->is_aead = true; dd = atmel_aes_find_dev(ctx); if (!dd) @@ -2223,6 +2256,7 @@ static int atmel_aes_authenc_crypt(struct aead_request *req, rctx->base.mode = mode; ctx->block_size = AES_BLOCK_SIZE; + ctx->is_aead = true; dd = atmel_aes_find_dev(ctx); if (!dd) -- 2.14.1
[PATCH 2/2] crypto: atmel-aes - Reset the controller before each use
When using the rfc4543(gcm(aes))) mode, the registers of the hardware engine are not empty after use. If the engine is not reset before its next use, the following results will be invalid. Always reset the hardware engine. Signed-off-by: Romain Izard <romain.izard@gmail.com> --- drivers/crypto/atmel-aes.c | 10 +++--- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 53432ab97d7e..024914e82734 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -76,12 +76,11 @@ AES_FLAGS_ENCRYPT |\ AES_FLAGS_GTAGEN) -#define AES_FLAGS_INIT BIT(2) #define AES_FLAGS_BUSY BIT(3) #define AES_FLAGS_DUMP_REG BIT(4) #define AES_FLAGS_OWN_SHA BIT(5) -#define AES_FLAGS_PERSISTENT (AES_FLAGS_INIT | AES_FLAGS_BUSY) +#define AES_FLAGS_PERSISTENT AES_FLAGS_BUSY #define ATMEL_AES_QUEUE_LENGTH 50 @@ -450,11 +449,8 @@ static int atmel_aes_hw_init(struct atmel_aes_dev *dd) if (err) return err; - if (!(dd->flags & AES_FLAGS_INIT)) { - atmel_aes_write(dd, AES_CR, AES_CR_SWRST); - atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET); - dd->flags |= AES_FLAGS_INIT; - } + atmel_aes_write(dd, AES_CR, AES_CR_SWRST); + atmel_aes_write(dd, AES_MR, 0xE << AES_MR_CKEY_OFFSET); return 0; } -- 2.14.1
[PATCH 0/2] Fixes for the Atmel AES crypto module
After encountering an issue with cts(cbc(aes)) in the Atmel AES module, I have used tcrypt and libkcapi's test suite to validate my fix. This led me to observe some other issues. This series includes the IV issue correction for the Atmel AES crypto engine, as well as a secondary issue observed when running 'insmod tcrypt.ko mode=10' and 'insmod tcrypt.ko mode=152' on a SAMA5D2 board. The libkcapi test suite still reports some problems, for example when the input data is too large to fit into an intermediate buffer in unaligned cases. And it seems that with the v4.14 updates, new asynchronous tests are enabled and report new issues. Romain Izard (2): crypto: atmel-aes - properly set IV after {en,de}crypt crypto: atmel-aes - Reset the controller before each use drivers/crypto/atmel-aes.c | 50 -- 1 file changed, 40 insertions(+), 10 deletions(-) -- 2.14.1
[PATCH] crypto: ccm - preserve the IV buffer
The IV buffer used during CCM operations is used twice, during both the hashing step and the ciphering step. When using a hardware accelerator that updates the contents of the IV buffer at the end of ciphering operations, the value will be modified. In the decryption case, the subsequent setup of the hashing algorithm will interpret the updated IV instead of the original value, which can lead to out-of-bounds writes. Reuse the idata buffer, only used in the hashing step, to preserve the IV's value during the ciphering step in the decryption case. Signed-off-by: Romain Izard <romain.izard@gmail.com> --- crypto/ccm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crypto/ccm.c b/crypto/ccm.c index 1ce37ae0ce56..0a083342ec8c 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -363,7 +363,7 @@ static int crypto_ccm_decrypt(struct aead_request *req) unsigned int cryptlen = req->cryptlen; u8 *authtag = pctx->auth_tag; u8 *odata = pctx->odata; - u8 *iv = req->iv; + u8 *iv = pctx->idata; int err; cryptlen -= authsize; @@ -379,6 +379,8 @@ static int crypto_ccm_decrypt(struct aead_request *req) if (req->src != req->dst) dst = pctx->dst; + memcpy(iv, req->iv, 16); + skcipher_request_set_tfm(skreq, ctx->ctr); skcipher_request_set_callback(skreq, pctx->flags, crypto_ccm_decrypt_done, req); -- 2.14.1
Re: [PATCH] crypto: AF_ALG - remove locking in async callback
2017-10-29 21:39 GMT+01:00 Stephan Müller <smuel...@chronox.de>: > Am Mittwoch, 25. Oktober 2017, 17:26:31 CET schrieb Romain Izard: > > Hi Romain, > > the patch below should cover the issue you see. Would you mind testing it? > > Thanks > Stephan > > ---8<--- > > The code paths protected by the socket-lock do not use or modify the > socket in a non-atomic fashion. The actions pertaining the socket do not > even need to be handled as an atomic operation. Thus, the socket-lock > can be safely ignored. > > This fixes a bug regarding scheduling in atomic as the callback function > may be invoked in interrupt context. > > Fixes: 2d97591ef43d0 ("crypto: af_alg - consolidation of duplicate code") > Reported-by: Romain Izard <romain.izard@gmail.com> > Signed-off-by: Stephan Mueller <smuel...@chronox.de> Tested-by: Romain Izard <romain.izard@gmail.com> The issue observed with atmel-aes is not reproduced anymore. > --- > crypto/af_alg.c | 4 > 1 file changed, 4 deletions(-) > > diff --git a/crypto/af_alg.c b/crypto/af_alg.c > index 337cf382718e..a41f08642eee 100644 > --- a/crypto/af_alg.c > +++ b/crypto/af_alg.c > @@ -1063,8 +1063,6 @@ void af_alg_async_cb(struct crypto_async_request *_req, > int err) > struct kiocb *iocb = areq->iocb; > unsigned int resultlen; > > - lock_sock(sk); > - > /* Buffer size written by crypto operation. */ > resultlen = areq->outlen; > > @@ -1073,8 +1071,6 @@ void af_alg_async_cb(struct crypto_async_request *_req, > int err) > __sock_put(sk); > > iocb->ki_complete(iocb, err ? err : resultlen, 0); > - > - release_sock(sk); > } > EXPORT_SYMBOL_GPL(af_alg_async_cb); > > -- > 2.13.6 > >
Re: Kernel panic when using ccm(aes) with the Atmel AES HW accelerator
2017-10-26 14:34 GMT+02:00 Tudor Ambarus <tudor.amba...@microchip.com>: > Hi, Romain, > > On 10/18/2017 04:32 PM, Romain Izard wrote: >> >> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c >> index 29e20c37f3a6..f3eabe1f1490 100644 >> --- a/drivers/crypto/atmel-aes.c >> +++ b/drivers/crypto/atmel-aes.c >> @@ -80,6 +80,7 @@ >> #define AES_FLAGS_BUSY BIT(3) >> #define AES_FLAGS_DUMP_REG BIT(4) >> #define AES_FLAGS_OWN_SHA BIT(5) >> +#define AES_FLAGS_CIPHERTAIL BIT(6) > > > not really needed, see below. > >> >> #define AES_FLAGS_PERSISTENT (AES_FLAGS_INIT | AES_FLAGS_BUSY) >> >> @@ -156,6 +157,7 @@ struct atmel_aes_authenc_ctx { >> >> struct atmel_aes_reqctx { >> unsigned long mode; >> + u32 ciphertail[AES_BLOCK_SIZE / sizeof(u32)]; > > How about renaming this variable to "lastc"? Ci, i=1..n is the usual > notation for the ciphertext blocks. > OK > The assumption that the last ciphertext block is of AES_BLOCK_SIZE size > is correct, this driver is meant just for AES. > >> }; >> >> #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC >> @@ -496,6 +498,11 @@ static void atmel_aes_authenc_complete(struct >> atmel_aes_dev *dd, int err); >> >> static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) >> { >> + struct ablkcipher_request *req = >> ablkcipher_request_cast(dd->areq); >> + struct crypto_ablkcipher *ablkcipher = >> crypto_ablkcipher_reqtfm(req); >> + struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); >> + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); >> + >> #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC >> atmel_aes_authenc_complete(dd, err); >> #endif >> @@ -503,6 +510,17 @@ static inline int atmel_aes_complete(struct >> atmel_aes_dev *dd, int err) >> clk_disable(dd->iclk); >> dd->flags &= ~AES_FLAGS_BUSY; >> >> + if (rctx->mode & AES_FLAGS_CIPHERTAIL) { >> + if (rctx->mode & AES_FLAGS_ENCRYPT) { >> + scatterwalk_map_and_copy(req->info, req->dst, >> +req->nbytes - ivsize, >> +ivsize, 0); >> + } else { >> + memcpy(req->info, rctx->ciphertail, ivsize); > > > why don't we make the same assumption and replace ivsize with > AES_BLOCK_SIZE? Is there any chance that req->info was allocated with > less than AES_BLOCK_SIZE size? > I do not really know. I'm just getting used to the crypto framework, and the fact that the iv buffer size is implicit... >> + memset(rctx->ciphertail, 0, ivsize); > > > memset to zero is not necessary. > OK >> + } >> + } >> + >> if (dd->is_async) >> dd->areq->complete(dd->areq, err); >> >> @@ -1071,11 +1089,13 @@ static int atmel_aes_ctr_start(struct >> atmel_aes_dev *dd) >> >> static int atmel_aes_crypt(struct ablkcipher_request *req, unsigned long >> mode) >> { >> + struct crypto_ablkcipher *ablkcipher; >> struct atmel_aes_base_ctx *ctx; >> struct atmel_aes_reqctx *rctx; >> struct atmel_aes_dev *dd; >> >> - ctx = crypto_ablkcipher_ctx(crypto_ablkcipher_reqtfm(req)); >> + ablkcipher = crypto_ablkcipher_reqtfm(req); >> + ctx = crypto_ablkcipher_ctx(ablkcipher); > > > you can initialize these variables at declaration. > OK >> switch (mode & AES_FLAGS_OPMODE_MASK) { >> case AES_FLAGS_CFB8: >> ctx->block_size = CFB8_BLOCK_SIZE; >> @@ -1103,7 +1123,15 @@ static int atmel_aes_crypt(struct >> ablkcipher_request *req, unsigned long mode) >> return -ENODEV; >> >> rctx = ablkcipher_request_ctx(req); > > > while here, please initialize this at declaration. > > Also, this one: > ''' > dd = atmel_aes_find_dev(ctx); > if (!dd) > return -ENODEV; > > ''' > should be moved at the beginning of the function. If an initialization > might fail, let's check it as soon as we can, so that we don't waste > resources. > Most of these initializations are in fact structure casts. >> - rctx->mode = mode; >> + >> + if (!(mode & AES_FLAGS_ENCRYPT)) { >> +
"BUG: scheduling while atomic" in atmel-aes on Linux v4.14-rc6
Hello, While running the kcapi test suite on a SAMA5D2 Xplained board with a v4.14-rc6 kernel, I encountered the following error: # kcapi -x 9 -e -c "cbc(aes)" -i -k 000 0 -p 1b077a6af4b7f98229de786d7516b639 BUG: scheduling while atomic: kcapi/926/0x0100 CPU: 0 PID: 926 Comm: kcapi Not tainted 4.14.0-rc6 #2 Hardware name: Atmel SAMA5 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (__schedule_bug+0x60/0x80) [] (__schedule_bug) from [] (__schedule+0x368/0x3fc) [] (__schedule) from [] (schedule+0x40/0xa0) [] (schedule) from [] (__lock_sock+0x78/0xb0) [] (__lock_sock) from [] (lock_sock_nested+0x48/0x50) [] (lock_sock_nested) from [] (af_alg_async_cb+0x20/0x80) [] (af_alg_async_cb) from [] (atmel_aes_transfer_complete+0x38/0x68) [] (atmel_aes_transfer_complete) from [] (tasklet_action+0x68/0xb4) [] (tasklet_action) from [] (__do_softirq+0xc4/0x250) [] (__do_softirq) from [] (irq_exit+0xfc/0x130) [] (irq_exit) from [] (__handle_domain_irq+0x58/0xa8) [] (__handle_domain_irq) from [] (__irq_svc+0x6c/0x90) [] (__irq_svc) from [] (skcipher_recvmsg+0x2d8/0x318) [] (skcipher_recvmsg) from [] (sock_read_iter+0x88/0xc8) [] (sock_read_iter) from [] (aio_read.constprop.3+0xcc/0x178) [] (aio_read.constprop.3) from [] (SyS_io_submit+0x540/0x644) [] (SyS_io_submit) from [] (ret_fast_syscall+0x0/0x48) After bisecting, I determined that it appeared during the 4.14 merge window, with the following commit: e870456d8e7c crypto: algif_skcipher - overhaul memory management Best regards, -- Romain Izard
Re: Kernel panic when using ccm(aes) with the Atmel AES HW accelerator
2017-10-24 5:20 GMT+02:00 Herbert Xu <herb...@gondor.apana.org.au>: > On Mon, Oct 23, 2017 at 03:38:59PM +0300, Tudor Ambarus wrote: >> >> I will propose a fix, but I'm taking my time to better understand why >> CTR requires to overwrite the iv with the last ciphertext block. > > That's an API requirement. So we should fix ccm. > Where is the documentation for this API requirement? I tried to find it in the kernel, but I only found a few comments in the commit messages or in the implementations, but not an explicit requirement. Moreover, as it seems to be a common mistake in the crypto accelerators, I believe that the algorithms' self-test should also check the IV at the end of a request. In the decryption case, the code should probably be shared for most implementations: we need to save the input data before decryption in case of in-place decoding, and restore it into the IV buffer before returning to the caller. -- Romain Izard
Kernel panic when using ccm(aes) with the Atmel AES HW accelerator
ctx->odata; - u8 *iv = req->iv; + u8 *iv = pctx->iv; int err; - err = crypto_ccm_init_crypt(req, odata); + err = crypto_ccm_init_crypt(req, odata, iv); if (err) return err; @@ -363,12 +354,12 @@ static int crypto_ccm_decrypt(struct aead_request *req) unsigned int cryptlen = req->cryptlen; u8 *authtag = pctx->auth_tag; u8 *odata = pctx->odata; - u8 *iv = req->iv; + u8 *iv = pctx->iv; int err; cryptlen -= authsize; - err = crypto_ccm_init_crypt(req, authtag); + err = crypto_ccm_init_crypt(req, authtag, iv); if (err) return err; 8<-- My problem is that I do not understand why it works. It ensures that in both encryption and decryption cases, the IV buffer is available and 16 bytes wide. But normally the IV buffer provided by the crypto request is already 16 bytes wide, as the algorithm is registered with ivsize=16. As I am not very familiar with the crypto subsystem, I fear that I missed something. I would gladly appreciate the feedback of more experienced developers regarding this issue. Best regards, -- Romain Izard
Re: [PATCH] crypto: atmel-aes - properly set IV after {en,de}crypt
2017-10-10 16:16 GMT+02:00 Boris Brezillon <boris.brezil...@free-electrons.com>: > Hi Romain, > > May I ask why you're sending this patch to the MTD ML? > This is related to an issue reported by Nicolas Feignon with UBIFS and fscrypt, which was reported on both mtd and fscrypt mailing lists. The file names are encrypted with cts(cbc(aes)), and this patch tried to fix a SAMA5D2 issue where the file names are not correctly encrypted when hardware acceleration is enabled. > While I'm here, can you have a look at this patch [1] and add you > Reviewed-by/Tested-by? > > [1]http://patchwork.ozlabs.org/patch/821959/ I'll try it. -- Romain Izard
Re: [PATCH] crypto: atmel-aes - properly set IV after {en,de}crypt
2017-10-06 17:51 GMT+02:00 Romain Izard <romain.izard@gmail.com>: > > Certain cipher modes like CTS expect the IV (req->info) of > ablkcipher_request (or equivalently req->iv of skcipher_request) to > contain the last ciphertext block when the {en,de}crypt operation is done. > > Fix this issue for the Atmel AES hardware engine. The tcrypt test > case for cts(cbc(aes)) is now correctly passed. > > To handle the case of in-place decryption, copy the ciphertext in an > intermediate buffer before decryption. > Unfortunately this does not seem to be enough. The tcrypt module's tests pass, but I encounter more issues. If I run the libkcapi test suite, I end up randomly with the following type of panic: 8< -- Unable to handle kernel paging request at virtual address 7ffc pgd = dee9c000 [7ffc] *pgd= Internal error: Oops: 5 [#1] ARM Modules linked in: CPU: 0 PID: 2187 Comm: kcapi Not tainted 4.13.4+ #16 Hardware name: Atmel SAMA5 task: dec7f280 task.stack: dee82000 PC is at memcpy+0x114/0x330 LR is at atmel_aes_transfer_complete+0x64/0xe8 pc : []lr : []psr: 2013 sp : dee83bcc ip : 0003 fp : dee83bfc r10: r9 : df638940 r8 : df638874 r7 : 0010 r6 : r5 : df638940 r4 : dec68110 r3 : 4004 r2 : 000c r1 : 7ffc r0 : df638afc Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c53c7d Table: 3ee9c059 DAC: 0051 Process kcapi (pid: 2187, stack limit = 0xdee82208) Stack: (0xdee83bcc to 0xdee84000) 3bc0:df638afc dec68110 c05e419c 3be0: 0030 dec68110 df557040 0030 dee83c3c dee83c00 c05e61cc c05e4144 3c00: 10031000 dec68110 df6388a4 0030 df6388a4 dec68110 df6388a4 0030 3c20: 0030 df638874 df557070 dee83c6c dee83c40 c05e488c c05e6064 3c40: df6388a4 df638874 dee83c6c dec68110 0030 0030 df6388a4 df638874 3c60: dee83c94 dee83c70 c05e4998 c05e471c 0030 dec68110 df557040 3c80: df638874 df557070 dee83cd4 dee83c98 c05e6198 c05e48d4 c05e6058 3ca0: dee83cbc df6388a4 c041ab04 dec68110 df557040 df638940 ff8d 3cc0: a013 0004 dee83d04 dee83cd8 c05e62f8 c05e6064 dee83d3c dee83ce8 3ce0: c01dbe9c dec68110 df638940 df638940 ff8d dee83d2c dee83d08 3d00: c05e4ac8 c05e61f8 df638940 4000 df638800 df557000 0020 df638860 3d20: dee83d44 dee83d30 c05e4b50 c05e4a14 df638874 0400 dee83d54 dee83d48 3d40: c05e4ba0 c05e4af0 dee83d74 dee83d58 c034997c c05e4b90 df638840 df638800 3d60: dec3e4c0 dee83db4 dee83d78 c0368f70 c0349918 c03bfab0 3d80: df6388a4 df638afc dfff1bc2 df63898c df638988 df608800 0040 df701000 3da0: df63898c dee83e28 dee83e1c dee83db8 c0393514 c0368e88 df701000 df608800 3dc0: 0020 df638afc 030c 0188 df63898c df638800 0044 014000c0 3de0: df638ae8 0040 dee83e20 df701000 0040 dee83e80 c0392d48 df61ff00 3e00: df241200 dee83e80 0004a150 dee83e6c dee83e20 c0641d8c c0392d54 3e20: dee83ea0 c0101254 3e40: dee4f400 df61ff00 dee4f400 3e60: dee83efc dee83e70 c0242950 c0641cfc dee83e80 c07edac4 8013 3e80: 0040 dee83e98 0001 c0101254 0004a298 0040 3ea0: f7f27003 0055 b6f27000 df644000 00f6 c0108ea4 0004a150 3ec0: e000 c021636c dee83ee4 dee83ed8 c021636c c02162d8 dee83efc 00049148 3ee0: dee4f400 df61ff00 df557200 dee83fa4 dee83f00 c0243db8 c024285c 3f00: dee83f1c c0d05f40 c0d98a98 014080c0 c0d9ad5c 0001 e000 3f20: dee83f20 dee83f20 dee83f28 dee83f28 dee83f30 dee83f30 3f40: 0007 0004a298 0040 3f60: 0001 0006 011d b6f2bce8 3f80: 00f6 c0108ea4 dee82000 dee83fa8 3fa0: c0108ce0 c0243734 b6f2bce8 b6f27000 0001 0004a150 00049188 3fc0: b6f2bce8 00f6 0001 000490b8 000490d4 3fe0: bee3d838 bee3d828 b6ee63bc b6e73810 6010 b6f27000 [] (memcpy) from [] (atmel_aes_transfer_complete+0x64/0xe8) [] (atmel_aes_transfer_complete) from [] (atmel_aes_ctr_transfer+0x174/0x194) [] (atmel_aes_ctr_transfer) from [] (atmel_aes_cpu_transfer+0x17c/0x1b8) [] (atmel_aes_cpu_transfer) from [] (atmel_aes_cpu_start+0xd0/0xd4) [] (atmel_aes_cpu_start) from [] (atmel_aes_ctr_transfer+0x140/0x194) [] (atmel_aes_ctr_transfer) from [] (atmel_aes_ctr_start+0x10c/0x15c) [] (atmel_aes_ctr_start) from [] (atmel_aes_handle_queue+0xc0/0xdc) [] (atmel_aes_handle_queue) from [] (atmel_aes_crypt+0x6c/0xa0) [] (atmel_aes_crypt) from [] (atmel_aes_ctr_decrypt+0x1c/0x20) [] (atmel_aes_ctr_decrypt) from [] (skcipher_decrypt_ablkcipher+0x70/0x74) [] (skcipher_decrypt_ab
[PATCH] crypto: atmel-aes - properly set IV after {en,de}crypt
Certain cipher modes like CTS expect the IV (req->info) of ablkcipher_request (or equivalently req->iv of skcipher_request) to contain the last ciphertext block when the {en,de}crypt operation is done. Fix this issue for the Atmel AES hardware engine. The tcrypt test case for cts(cbc(aes)) is now correctly passed. To handle the case of in-place decryption, copy the ciphertext in an intermediate buffer before decryption. Signed-off-by: Romain Izard <romain.izard@gmail.com> --- drivers/crypto/atmel-aes.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c index 29e20c37f3a6..f22300babb45 100644 --- a/drivers/crypto/atmel-aes.c +++ b/drivers/crypto/atmel-aes.c @@ -156,6 +156,7 @@ struct atmel_aes_authenc_ctx { struct atmel_aes_reqctx { unsigned long mode; + u8 *backup_info; }; #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC @@ -496,6 +497,12 @@ static void atmel_aes_authenc_complete(struct atmel_aes_dev *dd, int err); static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) { + struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); + struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + bool enc = atmel_aes_is_encrypt(dd); + #ifdef CONFIG_CRYPTO_DEV_ATMEL_AUTHENC atmel_aes_authenc_complete(dd, err); #endif @@ -503,6 +510,15 @@ static inline int atmel_aes_complete(struct atmel_aes_dev *dd, int err) clk_disable(dd->iclk); dd->flags &= ~AES_FLAGS_BUSY; + if (enc) { + scatterwalk_map_and_copy(req->info, req->dst, +req->nbytes - ivsize, ivsize, 0); + } else if (rctx->backup_info) { + memcpy(req->info, rctx->backup_info, ivsize); + kfree(rctx->backup_info); + rctx->backup_info = NULL; + } + if (dd->is_async) dd->areq->complete(dd->areq, err); @@ -959,13 +975,25 @@ static int atmel_aes_transfer_complete(struct atmel_aes_dev *dd) static int atmel_aes_start(struct atmel_aes_dev *dd) { struct ablkcipher_request *req = ablkcipher_request_cast(dd->areq); + struct crypto_ablkcipher *ablkcipher = crypto_ablkcipher_reqtfm(req); struct atmel_aes_reqctx *rctx = ablkcipher_request_ctx(req); + int ivsize = crypto_ablkcipher_ivsize(ablkcipher); + bool enc = atmel_aes_is_encrypt(dd); bool use_dma = (req->nbytes >= ATMEL_AES_DMA_THRESHOLD || dd->ctx->block_size != AES_BLOCK_SIZE); int err; atmel_aes_set_mode(dd, rctx); + if (!enc) { + rctx->backup_info = kzalloc(ivsize, GFP_KERNEL); + if (rctx->backup_info == NULL) + return atmel_aes_complete(dd, -ENOMEM); + + scatterwalk_map_and_copy(rctx->backup_info, req->src, +(req->nbytes - ivsize), ivsize, 0); + } + err = atmel_aes_hw_init(dd); if (err) return atmel_aes_complete(dd, err); -- 2.11.0