* Re: [PATCH v18 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O
From: Eric Biggers @ 2026-05-24 20:49 UTC (permalink / raw)
To: Bartosz Golaszewski
Cc: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong, dmaengine, linux-doc, linux-kernel, linux-arm-msm,
linux-crypto, linux-arm-kernel, brgl, Bartosz Golaszewski,
Dmitry Baryshkov, Konrad Dybcio
In-Reply-To: <20260522-qcom-qce-cmd-descr-v18-0-99103926bafc@oss.qualcomm.com>
On Fri, May 22, 2026 at 03:39:53PM +0200, Bartosz Golaszewski wrote:
> Currently the QCE crypto driver accesses the crypto engine registers
> directly via CPU. Trust Zone may perform crypto operations simultaneously
> resulting in a race condition.
So this driver is just critically broken currently? Yet it's still not
marked as BROKEN?
What are we even doing?
- Eric
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Eric Biggers @ 2026-05-24 20:45 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Demi Marie Obenour, Dmitry Baryshkov, Herbert Xu, David S. Miller,
Thara Gopinath, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Konrad Dybcio, Russell King, linux-kernel,
linux-crypto, linux-arm-msm, Ard Biesheuvel, devicetree,
linux-arm-kernel
In-Reply-To: <d97382a6-6c5d-4a3f-89cc-3ae9b432de3f@kernel.org>
On Sun, May 24, 2026 at 10:29:28PM +0200, Krzysztof Kozlowski wrote:
> On 24/05/2026 22:12, Demi Marie Obenour wrote:
> > On 5/24/26 12:42, Dmitry Baryshkov wrote:
> >> On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
> >>> From: Demi Marie Obenour <demiobenour@gmail.com>
> >>>
> >>> It's slower than the generic C code and causes problems.
> >>
> >> Which problems?
> >
> > See https://lore.kernel.org/all/20260522024912.GC5937@quark/.
>
> Your commit is still incomplete and other people's opinion is poor
> reason. If you do not know what to write, ask that person to make
> necessary changes.
>
> Not mentioning that removing driver is not even necessary to achieve the
> goal Eric was mentioning and if I understood correctly: you are removing
> even the pieces Eric found useful.
This driver is more than an order of magnitude slower than the CPU for
both encryption and hashing. See:
https://lore.kernel.org/r/20250704070322.20692-1-ebiggers@kernel.org/
https://lore.kernel.org/r/20250615031807.GA81869@sol/
There are many examples of it having bugs as well, for example see the
second link above.
That's why it had to be disabled via the cra_priority system. This
driver was actively making Linux worse.
This isn't particularly unique to drivers/crypto/, of course. This one
we just have data on, so it's a bit clearer.
I've yet to see any real reason to keep this driver.
Crypto drivers need to be held to a higher standard than other device
drivers, as well. The onus is on those who want to keep a particular
crypto driver to prove that it's worth keeping.
- Eric
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Demi Marie Obenour @ 2026-05-24 20:31 UTC (permalink / raw)
To: Krzysztof Kozlowski, Dmitry Baryshkov
Cc: Herbert Xu, David S. Miller, Thara Gopinath, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Russell King, linux-kernel, linux-crypto, linux-arm-msm,
Eric Biggers, Ard Biesheuvel, devicetree, linux-arm-kernel
In-Reply-To: <d97382a6-6c5d-4a3f-89cc-3ae9b432de3f@kernel.org>
[-- Attachment #1.1.1: Type: text/plain, Size: 1919 bytes --]
On 5/24/26 16:29, Krzysztof Kozlowski wrote:
> On 24/05/2026 22:12, Demi Marie Obenour wrote:
>> On 5/24/26 12:42, Dmitry Baryshkov wrote:
>>> On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
>>>> From: Demi Marie Obenour <demiobenour@gmail.com>
>>>>
>>>> It's slower than the generic C code and causes problems.
>>>
>>> Which problems?
>>
>> See https://lore.kernel.org/all/20260522024912.GC5937@quark/.
>
> Your commit is still incomplete and other people's opinion is poor
> reason. If you do not know what to write, ask that person to make
> necessary changes.
>
> Not mentioning that removing driver is not even necessary to achieve the
> goal Eric was mentioning and if I understood correctly: you are removing
> even the pieces Eric found useful.
>
>>
>> Also, if there are no systems in which the QCE driver is actually
>> the highest priority, then unless someone adjusts priorities manually
>> it's unused code.
>
> That's not a reason to remove a driver.
>
>
>>
>>> Also in the security world faster and safer are two orthogonal axis with
>>> very limited correlation.
>>
>> If by "safer" you mean protection against physical side-channel
>> attacks, then my understanding is that all operations on secret keys
>> need to be masked. This includes copying and storage.
>>
>> Linux only supports this for protected keys, and even then sometimes
>> uses the kernel's own RNG for key generation. There is no support
>> for using the QCE for protected keys.
>>
>> Linux does support using hardware-wrapped keys with inline crypto
>> engines, which are what are actually used on Android.
>
> Patches are discussed for some time, did you miss that?
>
> Best regards,
> Krzysztof
Thanks for the useful explanation. I'll remove this patch from my
tree and won't resend it.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Krzysztof Kozlowski @ 2026-05-24 20:29 UTC (permalink / raw)
To: Demi Marie Obenour, Dmitry Baryshkov
Cc: Herbert Xu, David S. Miller, Thara Gopinath, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Russell King, linux-kernel, linux-crypto, linux-arm-msm,
Eric Biggers, Ard Biesheuvel, devicetree, linux-arm-kernel
In-Reply-To: <66317f6a-645e-432b-ae11-8f40569d4117@gmail.com>
On 24/05/2026 22:12, Demi Marie Obenour wrote:
> On 5/24/26 12:42, Dmitry Baryshkov wrote:
>> On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
>>> From: Demi Marie Obenour <demiobenour@gmail.com>
>>>
>>> It's slower than the generic C code and causes problems.
>>
>> Which problems?
>
> See https://lore.kernel.org/all/20260522024912.GC5937@quark/.
Your commit is still incomplete and other people's opinion is poor
reason. If you do not know what to write, ask that person to make
necessary changes.
Not mentioning that removing driver is not even necessary to achieve the
goal Eric was mentioning and if I understood correctly: you are removing
even the pieces Eric found useful.
>
> Also, if there are no systems in which the QCE driver is actually
> the highest priority, then unless someone adjusts priorities manually
> it's unused code.
That's not a reason to remove a driver.
>
>> Also in the security world faster and safer are two orthogonal axis with
>> very limited correlation.
>
> If by "safer" you mean protection against physical side-channel
> attacks, then my understanding is that all operations on secret keys
> need to be masked. This includes copying and storage.
>
> Linux only supports this for protected keys, and even then sometimes
> uses the kernel's own RNG for key generation. There is no support
> for using the QCE for protected keys.
>
> Linux does support using hardware-wrapped keys with inline crypto
> engines, which are what are actually used on Android.
Patches are discussed for some time, did you miss that?
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Krzysztof Kozlowski @ 2026-05-24 20:24 UTC (permalink / raw)
To: demiobenour, Herbert Xu, David S. Miller, Thara Gopinath,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Konrad Dybcio, Russell King
Cc: linux-kernel, linux-crypto, linux-arm-msm, Eric Biggers,
Ard Biesheuvel, devicetree, linux-arm-kernel
In-Reply-To: <20260523-delete-qce-v1-1-86105cd7f406@gmail.com>
On 23/05/2026 21:03, Demi Marie Obenour via B4 Relay wrote:
> From: Demi Marie Obenour <demiobenour@gmail.com>
>
> It's slower than the generic C code and causes problems.
That's really vague and incomplete. You need to make your case, provide
arguments, numbers, data. Otherwise it is just trolling.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Demi Marie Obenour @ 2026-05-24 20:12 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Herbert Xu, David S. Miller, Thara Gopinath, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Russell King, linux-kernel, linux-crypto, linux-arm-msm,
Eric Biggers, Ard Biesheuvel, devicetree, linux-arm-kernel
In-Reply-To: <7rgfuvv3hai7g4wt4accbkejtzdt5dnb6mkj6x7ox5sz35q4n2@h7j6rr7extuj>
[-- Attachment #1.1.1: Type: text/plain, Size: 1145 bytes --]
On 5/24/26 12:42, Dmitry Baryshkov wrote:
> On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
>> From: Demi Marie Obenour <demiobenour@gmail.com>
>>
>> It's slower than the generic C code and causes problems.
>
> Which problems?
See https://lore.kernel.org/all/20260522024912.GC5937@quark/.
Also, if there are no systems in which the QCE driver is actually
the highest priority, then unless someone adjusts priorities manually
it's unused code.
> Also in the security world faster and safer are two orthogonal axis with
> very limited correlation.
If by "safer" you mean protection against physical side-channel
attacks, then my understanding is that all operations on secret keys
need to be masked. This includes copying and storage.
Linux only supports this for protected keys, and even then sometimes
uses the kernel's own RNG for key generation. There is no support
for using the QCE for protected keys.
Linux does support using hardware-wrapped keys with inline crypto
engines, which are what are actually used on Android.
--
Sincerely,
Demi Marie Obenour (she/her/hers)
[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 6/6] crypto: eip93: handle request ID exhaustion
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
The driver stores the async request pointer in an IDR and places the ID in
the hardware descriptor. The old allocation used the ring depth as the IDR
limit. It also did not check allocation failure, so request pressure could
encode a negative error value as a descriptor user ID.
Allocate request IDs from the full user ID field range and wait while the
IDR is full. Publish the descriptor only after DMA mappings and ID
allocation have succeeded. Add unwind paths for mappings that are active
when ID allocation fails, and tolerate stale or missing result IDs in the
interrupt handler.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Reported-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Suggested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Tested-by: Aleksander Jan Bajkowski <olek2@wp.pl>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
.../crypto/inside-secure/eip93/eip93-common.c | 48 +++++++++++++++----
.../crypto/inside-secure/eip93/eip93-common.h | 3 ++
.../crypto/inside-secure/eip93/eip93-hash.c | 26 +++++++---
.../crypto/inside-secure/eip93/eip93-main.c | 6 +++
.../crypto/inside-secure/eip93/eip93-main.h | 2 +
5 files changed, 69 insertions(+), 16 deletions(-)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-common.c b/drivers/crypto/inside-secure/eip93/eip93-common.c
index f422c93748c9..88b89d05d510 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-common.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-common.c
@@ -65,6 +65,31 @@ int eip93_parse_ctrl_stat_err(struct eip93_device *eip93, int err)
}
}
+int eip93_alloc_request_id(struct eip93_device *eip93, void *request)
+{
+ int id;
+
+ scoped_guard(spinlock_bh, &eip93->ring->idr_lock)
+ id = idr_alloc(&eip93->ring->crypto_async_idr, request, 0,
+ EIP93_REQUEST_IDR_LIMIT, GFP_ATOMIC);
+
+ return id;
+}
+
+int eip93_alloc_request_id_wait(struct eip93_device *eip93, void *request)
+{
+ int id;
+
+ for (;;) {
+ id = eip93_alloc_request_id(eip93, request);
+ if (id != -ENOSPC)
+ return id;
+
+ usleep_range(EIP93_RING_BUSY_DELAY,
+ EIP93_RING_BUSY_DELAY * 2);
+ }
+}
+
static void *eip93_ring_next_wptr(struct eip93_device *eip93,
struct eip93_desc_ring *ring)
{
@@ -597,15 +622,6 @@ int eip93_send_req(struct crypto_async_request *async,
cdesc.sa_addr = rctx->sa_record_base;
cdesc.arc4_addr = 0;
- scoped_guard(spinlock_bh, &eip93->ring->idr_lock)
- crypto_async_idr = idr_alloc(&eip93->ring->crypto_async_idr, async, 0,
- EIP93_RING_NUM - 1, GFP_ATOMIC);
-
- cdesc.user_id = FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) |
- FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, rctx->desc_flags);
-
- rctx->cdesc = &cdesc;
-
/* map DMA_BIDIRECTIONAL to invalidate cache on destination
* implies __dma_cache_wback_inv
*/
@@ -620,8 +636,22 @@ int eip93_send_req(struct crypto_async_request *async,
goto free_sg_dma;
}
+ crypto_async_idr = eip93_alloc_request_id_wait(eip93, async);
+ if (crypto_async_idr < 0) {
+ err = crypto_async_idr;
+ goto free_src_sg_dma;
+ }
+
+ cdesc.user_id = FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, crypto_async_idr) |
+ FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, rctx->desc_flags);
+
+ rctx->cdesc = &cdesc;
+
return eip93_scatter_combine(eip93, rctx, datalen, split, offsetin);
+free_src_sg_dma:
+ if (src != dst)
+ dma_unmap_sg(eip93->dev, src, rctx->src_nents, DMA_TO_DEVICE);
free_sg_dma:
dma_unmap_sg(eip93->dev, dst, rctx->dst_nents, DMA_BIDIRECTIONAL);
free_sa_state_ctr_dma:
diff --git a/drivers/crypto/inside-secure/eip93/eip93-common.h b/drivers/crypto/inside-secure/eip93/eip93-common.h
index 41c43782eb5c..3898962d0abf 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-common.h
+++ b/drivers/crypto/inside-secure/eip93/eip93-common.h
@@ -17,6 +17,9 @@ void eip93_set_sa_record(struct sa_record *sa_record, const unsigned int keylen,
int eip93_parse_ctrl_stat_err(struct eip93_device *eip93, int err);
+int eip93_alloc_request_id(struct eip93_device *eip93, void *request);
+int eip93_alloc_request_id_wait(struct eip93_device *eip93, void *request);
+
int eip93_hmac_setkey(u32 ctx_flags, const u8 *key, unsigned int keylen,
unsigned int hashlen, u8 *ipad, u8 *opad,
bool skip_ipad);
diff --git a/drivers/crypto/inside-secure/eip93/eip93-hash.c b/drivers/crypto/inside-secure/eip93/eip93-hash.c
index 060e90c5eaa7..512e0e2ce25e 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-hash.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-hash.c
@@ -221,6 +221,7 @@ static int eip93_send_hash_req(struct crypto_async_request *async, u8 *data,
struct eip93_device *eip93 = ctx->eip93;
struct eip93_descriptor cdesc = { };
dma_addr_t src_addr;
+ bool hmac_sa_mapped = false;
int ret;
/* Map block data to DMA */
@@ -258,22 +259,23 @@ static int eip93_send_hash_req(struct crypto_async_request *async, u8 *data,
ret = dma_mapping_error(eip93->dev, rctx->sa_record_hmac_base);
if (ret) {
rctx->sa_record_hmac_base = 0;
- dma_unmap_single(eip93->dev, src_addr, len,
- DMA_TO_DEVICE);
- return ret;
+ goto unmap_src;
}
cdesc.sa_addr = rctx->sa_record_hmac_base;
+ hmac_sa_mapped = true;
}
cdesc.pe_ctrl_stat_word |= EIP93_PE_CTRL_PE_HASH_FINAL;
}
- scoped_guard(spinlock_bh, &eip93->ring->idr_lock)
- crypto_async_idr = idr_alloc(&eip93->ring->crypto_async_idr, async, 0,
- EIP93_RING_NUM - 1, GFP_ATOMIC);
+ crypto_async_idr = eip93_alloc_request_id_wait(eip93, async);
+ if (crypto_async_idr < 0) {
+ ret = crypto_async_idr;
+ goto unmap_hmac_sa;
+ }
- cdesc.user_id |= FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, (u16)crypto_async_idr) |
+ cdesc.user_id |= FIELD_PREP(EIP93_PE_USER_ID_CRYPTO_IDR, crypto_async_idr) |
FIELD_PREP(EIP93_PE_USER_ID_DESC_FLAGS, EIP93_DESC_LAST);
}
@@ -291,6 +293,16 @@ static int eip93_send_hash_req(struct crypto_async_request *async, u8 *data,
*data_dma = src_addr;
return 0;
+
+unmap_hmac_sa:
+ if (hmac_sa_mapped) {
+ dma_unmap_single(eip93->dev, rctx->sa_record_hmac_base,
+ sizeof(rctx->sa_record_hmac), DMA_TO_DEVICE);
+ rctx->sa_record_hmac_base = 0;
+ }
+unmap_src:
+ dma_unmap_single(eip93->dev, src_addr, len, DMA_TO_DEVICE);
+ return ret;
}
static int eip93_hash_init(struct ahash_request *req)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c
index e3bd28cc0c67..0de18a0cbe33 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-main.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-main.c
@@ -257,6 +257,12 @@ static void eip93_handle_result_descriptor(struct eip93_device *eip93)
idr_remove(&eip93->ring->crypto_async_idr, crypto_idr);
}
+ if (!async) {
+ dev_warn_ratelimited(eip93->dev, "missing request id %u\n",
+ crypto_idr);
+ goto get_more;
+ }
+
/* Parse error in ctrl stat word */
err = eip93_parse_ctrl_stat_err(eip93, err);
diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.h b/drivers/crypto/inside-secure/eip93/eip93-main.h
index 990c2401b7ce..5237b75bba62 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-main.h
+++ b/drivers/crypto/inside-secure/eip93/eip93-main.h
@@ -13,11 +13,13 @@
#include <crypto/internal/skcipher.h>
#include <linux/bitfield.h>
#include <linux/interrupt.h>
+#include <linux/limits.h>
#define EIP93_RING_BUSY_DELAY 500
#define EIP93_RING_NUM 512
#define EIP93_RING_BUSY 32
+#define EIP93_REQUEST_IDR_LIMIT (U16_MAX + 1)
#define EIP93_CRA_PRIORITY 1500
#define EIP93_RING_SA_STATE_ADDR(base, idx) ((base) + (idx))
--
2.53.0
^ permalink raw reply related
* [PATCH 5/6] crypto: eip93: order result descriptor reads after PE_READY
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
The result handler polls ownership bits until the packet engine reports the
descriptor as ready. Ensure later descriptor reads observe the DMA writes
that completed before PE_READY became visible.
Use the value already read from the descriptor for error parsing.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Reported-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Suggested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
drivers/crypto/inside-secure/eip93/eip93-main.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c
index 276839e1a515..e3bd28cc0c67 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-main.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-main.c
@@ -224,11 +224,14 @@ static void eip93_handle_result_descriptor(struct eip93_device *eip93)
FIELD_GET(EIP93_PE_LENGTH_HOST_PE_READY, pe_length) !=
EIP93_PE_LENGTH_PE_READY);
- err = rdesc->pe_ctrl_stat_word & (EIP93_PE_CTRL_PE_EXT_ERR_CODE |
- EIP93_PE_CTRL_PE_EXT_ERR |
- EIP93_PE_CTRL_PE_SEQNUM_ERR |
- EIP93_PE_CTRL_PE_PAD_ERR |
- EIP93_PE_CTRL_PE_AUTH_ERR);
+ /* Order descriptor reads after device ownership is returned. */
+ dma_rmb();
+
+ err = pe_ctrl_stat & (EIP93_PE_CTRL_PE_EXT_ERR_CODE |
+ EIP93_PE_CTRL_PE_EXT_ERR |
+ EIP93_PE_CTRL_PE_SEQNUM_ERR |
+ EIP93_PE_CTRL_PE_PAD_ERR |
+ EIP93_PE_CTRL_PE_AUTH_ERR);
desc_flags = FIELD_GET(EIP93_PE_USER_ID_DESC_FLAGS, rdesc->user_id);
crypto_idr = FIELD_GET(EIP93_PE_USER_ID_CRYPTO_IDR, rdesc->user_id);
--
2.53.0
^ permalink raw reply related
* [PATCH 4/6] crypto: eip93: use request-local SA records for cipher requests
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
Cipher and AEAD requests keep mutable direction and copy flags in the SA
record. Updating the tfm-level SA record for decrypt requests can leak
those settings into concurrent requests using the same transform.
Copy the prepared SA record into the request context and apply the
request-specific flags there. Map that request-local record for DMA, then
unmap it on normal completion and validation failures.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Reported-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Suggested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
.../crypto/inside-secure/eip93/eip93-aead.c | 34 +++++++++++++------
.../crypto/inside-secure/eip93/eip93-cipher.c | 34 ++++++++++++-------
.../crypto/inside-secure/eip93/eip93-cipher.h | 3 +-
.../crypto/inside-secure/eip93/eip93-common.c | 9 +++++
4 files changed, 55 insertions(+), 25 deletions(-)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-aead.c b/drivers/crypto/inside-secure/eip93/eip93-aead.c
index 2bbd0af7b0e0..3b2edb012048 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-aead.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-aead.c
@@ -42,12 +42,18 @@ void eip93_aead_handle_result(struct crypto_async_request *async, int err)
static int eip93_aead_send_req(struct crypto_async_request *async)
{
+ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm);
struct aead_request *req = aead_request_cast(async);
struct eip93_cipher_reqctx *rctx = aead_request_ctx(req);
int err;
err = check_valid_request(rctx);
if (err) {
+ if (rctx->sa_record_base) {
+ dma_unmap_single(ctx->eip93->dev, rctx->sa_record_base,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ rctx->sa_record_base = 0;
+ }
aead_request_complete(req, err);
return err;
}
@@ -81,8 +87,6 @@ static void eip93_aead_cra_exit(struct crypto_tfm *tfm)
{
struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
- dma_unmap_single(ctx->eip93->dev, ctx->sa_record_base,
- sizeof(*ctx->sa_record), DMA_TO_DEVICE);
kfree(ctx->sa_record);
}
@@ -191,11 +195,24 @@ static int eip93_aead_crypt(struct aead_request *req)
struct crypto_aead *aead = crypto_aead_reqtfm(req);
int ret;
- ctx->sa_record_base = dma_map_single(ctx->eip93->dev, ctx->sa_record,
- sizeof(*ctx->sa_record), DMA_TO_DEVICE);
- ret = dma_mapping_error(ctx->eip93->dev, ctx->sa_record_base);
- if (ret)
+ memcpy(&rctx->sa_record, ctx->sa_record, sizeof(rctx->sa_record));
+ if (IS_DECRYPT(rctx->flags)) {
+ rctx->sa_record.sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN;
+ rctx->sa_record.sa_cmd1_word &= ~(EIP93_SA_CMD_COPY_PAD |
+ EIP93_SA_CMD_COPY_DIGEST);
+ } else {
+ rctx->sa_record.sa_cmd0_word &= ~EIP93_SA_CMD_DIRECTION_IN;
+ rctx->sa_record.sa_cmd1_word |= EIP93_SA_CMD_COPY_PAD |
+ EIP93_SA_CMD_COPY_DIGEST;
+ }
+
+ rctx->sa_record_base = dma_map_single(ctx->eip93->dev, &rctx->sa_record,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ ret = dma_mapping_error(ctx->eip93->dev, rctx->sa_record_base);
+ if (ret) {
+ rctx->sa_record_base = 0;
return ret;
+ }
rctx->textsize = req->cryptlen;
rctx->blksize = ctx->blksize;
@@ -205,7 +222,6 @@ static int eip93_aead_crypt(struct aead_request *req)
rctx->sg_dst = req->dst;
rctx->ivsize = crypto_aead_ivsize(aead);
rctx->desc_flags = EIP93_DESC_AEAD;
- rctx->sa_record_base = ctx->sa_record_base;
if (IS_DECRYPT(rctx->flags))
rctx->textsize -= rctx->authsize;
@@ -238,10 +254,6 @@ static int eip93_aead_decrypt(struct aead_request *req)
struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct eip93_cipher_reqctx *rctx = aead_request_ctx(req);
- ctx->sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN;
- ctx->sa_record->sa_cmd1_word &= ~(EIP93_SA_CMD_COPY_PAD |
- EIP93_SA_CMD_COPY_DIGEST);
-
rctx->flags = ctx->flags;
rctx->flags |= EIP93_DECRYPT;
if (ctx->set_assoc) {
diff --git a/drivers/crypto/inside-secure/eip93/eip93-cipher.c b/drivers/crypto/inside-secure/eip93/eip93-cipher.c
index 4dd7ab7503e8..66b85781ef93 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-cipher.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-cipher.c
@@ -32,6 +32,7 @@ void eip93_skcipher_handle_result(struct crypto_async_request *async, int err)
static int eip93_skcipher_send_req(struct crypto_async_request *async)
{
+ struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(async->tfm);
struct skcipher_request *req = skcipher_request_cast(async);
struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req);
int err;
@@ -39,6 +40,11 @@ static int eip93_skcipher_send_req(struct crypto_async_request *async)
err = check_valid_request(rctx);
if (err) {
+ if (rctx->sa_record_base) {
+ dma_unmap_single(ctx->eip93->dev, rctx->sa_record_base,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ rctx->sa_record_base = 0;
+ }
skcipher_request_complete(req, err);
return err;
}
@@ -72,8 +78,6 @@ static void eip93_skcipher_cra_exit(struct crypto_tfm *tfm)
{
struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(tfm);
- dma_unmap_single(ctx->eip93->dev, ctx->sa_record_base,
- sizeof(*ctx->sa_record), DMA_TO_DEVICE);
kfree(ctx->sa_record);
}
@@ -133,7 +137,7 @@ static int eip93_skcipher_setkey(struct crypto_skcipher *ctfm, const u8 *key,
return 0;
}
-static int eip93_skcipher_crypt(struct skcipher_request *req)
+static int eip93_skcipher_crypt(struct skcipher_request *req, bool encrypt)
{
struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req);
struct crypto_async_request *async = &req->base;
@@ -153,11 +157,19 @@ static int eip93_skcipher_crypt(struct skcipher_request *req)
crypto_skcipher_blocksize(skcipher)))
return -EINVAL;
- ctx->sa_record_base = dma_map_single(ctx->eip93->dev, ctx->sa_record,
- sizeof(*ctx->sa_record), DMA_TO_DEVICE);
- ret = dma_mapping_error(ctx->eip93->dev, ctx->sa_record_base);
- if (ret)
+ memcpy(&rctx->sa_record, ctx->sa_record, sizeof(rctx->sa_record));
+ if (encrypt)
+ rctx->sa_record.sa_cmd0_word &= ~EIP93_SA_CMD_DIRECTION_IN;
+ else
+ rctx->sa_record.sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN;
+
+ rctx->sa_record_base = dma_map_single(ctx->eip93->dev, &rctx->sa_record,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ ret = dma_mapping_error(ctx->eip93->dev, rctx->sa_record_base);
+ if (ret) {
+ rctx->sa_record_base = 0;
return ret;
+ }
rctx->assoclen = 0;
rctx->textsize = req->cryptlen;
@@ -167,7 +179,6 @@ static int eip93_skcipher_crypt(struct skcipher_request *req)
rctx->ivsize = crypto_skcipher_ivsize(skcipher);
rctx->blksize = ctx->blksize;
rctx->desc_flags = EIP93_DESC_SKCIPHER;
- rctx->sa_record_base = ctx->sa_record_base;
return eip93_skcipher_send_req(async);
}
@@ -181,22 +192,19 @@ static int eip93_skcipher_encrypt(struct skcipher_request *req)
rctx->flags = tmpl->flags;
rctx->flags |= EIP93_ENCRYPT;
- return eip93_skcipher_crypt(req);
+ return eip93_skcipher_crypt(req, true);
}
static int eip93_skcipher_decrypt(struct skcipher_request *req)
{
- struct eip93_crypto_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct eip93_cipher_reqctx *rctx = skcipher_request_ctx(req);
struct eip93_alg_template *tmpl = container_of(req->base.tfm->__crt_alg,
struct eip93_alg_template, alg.skcipher.base);
- ctx->sa_record->sa_cmd0_word |= EIP93_SA_CMD_DIRECTION_IN;
-
rctx->flags = tmpl->flags;
rctx->flags |= EIP93_DECRYPT;
- return eip93_skcipher_crypt(req);
+ return eip93_skcipher_crypt(req, false);
}
/* Available algorithms in this module */
diff --git a/drivers/crypto/inside-secure/eip93/eip93-cipher.h b/drivers/crypto/inside-secure/eip93/eip93-cipher.h
index 47e4e84ff14e..e9612696c388 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-cipher.h
+++ b/drivers/crypto/inside-secure/eip93/eip93-cipher.h
@@ -9,6 +9,7 @@
#define _EIP93_CIPHER_H_
#include "eip93-main.h"
+#include "eip93-regs.h"
struct eip93_crypto_ctx {
struct eip93_device *eip93;
@@ -16,7 +17,6 @@ struct eip93_crypto_ctx {
struct sa_record *sa_record;
u32 sa_nonce;
int blksize;
- dma_addr_t sa_record_base;
/* AEAD specific */
unsigned int authsize;
unsigned int assoclen;
@@ -32,6 +32,7 @@ struct eip93_cipher_reqctx {
unsigned int textsize;
unsigned int assoclen;
unsigned int authsize;
+ struct sa_record sa_record __aligned(CRYPTO_DMA_ALIGN);
dma_addr_t sa_record_base;
struct sa_state *sa_state;
dma_addr_t sa_state_base;
diff --git a/drivers/crypto/inside-secure/eip93/eip93-common.c b/drivers/crypto/inside-secure/eip93/eip93-common.c
index ed46730c36bc..f422c93748c9 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-common.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-common.c
@@ -637,6 +637,10 @@ int eip93_send_req(struct crypto_async_request *async,
DMA_TO_DEVICE);
free_sa_state:
kfree(rctx->sa_state);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ rctx->sa_record_base = 0;
return err;
}
@@ -693,6 +697,11 @@ void eip93_handle_result(struct eip93_device *eip93, struct eip93_cipher_reqctx
sizeof(*rctx->sa_state_ctr),
DMA_FROM_DEVICE);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ rctx->sa_record_base = 0;
+
if (rctx->sa_state)
dma_unmap_single(eip93->dev, rctx->sa_state_base,
sizeof(*rctx->sa_state),
--
2.53.0
^ permalink raw reply related
* [PATCH 3/6] crypto: eip93: reject HMAC requests before setkey
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
HMAC requests need the precomputed ipad/opad state installed by setkey().
Using an HMAC tfm before setkey() initializes the request with an all-zero
ipad and produces invalid hardware input.
Reject those requests during hash init so the failure is explicit.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Originally-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
drivers/crypto/inside-secure/eip93/eip93-hash.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-hash.c b/drivers/crypto/inside-secure/eip93/eip93-hash.c
index 63bb6c4670cb..060e90c5eaa7 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-hash.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-hash.c
@@ -300,6 +300,9 @@ static int eip93_hash_init(struct ahash_request *req)
struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash);
struct sa_state *sa_state = &rctx->sa_state;
+ if (IS_HMAC(ctx->flags) && !memchr_inv(ctx->ipad, 0, SHA256_BLOCK_SIZE))
+ return -EINVAL;
+
memset(sa_state->state_byte_cnt, 0, sizeof(u32) * 2);
eip93_hash_init_sa_state_digest(ctx->flags & EIP93_HASH_MASK,
sa_state->state_i_digest);
--
2.53.0
^ permalink raw reply related
* [PATCH 2/6] crypto: eip93: guard DMA cleanup on uninitialized mappings
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
Several error paths can reach cleanup before all DMA addresses have been
initialized or mapped. Initialize request DMA handles and check them before
cleanup so the driver does not unmap zero or stale addresses.
If mapping the temporary HMAC SA record fails, also release the block data
DMA mapping that was already active.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Reported-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Originally-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Suggested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
.../crypto/inside-secure/eip93/eip93-common.c | 8 ++-
.../crypto/inside-secure/eip93/eip93-hash.c | 54 ++++++++++++-------
2 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-common.c b/drivers/crypto/inside-secure/eip93/eip93-common.c
index 4c163d7281b3..ed46730c36bc 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-common.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-common.c
@@ -527,6 +527,8 @@ int eip93_send_req(struct crypto_async_request *async,
rctx->sa_state_ctr = NULL;
rctx->sa_state = NULL;
+ rctx->sa_state_ctr_base = 0;
+ rctx->sa_state_base = 0;
if (IS_ECB(flags))
goto skip_iv;
@@ -534,8 +536,10 @@ int eip93_send_req(struct crypto_async_request *async,
memcpy(iv, reqiv, rctx->ivsize);
rctx->sa_state = kzalloc(sizeof(*rctx->sa_state), GFP_KERNEL);
- if (!rctx->sa_state)
- return -ENOMEM;
+ if (!rctx->sa_state) {
+ err = -ENOMEM;
+ goto free_sa_state;
+ }
sa_state = rctx->sa_state;
diff --git a/drivers/crypto/inside-secure/eip93/eip93-hash.c b/drivers/crypto/inside-secure/eip93/eip93-hash.c
index 84d3ff2d3836..63bb6c4670cb 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-hash.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-hash.c
@@ -34,7 +34,7 @@ static void eip93_hash_free_data_blocks(struct ahash_request *req)
if (!list_empty(&rctx->blocks))
INIT_LIST_HEAD(&rctx->blocks);
- if (rctx->finalize)
+ if (rctx->finalize && rctx->data_dma)
dma_unmap_single(eip93->dev, rctx->data_dma,
rctx->data_used,
DMA_TO_DEVICE);
@@ -47,12 +47,13 @@ static void eip93_hash_free_sa_record(struct ahash_request *req)
struct eip93_hash_ctx *ctx = crypto_ahash_ctx(ahash);
struct eip93_device *eip93 = ctx->eip93;
- if (IS_HMAC(ctx->flags))
+ if (IS_HMAC(ctx->flags) && rctx->sa_record_hmac_base)
dma_unmap_single(eip93->dev, rctx->sa_record_hmac_base,
sizeof(rctx->sa_record_hmac), DMA_TO_DEVICE);
- dma_unmap_single(eip93->dev, rctx->sa_record_base,
- sizeof(rctx->sa_record), DMA_TO_DEVICE);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(rctx->sa_record), DMA_TO_DEVICE);
}
void eip93_hash_handle_result(struct crypto_async_request *async, int err)
@@ -66,8 +67,9 @@ void eip93_hash_handle_result(struct crypto_async_request *async, int err)
struct eip93_device *eip93 = ctx->eip93;
int i;
- dma_unmap_single(eip93->dev, rctx->sa_state_base,
- sizeof(*sa_state), DMA_FROM_DEVICE);
+ if (rctx->sa_state_base)
+ dma_unmap_single(eip93->dev, rctx->sa_state_base,
+ sizeof(*sa_state), DMA_FROM_DEVICE);
/*
* With partial_hash assume SHA256_DIGEST_SIZE buffer is passed.
@@ -200,6 +202,10 @@ static void __eip93_hash_init(struct ahash_request *req)
rctx->len = 0;
rctx->data_used = 0;
+ rctx->sa_record_base = 0;
+ rctx->sa_state_base = 0;
+ rctx->sa_record_hmac_base = 0;
+ rctx->data_dma = 0;
rctx->partial_hash = false;
rctx->finalize = false;
INIT_LIST_HEAD(&rctx->blocks);
@@ -250,8 +256,12 @@ static int eip93_send_hash_req(struct crypto_async_request *async, u8 *data,
sizeof(*sa_record_hmac),
DMA_TO_DEVICE);
ret = dma_mapping_error(eip93->dev, rctx->sa_record_hmac_base);
- if (ret)
+ if (ret) {
+ rctx->sa_record_hmac_base = 0;
+ dma_unmap_single(eip93->dev, src_addr, len,
+ DMA_TO_DEVICE);
return ret;
+ }
cdesc.sa_addr = rctx->sa_record_hmac_base;
}
@@ -420,12 +430,14 @@ static int eip93_hash_update(struct ahash_request *req)
return ret;
free_sa_record:
- dma_unmap_single(eip93->dev, rctx->sa_record_base,
- sizeof(*sa_record), DMA_TO_DEVICE);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(*sa_record), DMA_TO_DEVICE);
free_sa_state:
- dma_unmap_single(eip93->dev, rctx->sa_state_base,
- sizeof(*sa_state), DMA_TO_DEVICE);
+ if (rctx->sa_state_base)
+ dma_unmap_single(eip93->dev, rctx->sa_state_base,
+ sizeof(*sa_state), DMA_TO_DEVICE);
return ret;
}
@@ -501,12 +513,14 @@ static int __eip93_hash_final(struct ahash_request *req, bool map_dma)
free_blocks:
eip93_hash_free_data_blocks(req);
- dma_unmap_single(eip93->dev, rctx->sa_record_base,
- sizeof(*sa_record), DMA_TO_DEVICE);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(*sa_record), DMA_TO_DEVICE);
free_sa_state:
- dma_unmap_single(eip93->dev, rctx->sa_state_base,
- sizeof(*sa_state), DMA_TO_DEVICE);
+ if (rctx->sa_state_base)
+ dma_unmap_single(eip93->dev, rctx->sa_state_base,
+ sizeof(*sa_state), DMA_TO_DEVICE);
return ret;
}
@@ -549,11 +563,13 @@ static int eip93_hash_finup(struct ahash_request *req)
return __eip93_hash_final(req, false);
free_sa_record:
- dma_unmap_single(eip93->dev, rctx->sa_record_base,
- sizeof(*sa_record), DMA_TO_DEVICE);
+ if (rctx->sa_record_base)
+ dma_unmap_single(eip93->dev, rctx->sa_record_base,
+ sizeof(*sa_record), DMA_TO_DEVICE);
free_sa_state:
- dma_unmap_single(eip93->dev, rctx->sa_state_base,
- sizeof(*sa_state), DMA_TO_DEVICE);
+ if (rctx->sa_state_base)
+ dma_unmap_single(eip93->dev, rctx->sa_state_base,
+ sizeof(*sa_state), DMA_TO_DEVICE);
return ret;
}
--
2.53.0
^ permalink raw reply related
* [PATCH 1/6] crypto: eip93: return IRQ request errors from probe
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
In-Reply-To: <20260524194528.3666383-1-hurryman2212@gmail.com>
devm_request_threaded_irq() can fail, but eip93_crypto_probe()
continues as if the interrupt handler was installed. Return the error
immediately so the driver does not register algorithms for a device that
cannot signal completions.
Fixes: 9739f5f93b78 ("crypto: eip93 - Add Inside Secure SafeXcel EIP-93 crypto engine support")
Originally-by: Mieczyslaw Nalewaj <namiltd@yahoo.com>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Jihong Min <hurryman2212@gmail.com>
---
drivers/crypto/inside-secure/eip93/eip93-main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/crypto/inside-secure/eip93/eip93-main.c b/drivers/crypto/inside-secure/eip93/eip93-main.c
index 7dccfdeb7b11..276839e1a515 100644
--- a/drivers/crypto/inside-secure/eip93/eip93-main.c
+++ b/drivers/crypto/inside-secure/eip93/eip93-main.c
@@ -433,6 +433,8 @@ static int eip93_crypto_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(eip93->dev, eip93->irq, eip93_irq_handler,
NULL, IRQF_ONESHOT,
dev_name(eip93->dev), eip93);
+ if (ret)
+ return ret;
eip93->ring = devm_kcalloc(eip93->dev, 1, sizeof(*eip93->ring), GFP_KERNEL);
if (!eip93->ring)
--
2.53.0
^ permalink raw reply related
* [PATCH 0/6] crypto: eip93: fix request lifetime and completion handling
From: Jihong Min @ 2026-05-24 19:45 UTC (permalink / raw)
To: Herbert Xu, linux-crypto
Cc: Christian Marangi, Antoine Tenart, David S . Miller,
Richard van Schagen, linux-kernel, Benjamin Larsson,
Mieczyslaw Nalewaj, Aleksander Jan Bajkowski, Jihong Min
This series collects EIP-93 fixes which have been carried out-of-tree for a
while but have not reached upstream yet. The patches came from work by
multiple authors; I rebased the relevant parts onto current crypto.git,
split them by bug, dropped pieces that are already upstream, and adjusted the
remaining changes for the current driver.
Some of the original patch sketches were initially written with Claude Opus
4.7. The final review, split, upstream rework, and fixes were done with
assistance from OpenAI Codex GPT-5.5. The submitted commits carry the
corresponding provenance trailers where the original patch author or reporter
is known.
This series is intended as a prerequisite for the EIP-93 IPsec ESP support
series. The currently posted version of that series is broken because it
contains some overlapping fixes which are now split out here:
https://lore.kernel.org/netdev/20260523121522.3023992-1-hurryman2212@gmail.com/
I plan to resend the IPsec ESP support series after this fix series is
resolved.
Tested on a Lumen W1700K2 wireless AP running my Linux 6.18 based OpenWrt
build, after verifying that the resulting driver changes match the
corresponding OpenWrt patch diffs, modulo upstream context differences.
Jihong Min (6):
crypto: eip93: return IRQ request errors from probe
crypto: eip93: guard DMA cleanup on uninitialized mappings
crypto: eip93: reject HMAC requests before setkey
crypto: eip93: use request-local SA records for cipher requests
crypto: eip93: order result descriptor reads after PE_READY
crypto: eip93: handle request ID exhaustion
.../crypto/inside-secure/eip93/eip93-aead.c | 34 +++++---
.../crypto/inside-secure/eip93/eip93-cipher.c | 34 +++++---
.../crypto/inside-secure/eip93/eip93-cipher.h | 3 +-
.../crypto/inside-secure/eip93/eip93-common.c | 65 ++++++++++++---
.../crypto/inside-secure/eip93/eip93-common.h | 3 +
.../crypto/inside-secure/eip93/eip93-hash.c | 79 +++++++++++++------
.../crypto/inside-secure/eip93/eip93-main.c | 21 +++--
.../crypto/inside-secure/eip93/eip93-main.h | 2 +
8 files changed, 176 insertions(+), 65 deletions(-)
base-commit: 49e05bb00f2e8168695f7af4d694c39e1423e8a2
--
2.53.0
^ permalink raw reply
* Re: [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Dmitry Baryshkov @ 2026-05-24 16:42 UTC (permalink / raw)
To: demiobenour
Cc: Herbert Xu, David S. Miller, Thara Gopinath, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Russell King, linux-kernel, linux-crypto, linux-arm-msm,
Eric Biggers, Ard Biesheuvel, devicetree, linux-arm-kernel
In-Reply-To: <20260523-delete-qce-v1-1-86105cd7f406@gmail.com>
On Sat, May 23, 2026 at 03:03:56PM -0400, Demi Marie Obenour via B4 Relay wrote:
> From: Demi Marie Obenour <demiobenour@gmail.com>
>
> It's slower than the generic C code and causes problems.
Which problems?
Also in the security world faster and safer are two orthogonal axis with
very limited correlation.
>
> Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
> ---
> MAINTAINERS | 8 -
> arch/arm/configs/multi_v7_defconfig | 1 -
> arch/arm64/configs/defconfig | 1 -
> drivers/crypto/Kconfig | 111 -----
> drivers/crypto/Makefile | 1 -
> drivers/crypto/qce/Makefile | 9 -
> drivers/crypto/qce/aead.c | 841 ------------------------------------
> drivers/crypto/qce/aead.h | 56 ---
> drivers/crypto/qce/cipher.h | 56 ---
> drivers/crypto/qce/common.c | 595 -------------------------
> drivers/crypto/qce/common.h | 104 -----
> drivers/crypto/qce/core.c | 271 ------------
> drivers/crypto/qce/core.h | 64 ---
> drivers/crypto/qce/dma.c | 135 ------
> drivers/crypto/qce/dma.h | 47 --
> drivers/crypto/qce/regs-v5.h | 326 --------------
> drivers/crypto/qce/sha.c | 545 -----------------------
> drivers/crypto/qce/sha.h | 72 ---
> drivers/crypto/qce/skcipher.c | 529 -----------------------
> 19 files changed, 3772 deletions(-)
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH] crypto: nx: fix nx_crypto_ctx_exit argument
From: Breno Leitao @ 2026-05-24 7:10 UTC (permalink / raw)
To: Sam James
Cc: Nayna Jain, Paulo Flabiano Smorigo, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
Herbert Xu, David S. Miller, Eric Biggers, Ard Biesheuvel,
Eric Biggers, Calvin Buckley, Brad Spengler, linux-crypto,
linuxppc-dev, linux-kernel
In-Reply-To: <a3e89c1e8342ffa415b0d29725a0571a4f355d34.1779472902.git.sam@gentoo.org>
On Fri, May 22, 2026 at 07:01:42PM +0000, Sam James wrote:
> nx_crypto_ctx_shash_exit calls nx_crypto_ctx_exit with crypto_shash_ctx(...)
> but crypto_shash_ctx gives a nx_crypto_ctx *, not a crypto_tfm *.
>
> Fix the type in nx_crypto_ctx_exit and drop the bogus crypto_tfm_ctx
> call.
>
> This fixes the following oops:
>
> BUG: Unable to handle kernel data access at 0xc0403effffffffc8
> Faulting instruction address: 0xc000000000396cb4
> Oops: Kernel access of bad area, sig: 11 [#15]
> Call Trace:
> nx_crypto_ctx_shash_exit+0x24/0x60
> crypto_shash_exit_tfm+0x28/0x40
> crypto_destroy_tfm+0x98/0x140
> crypto_exit_ahash_using_shash+0x20/0x40
> crypto_destroy_tfm+0x98/0x140
> hash_release+0x1c/0x30
> alg_sock_destruct+0x38/0x60
> __sk_destruct+0x48/0x2b0
> af_alg_release+0x58/0xb0
> __sock_release+0x68/0x150
> sock_close+0x20/0x40
> __fput+0x110/0x3a0
> sys_close+0x48/0xa0
> system_call_exception+0x140/0x2d0
> system_call_common+0xf4/0x258
>
> .. which came from hardlink(1) opportunistically using AF_ALG.
>
> The same problem exists with nx_crypto_ctx_skcipher_exit getting a context
> it wasn't expecting, but apparently nobody hit that for years.
>
> Cc: Eric Biggers <ebiggers@kernel.org>
> Fixes: bfd9efddf990 ("crypto: nx - convert AES-ECB to skcipher API")
> Fixes: 9420e628e7d8 ("crypto: nx - Use API partial block handling")
> Reported-by: Calvin Buckley <calvin@cmpct.info>
> Tested-by: Calvin Buckley <calvin@cmpct.info>
> Suggested-by: Brad Spengler <brad.spengler@opensrcsec.com>
> Signed-off-by: Sam James <sam@gentoo.org>
Acked-by: Breno Leitao <leitao@debian.org>
^ permalink raw reply
* Re: [PATCH v8 0/3]
From: Jarkko Sakkinen @ 2026-05-24 5:20 UTC (permalink / raw)
To: keyrings
Cc: David Howells, linux-crypto, linux-integrity, David Woodhouse,
James Bottomley, Stefan Berger, Herbert Xu, Mimi Zohar,
Paul Moore, James Morris, Serge E. Hallyn,
open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <20260524051519.3708075-1-jarkko@kernel.org>
On Sun, May 24, 2026 at 08:15:11AM +0300, Jarkko Sakkinen wrote:
> This series introduces key type for operating with asymmetric keys using
> a TPM2 chip.
>
> Change Log
> ==========
>
> v8:
> - Reset patch change logs given the overhaul of the code and patches.
> - Have only single new subkey type.
> - Make key type only use TPM operations.
> - Use TPM2_Sign for both ECC and RSA keys.
> - Align key descriptions with other key types.
>
> Previous versions
> =================
>
> * v7: https://lore.kernel.org/linux-integrity/20240528210823.28798-1-jarkko@kernel.org/
> * v6: https://lore.kernel.org/linux-integrity/20240528035136.11464-1-jarkko@kernel.org/
> * v5: https://lore.kernel.org/linux-integrity/20240523212515.4875-1-jarkko@kernel.org/
> * v4: https://lore.kernel.org/linux-integrity/20240522005252.17841-1-jarkko@kernel.org/
> * v3: https://lore.kernel.org/linux-integrity/20240521152659.26438-1-jarkko@kernel.org/
> * v2: https://lore.kernel.org/linux-integrity/336755.1716327854@warthog.procyon.org.uk/
> * v1: https://lore.kernel.org/linux-integrity/20240520184727.22038-1-jarkko@kernel.org/
> * Derived from https://lore.kernel.org/all/20200518172704.29608-1-prestwoj@gmail.com/
>
>
> Jarkko Sakkinen (3):
> lib/asn1_encoder: Add asn1_encode_integer_bytes()
> crypto: Migrate TPMKey ASN.1 objects from trusted-keys
> keys: asymmetric: tpm2_asymmetric
>
> crypto/Kconfig | 7 +
> crypto/Makefile | 6 +
> crypto/asymmetric_keys/Kconfig | 17 +
> crypto/asymmetric_keys/Makefile | 1 +
> crypto/asymmetric_keys/tpm2_asymmetric.c | 1096 +++++++++++++++++++++
> crypto/tpm2_key.asn1 | 11 +
> crypto/tpm2_key.c | 150 +++
> include/crypto/tpm2_key.h | 46 +
> include/linux/asn1_encoder.h | 3 +
> include/linux/tpm.h | 10 +
> lib/asn1_encoder.c | 62 ++
> security/keys/trusted-keys/Kconfig | 2 +-
> security/keys/trusted-keys/Makefile | 2 -
> security/keys/trusted-keys/tpm2key.asn1 | 11 -
> security/keys/trusted-keys/trusted_tpm2.c | 119 +--
> 15 files changed, 1421 insertions(+), 122 deletions(-)
> create mode 100644 crypto/asymmetric_keys/tpm2_asymmetric.c
> create mode 100644 crypto/tpm2_key.asn1
> create mode 100644 crypto/tpm2_key.c
> create mode 100644 include/crypto/tpm2_key.h
> delete mode 100644 security/keys/trusted-keys/tpm2key.asn1
>
> --
> 2.47.3
>
There's some initial test code for this too:
https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd-test.git/tree/overlay/usr/local/bin/tpmdd_tpm2_asymmetric.sh?h=main
Ugh, that's one hell of an url...
BR, Jarkko
^ permalink raw reply
* [PATCH v8 3/3] keys: asymmetric: tpm2_asymmetric
From: Jarkko Sakkinen @ 2026-05-24 5:15 UTC (permalink / raw)
To: keyrings
Cc: David Howells, linux-crypto, linux-integrity, David Woodhouse,
James Bottomley, Stefan Berger, Herbert Xu, Jarkko Sakkinen,
James Prestwood, Lukas Wunner, Ignat Korchagin, David S. Miller,
Peter Huewe, Jason Gunthorpe, James Bottomley, Mimi Zohar,
Paul Moore, James Morris, Serge E. Hallyn, open list,
open list:SECURITY SUBSYSTEM
In-Reply-To: <20260524051519.3708075-1-jarkko@kernel.org>
tpm2_asymmetric is a key type for external keys generated outside the TPM
chip but later imported to the chip's key hierarchy as leaf keys.
The key type supports ECC-NIST-P256/384/521 and RSA keys and provides
signing and verification operations for each. In addition, for RSA
encryption and decryption operations are supported.
Co-developed-by: James Prestwood <prestwoj@gmail.com>
Signed-off-by: James Prestwood <prestwoj@gmail.com>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
crypto/asymmetric_keys/Kconfig | 17 +
crypto/asymmetric_keys/Makefile | 1 +
crypto/asymmetric_keys/tpm2_asymmetric.c | 1096 ++++++++++++++++++++++
include/linux/tpm.h | 10 +
4 files changed, 1124 insertions(+)
create mode 100644 crypto/asymmetric_keys/tpm2_asymmetric.c
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index e50bd9b3e27b..a93e13d5768f 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -15,6 +15,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select MPILIB
select CRYPTO_HASH_INFO
select CRYPTO_AKCIPHER
+ select CRYPTO_RSA
select CRYPTO_SIG
select CRYPTO_HASH
help
@@ -23,6 +24,22 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
appropriate hash algorithms (such as SHA-1) must be available.
ENOPKG will be reported if the requisite algorithm is unavailable.
+config ASYMMETRIC_TPM2_KEY_SUBTYPE
+ tristate "Asymmetric TPM2 crypto algorithm subtype"
+ depends on TCG_TPM
+ select CRYPTO_SHA256
+ select CRYPTO_HASH_INFO
+ select CRYPTO_TPM2_KEY
+ select ASN1
+ select ASN1_ENCODER
+ help
+ This option provides support for asymmetric TPM2 key type handling.
+ Asymmetric operations such as sign and verify are delegated to the
+ TPM, and bound to the kernel crypto subsystem. Both RSA and ECDSA
+ keys are supported.
+
+ ENOPKG will be reported if the requisite algorithm is unavailable.
+
config X509_CERTIFICATE_PARSER
tristate "X.509 certificate parser"
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile
index bc65d3b98dcb..c83b40d021ac 100644
--- a/crypto/asymmetric_keys/Makefile
+++ b/crypto/asymmetric_keys/Makefile
@@ -11,6 +11,7 @@ asymmetric_keys-y := \
signature.o
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
+obj-$(CONFIG_ASYMMETRIC_TPM2_KEY_SUBTYPE) += tpm2_asymmetric.o
#
# X.509 Certificate handling
diff --git a/crypto/asymmetric_keys/tpm2_asymmetric.c b/crypto/asymmetric_keys/tpm2_asymmetric.c
new file mode 100644
index 000000000000..f6598e6fd283
--- /dev/null
+++ b/crypto/asymmetric_keys/tpm2_asymmetric.c
@@ -0,0 +1,1096 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * An asymmetric TPM2 key subtype.
+ */
+
+#include <crypto/hash_info.h>
+#include <crypto/internal/ecc.h>
+#include <crypto/public_key.h>
+#include <crypto/tpm2_key.h>
+#include <keys/asymmetric-parser.h>
+#include <keys/asymmetric-subtype.h>
+#include <linux/asn1_encoder.h>
+#include <linux/keyctl.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tpm.h>
+#include <linux/unaligned.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "tpm2_asymmetric: "fmt
+
+/* TPM2 Structures 12.2.3.5: TPMS_RSA_PARMS */
+struct tpm2_asymmetric_rsa_parms {
+ __be16 symmetric;
+ __be16 scheme;
+ __be16 key_bits;
+ __be32 exponent;
+ __be16 modulus_size;
+} __packed;
+
+/* TPM2 Structures 12.2.3.6: TPMS_ECC_PARMS */
+struct tpm2_asymmetric_ecc_parms {
+ __be16 symmetric;
+ __be16 scheme;
+ __be16 ecc;
+ __be16 kdf;
+};
+
+static const void *tpm2_asymmetric_parms(const struct tpm2_key *key)
+{
+ return &key->data[key->priv_len + 2 + sizeof(*key->desc)];
+}
+
+static u16 tpm2_asymmetric_rsa_mod_size(const struct tpm2_key *key)
+{
+ const struct tpm2_asymmetric_rsa_parms *p = tpm2_asymmetric_parms(key);
+
+ return be16_to_cpu(p->modulus_size);
+}
+
+static const u8 *tpm2_asymmetric_ecc_x(const struct tpm2_key *key)
+{
+ return tpm2_asymmetric_parms(key) + sizeof(struct tpm2_asymmetric_ecc_parms);
+}
+
+static const u8 *tpm2_asymmetric_ecc_y(const struct tpm2_key *key)
+{
+ const u8 *x = tpm2_asymmetric_ecc_x(key);
+ u16 x_size = get_unaligned_be16(&x[0]);
+
+ return &x[2 + x_size];
+}
+
+static unsigned int tpm2_asymmetric_ecc_key_bits(u16 ecc)
+{
+ switch (ecc) {
+ case TPM2_ECC_NIST_P256:
+ return 256;
+ case TPM2_ECC_NIST_P384:
+ return 384;
+ case TPM2_ECC_NIST_P521:
+ return 521;
+ default:
+ return 0;
+ }
+}
+
+static int tpm2_asymmetric_hash_lookup(const char *hash_algo,
+ int *hash_id, int *tpm_hash)
+{
+ int id, alg;
+
+ if (!hash_algo)
+ return -EINVAL;
+
+ id = match_string(hash_algo_name, HASH_ALGO__LAST, hash_algo);
+ if (id < 0)
+ return -ENOPKG;
+
+ alg = tpm2_find_hash_alg(id);
+ if (alg < 0)
+ return -ENOPKG;
+
+ if (hash_id)
+ *hash_id = id;
+
+ if (tpm_hash)
+ *tpm_hash = alg;
+
+ return 0;
+}
+
+static int tpm2_asymmetric_signature_scheme(const struct tpm2_key *key,
+ const char *encoding,
+ const char *hash_algo,
+ u16 *scheme,
+ int *tpm_hash)
+{
+ if (!encoding)
+ return -ENOPKG;
+
+ switch (tpm2_key_type(key)) {
+ case TPM_ALG_RSA:
+ if (strcmp(encoding, "pkcs1") != 0)
+ return -ENOPKG;
+ *scheme = TPM_ALG_RSASSA;
+ break;
+ case TPM_ALG_ECC:
+ if (strcmp(encoding, "x962") != 0)
+ return -ENOPKG;
+ *scheme = TPM_ALG_ECDSA;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return tpm2_asymmetric_hash_lookup(hash_algo, NULL, tpm_hash);
+}
+
+/*
+ * Load a TPM2 key blob into the TPM.
+ *
+ * On success, @buf is initialized and the authorization session is kept open.
+ * On failure, @buf is destroyed and the authorization session is closed.
+ */
+static int tpm2_asymmetric_load(struct tpm_chip *chip, struct tpm2_key *key,
+ struct tpm_buf *buf, u32 *handle_out)
+{
+ int ret;
+
+ ret = tpm2_start_auth_session(chip);
+ if (ret)
+ return ret;
+
+ ret = tpm_buf_init(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ if (ret < 0)
+ goto err_auth;
+
+ ret = tpm_buf_append_name(chip, buf, key->parent, NULL);
+ if (ret)
+ goto err_buf;
+ tpm_buf_append_hmac_session(chip, buf, TPM2_SA_CONTINUE_SESSION |
+ TPM2_SA_ENCRYPT, NULL, 0);
+ tpm_buf_append(buf, &key->data[0], key->priv_len + key->pub_len);
+ if (buf->flags & TPM_BUF_OVERFLOW) {
+ ret = -E2BIG;
+ goto err_buf;
+ }
+ ret = tpm_buf_fill_hmac_session(chip, buf);
+ if (ret)
+ goto err_buf;
+ ret = tpm_transmit_cmd(chip, buf, 4, "TPM2_CC_LOAD");
+ ret = tpm_buf_check_hmac_response(chip, buf, ret);
+ if (ret) {
+ ret = -EIO;
+ goto err_buf;
+ }
+
+ *handle_out = be32_to_cpup((__be32 *)&buf->data[TPM_HEADER_SIZE]);
+ return 0;
+
+err_buf:
+ tpm_buf_destroy(buf);
+
+err_auth:
+ tpm2_end_auth_session(chip);
+ return ret;
+}
+
+static void tpm2_asymmetric_key_destroy(void *payload0, void *payload3)
+{
+ kfree(payload0);
+}
+
+/*
+ * Encrypt using TPM2_RSA_Encrypt with RSAES (PKCS#1 v1.5) scheme.
+ */
+static int tpm2_asymmetric_rsa_encrypt(struct tpm_chip *chip,
+ struct tpm2_key *key,
+ struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ u32 key_handle = 0;
+ struct tpm_buf buf;
+ u16 ciphertext_len;
+ u16 scheme;
+ u8 *pos;
+ int ret;
+
+ if (!params->encoding)
+ return -EINVAL;
+
+ if (strcmp(params->encoding, "pkcs1") == 0)
+ scheme = TPM_ALG_RSAES;
+ else if (strcmp(params->encoding, "raw") == 0)
+ scheme = TPM_ALG_NULL;
+ else
+ return -ENOPKG;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ return ret;
+
+ ret = tpm2_asymmetric_load(chip, key, &buf, &key_handle);
+ if (ret)
+ goto err_ops;
+
+ tpm2_end_auth_session(chip);
+ tpm_buf_destroy(&buf);
+
+ ret = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_RSA_ENCRYPT);
+ if (ret)
+ goto err_key;
+
+ tpm_buf_append_u32(&buf, key_handle);
+
+ tpm_buf_append_u16(&buf, params->in_len);
+ tpm_buf_append(&buf, in, params->in_len);
+
+ tpm_buf_append_u16(&buf, scheme);
+
+ tpm_buf_append_u16(&buf, 0);
+
+ ret = tpm_transmit_cmd(chip, &buf, 4, "TPM2_RSA_Encrypt");
+ if (ret) {
+ ret = -EIO;
+ goto err_buf;
+ }
+
+ pos = buf.data + TPM_HEADER_SIZE;
+ ciphertext_len = be16_to_cpup((__be16 *)pos);
+ pos += 2;
+ if (pos + ciphertext_len > buf.data + buf.length) {
+ ret = -EIO;
+ goto err_buf;
+ }
+
+ if (params->out_len < ciphertext_len) {
+ ret = -EMSGSIZE;
+ goto err_buf;
+ }
+
+ memcpy(out, pos, ciphertext_len);
+ ret = ciphertext_len;
+
+err_buf:
+ tpm_buf_destroy(&buf);
+
+err_key:
+ tpm2_flush_context(chip, key_handle);
+
+err_ops:
+ tpm_put_ops(chip);
+ return ret;
+}
+
+/*
+ * Convert a TPM2B_PUBLIC_KEY_RSA response into a raw RSA signature.
+ */
+static int tpm2_asymmetric_rsa_parse_signature(struct tpm_buf *buf,
+ off_t *offset,
+ struct kernel_pkey_params *params,
+ void *out)
+{
+ u16 sig_len;
+
+ sig_len = tpm_buf_read_u16(buf, offset);
+ if (buf->flags & TPM_BUF_BOUNDARY_ERROR)
+ return -EIO;
+ if (*offset + sig_len > buf->length)
+ return -EIO;
+ if (sig_len > params->out_len)
+ return -EMSGSIZE;
+
+ memcpy(out, &buf->data[*offset], sig_len);
+ return sig_len;
+}
+
+/*
+ * Convert a TPMT_SIGNATURE ECDSA R/S response into DER SEQUENCE form.
+ */
+static int tpm2_asymmetric_ecc_parse_signature(struct tpm_buf *buf, off_t *offset,
+ struct kernel_pkey_params *params,
+ void *out)
+{
+ u8 der[2 * (2 + ECC_MAX_BYTES + 1)];
+ u8 *encoded, *ptr;
+ const u8 *s;
+ u16 r_size;
+ u16 s_size;
+
+ r_size = tpm_buf_read_u16(buf, offset);
+ if (buf->flags & TPM_BUF_BOUNDARY_ERROR)
+ return -EIO;
+ if (r_size == 0 || r_size > ECC_MAX_BYTES ||
+ *offset + r_size + 2 > buf->length)
+ return -EIO;
+
+ s_size = get_unaligned_be16(&buf->data[*offset + r_size]);
+ s = &buf->data[*offset + r_size + 2];
+ if (s_size == 0 || s_size > ECC_MAX_BYTES ||
+ *offset + r_size + 2 + s_size > buf->length)
+ return -EIO;
+
+ ptr = der;
+ ptr = asn1_encode_integer_bytes(ptr, der + sizeof(der),
+ &buf->data[*offset], r_size);
+ ptr = asn1_encode_integer_bytes(ptr, der + sizeof(der), s, s_size);
+ if (IS_ERR(ptr))
+ return PTR_ERR(ptr);
+
+ encoded = asn1_encode_sequence(out, (u8 *)out + params->out_len,
+ der, ptr - der);
+ if (IS_ERR(encoded))
+ return PTR_ERR(encoded) == -EINVAL ? -EMSGSIZE : PTR_ERR(encoded);
+
+ return encoded - (u8 *)out;
+}
+
+static int tpm2_asymmetric_parse_signature(struct tpm_buf *buf,
+ u16 scheme, int tpm_hash,
+ struct kernel_pkey_params *params,
+ void *out)
+{
+ off_t offset = TPM_HEADER_SIZE + 4;
+ u16 hash_alg;
+ u16 sig_alg;
+
+ sig_alg = tpm_buf_read_u16(buf, &offset);
+ hash_alg = tpm_buf_read_u16(buf, &offset);
+ if (buf->flags & TPM_BUF_BOUNDARY_ERROR)
+ return -EIO;
+ if (sig_alg != scheme || hash_alg != tpm_hash)
+ return -EIO;
+
+ switch (scheme) {
+ case TPM_ALG_RSASSA:
+ return tpm2_asymmetric_rsa_parse_signature(buf, &offset, params, out);
+ case TPM_ALG_ECDSA:
+ return tpm2_asymmetric_ecc_parse_signature(buf, &offset, params, out);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/*
+ * Sign a digest using TPM2_Sign.
+ */
+static int tpm2_asymmetric_sign(struct tpm_chip *chip, struct tpm2_key *key,
+ struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ struct tpm_buf buf;
+ u32 key_handle = 0;
+ int tpm_hash;
+ u16 scheme;
+ int ret;
+
+ ret = tpm2_asymmetric_signature_scheme(key, params->encoding,
+ params->hash_algo, &scheme,
+ &tpm_hash);
+ if (ret)
+ return ret;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ return ret;
+
+ ret = tpm2_asymmetric_load(chip, key, &buf, &key_handle);
+ if (ret)
+ goto err_ops;
+
+ tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_SIGN);
+ ret = tpm_buf_append_name(chip, &buf, key_handle, NULL);
+ if (ret)
+ goto err_key;
+ tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, NULL, 0);
+
+ /* digest (TPM2B_DIGEST) */
+ tpm_buf_append_u16(&buf, params->in_len);
+ tpm_buf_append(&buf, in, params->in_len);
+
+ /* inScheme (TPMT_SIG_SCHEME) */
+ tpm_buf_append_u16(&buf, scheme);
+ tpm_buf_append_u16(&buf, tpm_hash);
+
+ /* validation (TPMT_TK_HASHCHECK): NULL ticket */
+ tpm_buf_append_u16(&buf, TPM2_ST_HASHCHECK);
+ tpm_buf_append_u32(&buf, TPM2_RH_NULL);
+ tpm_buf_append_u16(&buf, 0);
+
+ if (buf.flags & TPM_BUF_OVERFLOW) {
+ tpm2_end_auth_session(chip);
+ ret = -E2BIG;
+ goto err_key;
+ }
+ ret = tpm_buf_fill_hmac_session(chip, &buf);
+ if (ret)
+ goto err_key;
+ ret = tpm_transmit_cmd(chip, &buf, 4, "TPM2_Sign");
+ ret = tpm_buf_check_hmac_response(chip, &buf, ret);
+ if (ret) {
+ ret = -EIO;
+ goto err_key;
+ }
+
+ ret = tpm2_asymmetric_parse_signature(&buf, scheme, tpm_hash, params, out);
+
+err_key:
+ tpm2_flush_context(chip, key_handle);
+ tpm_buf_destroy(&buf);
+
+err_ops:
+ tpm_put_ops(chip);
+ return ret;
+}
+
+/*
+ * Decrypt using TPM2_RSA_Decrypt with RSAES-PKCS1-v1_5 scheme.
+ */
+static int tpm2_asymmetric_rsa_decrypt(struct tpm_chip *chip,
+ struct tpm2_key *key,
+ struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ u32 key_handle = 0;
+ struct tpm_buf buf;
+ u16 decrypted_len;
+ off_t offset;
+ int ret;
+
+ if (!params->encoding || strcmp(params->encoding, "pkcs1") != 0)
+ return -ENOPKG;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ return ret;
+
+ ret = tpm2_asymmetric_load(chip, key, &buf, &key_handle);
+ if (ret)
+ goto err_ops;
+
+ tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_RSA_DECRYPT);
+ ret = tpm_buf_append_name(chip, &buf, key_handle, NULL);
+ if (ret)
+ goto err_key;
+ tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, NULL, 0);
+ tpm_buf_append_u16(&buf, params->in_len);
+ tpm_buf_append(&buf, in, params->in_len);
+ tpm_buf_append_u16(&buf, TPM_ALG_RSAES);
+ tpm_buf_append_u16(&buf, 0);
+ if (buf.flags & TPM_BUF_OVERFLOW) {
+ tpm2_end_auth_session(chip);
+ ret = -E2BIG;
+ goto err_key;
+ }
+ ret = tpm_buf_fill_hmac_session(chip, &buf);
+ if (ret)
+ goto err_key;
+ ret = tpm_transmit_cmd(chip, &buf, 4, "TPM2_RSA_DECRYPT");
+ ret = tpm_buf_check_hmac_response(chip, &buf, ret);
+ if (ret) {
+ ret = -EIO;
+ goto err_key;
+ }
+
+ offset = TPM_HEADER_SIZE + 4;
+ decrypted_len = tpm_buf_read_u16(&buf, &offset);
+ if (buf.flags & TPM_BUF_BOUNDARY_ERROR) {
+ ret = -EIO;
+ goto err_key;
+ }
+ if (offset + decrypted_len > buf.length) {
+ ret = -EIO;
+ goto err_key;
+ }
+
+ if (params->out_len < decrypted_len) {
+ ret = -EMSGSIZE;
+ goto err_key;
+ }
+
+ memcpy(out, &buf.data[offset], decrypted_len);
+ ret = decrypted_len;
+
+err_key:
+ tpm2_flush_context(chip, key_handle);
+ tpm_buf_destroy(&buf);
+
+err_ops:
+ tpm_put_ops(chip);
+ return ret;
+}
+
+/*
+ * Verify an RSA signature using TPM2_VerifySignature with RSASSA scheme.
+ */
+static int tpm2_asymmetric_rsa_verify(const struct key *key,
+ const struct public_key_signature *sig)
+{
+ struct tpm2_key *tpm2_key = key->payload.data[asym_crypto];
+ struct tpm_chip *chip;
+ struct tpm_buf buf;
+ u32 key_handle = 0;
+ int tpm_hash;
+ int ret;
+
+ if (!sig->m)
+ return -ENOPKG;
+
+ if (!sig->encoding || strcmp(sig->encoding, "pkcs1") != 0)
+ return -ENOPKG;
+
+ if (!sig->hash_algo)
+ return -EINVAL;
+
+ chip = tpm_default_chip();
+
+ if (!chip)
+ return -ENODEV;
+
+ ret = tpm2_asymmetric_hash_lookup(sig->hash_algo, NULL, &tpm_hash);
+ if (ret)
+ goto err_chip;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ goto err_chip;
+
+ ret = tpm2_asymmetric_load(chip, tpm2_key, &buf, &key_handle);
+ if (ret)
+ goto err_ops;
+
+ tpm2_end_auth_session(chip);
+ tpm_buf_destroy(&buf);
+
+ ret = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+ TPM2_CC_VERIFY_SIGNATURE);
+ if (ret)
+ goto err_key;
+
+ tpm_buf_append_u32(&buf, key_handle);
+
+ tpm_buf_append_u16(&buf, sig->m_size);
+ tpm_buf_append(&buf, sig->m, sig->m_size);
+
+ tpm_buf_append_u16(&buf, TPM_ALG_RSASSA);
+ tpm_buf_append_u16(&buf, tpm_hash);
+ tpm_buf_append_u16(&buf, sig->s_size);
+ tpm_buf_append(&buf, sig->s, sig->s_size);
+
+ ret = tpm_transmit_cmd(chip, &buf, 0, "TPM2_VerifySignature");
+ if (ret)
+ ret = -EKEYREJECTED;
+
+ tpm_buf_destroy(&buf);
+
+err_key:
+ tpm2_flush_context(chip, key_handle);
+
+err_ops:
+ tpm_put_ops(chip);
+
+err_chip:
+ put_device(&chip->dev);
+ return ret;
+}
+
+static int tpm2_asymmetric_rsa_query(const struct kernel_pkey_params *params,
+ struct kernel_pkey_query *info)
+{
+ const struct tpm2_key *key = params->key->payload.data[asym_crypto];
+ u16 max_data_size = TPM2_MAX_DIGEST_SIZE;
+ const u16 mod_size = tpm2_asymmetric_rsa_mod_size(key);
+ int hash_id, ret;
+
+ if (!params->encoding)
+ return -EINVAL;
+
+ memset(info, 0, sizeof(*info));
+ info->key_size = mod_size * 8;
+
+ if (strcmp(params->encoding, "pkcs1") == 0) {
+ if (params->hash_algo) {
+ ret = tpm2_asymmetric_hash_lookup(params->hash_algo, &hash_id, NULL);
+ if (ret)
+ return ret;
+ max_data_size = hash_digest_size[hash_id];
+ }
+
+ info->max_data_size = max_data_size;
+ info->max_sig_size = mod_size;
+ info->max_enc_size = mod_size;
+ info->max_dec_size = mod_size;
+ info->supported_ops = KEYCTL_SUPPORTS_SIGN |
+ KEYCTL_SUPPORTS_VERIFY |
+ KEYCTL_SUPPORTS_ENCRYPT |
+ KEYCTL_SUPPORTS_DECRYPT;
+ return 0;
+ }
+
+ if (strcmp(params->encoding, "raw") == 0) {
+ info->max_data_size = mod_size;
+ info->max_enc_size = mod_size;
+ info->max_dec_size = mod_size;
+ info->supported_ops = KEYCTL_SUPPORTS_ENCRYPT;
+ return 0;
+ }
+
+ return -ENOPKG;
+}
+
+static int tpm2_asymmetric_rsa_validate(const struct tpm2_key *key)
+{
+ const struct tpm2_asymmetric_rsa_parms *p = tpm2_asymmetric_parms(key);
+ u16 key_bits;
+ u16 mod_size;
+
+ if (tpm2_key_policy_size(key) != 0)
+ return -EBADMSG;
+
+ if (key->pub_len < 2 + sizeof(*key->desc) + sizeof(*p))
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->symmetric) != TPM_ALG_NULL)
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->scheme) != TPM_ALG_NULL)
+ return -EBADMSG;
+
+ key_bits = be16_to_cpu(p->key_bits);
+ if (key_bits != 2048 && key_bits != 3072 && key_bits != 4096)
+ return -EBADMSG;
+
+ if (be32_to_cpu(p->exponent) != 0x00000000 &&
+ be32_to_cpu(p->exponent) != 0x00010001)
+ return -EBADMSG;
+
+ mod_size = tpm2_asymmetric_rsa_mod_size(key);
+ if (mod_size != key_bits / 8)
+ return -EBADMSG;
+
+ if (key->pub_len < 2 + sizeof(*key->desc) + sizeof(*p) + mod_size)
+ return -EBADMSG;
+
+ return 0;
+}
+
+static unsigned int tpm2_asymmetric_der_len_size(unsigned int len)
+{
+ if (len < 128)
+ return 1;
+ if (len <= 255)
+ return 2;
+ return 3;
+}
+
+/*
+ * Parse a DER-encoded ECDSA signature: SEQUENCE { INTEGER r, INTEGER s }.
+ *
+ * On success, @r/@r_len and @s/@s_len point into @der with leading zero
+ * pads stripped.
+ */
+static int tpm2_asymmetric_ecc_parse_der_signature(const u8 *der, u32 der_len,
+ const u8 **r, u16 *r_len,
+ const u8 **s, u16 *s_len)
+{
+ const u8 *end = der + der_len;
+ u32 seq_len, int_len;
+ const u8 *p = der;
+
+ if (p >= end || *p++ != 0x30)
+ return -EBADMSG;
+
+ if (p >= end)
+ return -EBADMSG;
+ if (*p < 0x80) {
+ seq_len = *p++;
+ } else if (*p == 0x81) {
+ if (++p >= end)
+ return -EBADMSG;
+ seq_len = *p++;
+ } else {
+ return -EBADMSG;
+ }
+
+ if (p + seq_len > end)
+ return -EBADMSG;
+ end = p + seq_len;
+
+ /* INTEGER r */
+ if (p >= end || *p++ != 0x02)
+ return -EBADMSG;
+ if (p >= end)
+ return -EBADMSG;
+ int_len = *p++;
+ if (int_len == 0 || int_len >= 0x80 || p + int_len > end)
+ return -EBADMSG;
+ while (int_len > 1 && *p == 0x00) {
+ p++;
+ int_len--;
+ }
+ *r = p;
+ *r_len = int_len;
+ p += int_len;
+
+ /* INTEGER s */
+ if (p >= end || *p++ != 0x02)
+ return -EBADMSG;
+ if (p >= end)
+ return -EBADMSG;
+ int_len = *p++;
+ if (int_len == 0 || int_len >= 0x80 || p + int_len > end)
+ return -EBADMSG;
+ while (int_len > 1 && *p == 0x00) {
+ p++;
+ int_len--;
+ }
+ *s = p;
+ *s_len = int_len;
+ p += int_len;
+
+ if (p != end)
+ return -EBADMSG;
+
+ return 0;
+}
+
+/*
+ * Verify an ECDSA signature using TPM2_VerifySignature.
+ *
+ * A DER-encoded signature is parsed into (r, s) components for the TPM command.
+ */
+static int tpm2_asymmetric_ecc_verify(const struct key *key,
+ const struct public_key_signature *sig)
+{
+ struct tpm2_key *tpm2_key = key->payload.data[asym_crypto];
+ struct tpm_chip *chip;
+ const u8 *r, *s_data;
+ struct tpm_buf buf;
+ u32 key_handle = 0;
+ u16 r_len, s_len;
+ int tpm_hash;
+ int ret;
+
+ if (!sig->m)
+ return -ENOPKG;
+
+ if (!sig->encoding || strcmp(sig->encoding, "x962") != 0)
+ return -ENOPKG;
+
+ if (!sig->hash_algo)
+ return -EINVAL;
+
+ chip = tpm_default_chip();
+
+ if (!chip)
+ return -ENODEV;
+
+ ret = tpm2_asymmetric_hash_lookup(sig->hash_algo, NULL, &tpm_hash);
+ if (ret)
+ goto err_chip;
+
+ ret = tpm2_asymmetric_ecc_parse_der_signature(sig->s, sig->s_size,
+ &r, &r_len, &s_data,
+ &s_len);
+ if (ret)
+ goto err_chip;
+
+ ret = tpm_try_get_ops(chip);
+ if (ret)
+ goto err_chip;
+
+ ret = tpm2_asymmetric_load(chip, tpm2_key, &buf, &key_handle);
+ if (ret)
+ goto err_ops;
+
+ tpm2_end_auth_session(chip);
+ tpm_buf_destroy(&buf);
+
+ ret = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS,
+ TPM2_CC_VERIFY_SIGNATURE);
+ if (ret)
+ goto err_key;
+
+ tpm_buf_append_u32(&buf, key_handle);
+
+ /* digest (TPM2B_DIGEST) */
+ tpm_buf_append_u16(&buf, sig->m_size);
+ tpm_buf_append(&buf, sig->m, sig->m_size);
+
+ /* signature (TPMT_SIGNATURE): ECDSA with the given hash */
+ tpm_buf_append_u16(&buf, TPM_ALG_ECDSA);
+ tpm_buf_append_u16(&buf, tpm_hash);
+
+ /* signatureR (TPM2B_ECC_PARAMETER) */
+ tpm_buf_append_u16(&buf, r_len);
+ tpm_buf_append(&buf, r, r_len);
+
+ /* signatureS (TPM2B_ECC_PARAMETER) */
+ tpm_buf_append_u16(&buf, s_len);
+ tpm_buf_append(&buf, s_data, s_len);
+
+ ret = tpm_transmit_cmd(chip, &buf, 0, "TPM2_VerifySignature");
+ if (ret)
+ ret = -EKEYREJECTED;
+
+ tpm_buf_destroy(&buf);
+
+err_key:
+ tpm2_flush_context(chip, key_handle);
+
+err_ops:
+ tpm_put_ops(chip);
+
+err_chip:
+ put_device(&chip->dev);
+ return ret;
+}
+
+static int tpm2_asymmetric_ecc_query(const struct kernel_pkey_params *params,
+ struct kernel_pkey_query *info)
+{
+ const struct tpm2_key *key = params->key->payload.data[asym_crypto];
+ const struct tpm2_asymmetric_ecc_parms *p = tpm2_asymmetric_parms(key);
+ unsigned int int_len, seq_payload;
+ const u8 *x;
+ u16 ecc, n;
+ int ret;
+
+ ecc = be16_to_cpu(p->ecc);
+ x = tpm2_asymmetric_ecc_x(key);
+ n = get_unaligned_be16(&x[0]);
+ int_len = n + 1;
+
+ if (!params->encoding || strcmp(params->encoding, "x962") != 0)
+ return -ENOPKG;
+
+ ret = tpm2_asymmetric_hash_lookup(params->hash_algo, NULL, NULL);
+ if (ret)
+ return ret;
+
+ /*
+ * SEQUENCE { INTEGER (<=n+1 bytes), INTEGER (<=n+1 bytes) }
+ */
+ seq_payload = 2 * (1 + tpm2_asymmetric_der_len_size(int_len) + int_len);
+
+ memset(info, 0, sizeof(*info));
+ info->key_size = tpm2_asymmetric_ecc_key_bits(ecc);
+ info->max_sig_size = 1 + tpm2_asymmetric_der_len_size(seq_payload) + seq_payload;
+ info->max_data_size = TPM2_MAX_DIGEST_SIZE;
+ info->supported_ops = KEYCTL_SUPPORTS_SIGN | KEYCTL_SUPPORTS_VERIFY;
+
+ return 0;
+}
+
+static int tpm2_asymmetric_ecc_validate(const struct tpm2_key *key)
+{
+ const struct tpm2_asymmetric_ecc_parms *p = tpm2_asymmetric_parms(key);
+ size_t min_len = 2 + sizeof(*key->desc) + sizeof(*p);
+ u16 x_size, y_size;
+ const u8 *x, *y;
+
+ if (tpm2_key_policy_size(key) != 0)
+ return -EBADMSG;
+
+ if (key->pub_len < min_len + 2)
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->symmetric) != TPM_ALG_NULL)
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->scheme) != TPM_ALG_NULL)
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->ecc) != TPM2_ECC_NIST_P256 &&
+ be16_to_cpu(p->ecc) != TPM2_ECC_NIST_P384 &&
+ be16_to_cpu(p->ecc) != TPM2_ECC_NIST_P521)
+ return -EBADMSG;
+
+ if (be16_to_cpu(p->kdf) != TPM_ALG_NULL)
+ return -EBADMSG;
+
+ x = tpm2_asymmetric_ecc_x(key);
+ x_size = get_unaligned_be16(&x[0]);
+ if (x_size > ECC_MAX_BYTES)
+ return -EBADMSG;
+
+ if (key->pub_len < min_len + 2 + x_size + 2)
+ return -EBADMSG;
+
+ y = tpm2_asymmetric_ecc_y(key);
+ y_size = get_unaligned_be16(&y[0]);
+ if (y_size > ECC_MAX_BYTES)
+ return -EBADMSG;
+
+ if (key->pub_len < min_len + 2 + x_size + 2 + y_size)
+ return -EBADMSG;
+
+ if (x_size != y_size)
+ return -EBADMSG;
+
+ return 0;
+}
+
+static const char *tpm2_asymmetric_ecc_name(const struct tpm2_key *key)
+{
+ const struct tpm2_asymmetric_ecc_parms *p;
+
+ p = tpm2_asymmetric_parms(key);
+
+ switch (be16_to_cpu(p->ecc)) {
+ case TPM2_ECC_NIST_P256:
+ return "ecdsa-nist-p256";
+ case TPM2_ECC_NIST_P384:
+ return "ecdsa-nist-p384";
+ case TPM2_ECC_NIST_P521:
+ return "ecdsa-nist-p521";
+ default:
+ return "ecdsa";
+ }
+}
+
+static void tpm2_asymmetric_describe(const struct key *asymmetric_key,
+ struct seq_file *m)
+{
+ const struct tpm2_key *key;
+
+ key = asymmetric_key->payload.data[asym_crypto];
+ if (!key)
+ return;
+
+ switch (tpm2_key_type(key)) {
+ case TPM_ALG_RSA:
+ seq_puts(m, "tpm2.rsa");
+ break;
+ case TPM_ALG_ECC:
+ seq_printf(m, "tpm2.%s", tpm2_asymmetric_ecc_name(key));
+ break;
+ default:
+ seq_puts(m, "tpm2.unknown");
+ break;
+ }
+}
+
+static int tpm2_asymmetric_query(const struct kernel_pkey_params *params,
+ struct kernel_pkey_query *info)
+{
+ struct tpm2_key *key = params->key->payload.data[asym_crypto];
+
+ switch (tpm2_key_type(key)) {
+ case TPM_ALG_RSA:
+ return tpm2_asymmetric_rsa_query(params, info);
+ case TPM_ALG_ECC:
+ return tpm2_asymmetric_ecc_query(params, info);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int tpm2_asymmetric_eds_op(struct kernel_pkey_params *params,
+ const void *in, void *out)
+{
+ struct tpm2_key *key = params->key->payload.data[asym_crypto];
+ struct tpm_chip *chip;
+ int ret;
+
+ chip = tpm_default_chip();
+ if (!chip)
+ return -ENODEV;
+
+ switch (params->op) {
+ case kernel_pkey_encrypt:
+ if (tpm2_key_type(key) != TPM_ALG_RSA) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ ret = tpm2_asymmetric_rsa_encrypt(chip, key, params, in, out);
+ break;
+ case kernel_pkey_decrypt:
+ if (tpm2_key_type(key) != TPM_ALG_RSA) {
+ ret = -EOPNOTSUPP;
+ break;
+ }
+ ret = tpm2_asymmetric_rsa_decrypt(chip, key, params, in, out);
+ break;
+ case kernel_pkey_sign:
+ ret = tpm2_asymmetric_sign(chip, key, params, in, out);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ put_device(&chip->dev);
+ return ret;
+}
+
+static int tpm2_asymmetric_verify_signature(const struct key *asymmetric_key,
+ const struct public_key_signature *sig)
+{
+ struct tpm2_key *key = asymmetric_key->payload.data[asym_crypto];
+
+ switch (tpm2_key_type(key)) {
+ case TPM_ALG_RSA:
+ return tpm2_asymmetric_rsa_verify(asymmetric_key, sig);
+ case TPM_ALG_ECC:
+ return tpm2_asymmetric_ecc_verify(asymmetric_key, sig);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static struct asymmetric_key_subtype tpm2_asymmetric_subtype = {
+ .owner = THIS_MODULE,
+ .name = "tpm2_asymmetric_key",
+ .name_len = sizeof("tpm2_asymmetric_key") - 1,
+ .describe = tpm2_asymmetric_describe,
+ .destroy = tpm2_asymmetric_key_destroy,
+ .query = tpm2_asymmetric_query,
+ .eds_op = tpm2_asymmetric_eds_op,
+ .verify_signature = tpm2_asymmetric_verify_signature,
+};
+
+static int tpm2_asymmetric_preparse(struct key_preparsed_payload *prep)
+{
+ struct tpm2_key *key __free(kfree) = NULL;
+ int ret;
+
+ key = tpm2_key_decode(prep->data, prep->datalen);
+ if (IS_ERR(key)) {
+ ret = PTR_ERR(key);
+ key = NULL;
+ return ret;
+ }
+
+ if (key->oid != OID_TPMLoadableKey)
+ return -EBADMSG;
+
+ switch (tpm2_key_type(key)) {
+ case TPM_ALG_RSA:
+ ret = tpm2_asymmetric_rsa_validate(key);
+ break;
+ case TPM_ALG_ECC:
+ ret = tpm2_asymmetric_ecc_validate(key);
+ break;
+ default:
+ ret = -EBADMSG;
+ break;
+ }
+
+ if (ret < 0)
+ return ret;
+
+ __module_get(tpm2_asymmetric_subtype.owner);
+
+ prep->payload.data[asym_subtype] = &tpm2_asymmetric_subtype;
+ prep->payload.data[asym_key_ids] = NULL;
+ prep->payload.data[asym_crypto] = no_free_ptr(key);
+ prep->payload.data[asym_auth] = NULL;
+ prep->quotalen = 100;
+
+ return 0;
+}
+
+static struct asymmetric_key_parser tpm2_asymmetric_parser = {
+ .owner = THIS_MODULE,
+ .name = "tpm2_asymmetric_parser",
+ .parse = tpm2_asymmetric_preparse,
+};
+
+static int __init tpm2_asymmetric_init(void)
+{
+ return register_asymmetric_key_parser(&tpm2_asymmetric_parser);
+}
+
+static void __exit tpm2_asymmetric_exit(void)
+{
+ unregister_asymmetric_key_parser(&tpm2_asymmetric_parser);
+}
+
+module_init(tpm2_asymmetric_init);
+module_exit(tpm2_asymmetric_exit);
+
+MODULE_DESCRIPTION("Asymmetric TPM2 key");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 202da079d500..d4d5ddc0173a 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -45,6 +45,7 @@ enum tpm2_session_types {
/* if you add a new hash to this, increment TPM_MAX_HASHES below */
enum tpm_algorithms {
TPM_ALG_ERROR = 0x0000,
+ TPM_ALG_RSA = 0x0001,
TPM_ALG_SHA1 = 0x0004,
TPM_ALG_AES = 0x0006,
TPM_ALG_KEYEDHASH = 0x0008,
@@ -53,6 +54,9 @@ enum tpm_algorithms {
TPM_ALG_SHA512 = 0x000D,
TPM_ALG_NULL = 0x0010,
TPM_ALG_SM3_256 = 0x0012,
+ TPM_ALG_RSASSA = 0x0014,
+ TPM_ALG_RSAES = 0x0015,
+ TPM_ALG_ECDSA = 0x0018,
TPM_ALG_ECC = 0x0023,
TPM_ALG_CFB = 0x0043,
};
@@ -66,6 +70,8 @@ enum tpm_algorithms {
enum tpm2_curves {
TPM2_ECC_NONE = 0x0000,
TPM2_ECC_NIST_P256 = 0x0003,
+ TPM2_ECC_NIST_P384 = 0x0004,
+ TPM2_ECC_NIST_P521 = 0x0005,
};
struct tpm_digest {
@@ -242,6 +248,7 @@ enum tpm2_structures {
TPM2_ST_NO_SESSIONS = 0x8001,
TPM2_ST_SESSIONS = 0x8002,
TPM2_ST_CREATION = 0x8021,
+ TPM2_ST_HASHCHECK = 0x8024,
};
/* Indicates from what layer of the software stack the error comes from */
@@ -276,12 +283,15 @@ enum tpm2_command_codes {
TPM2_CC_NV_READ = 0x014E,
TPM2_CC_CREATE = 0x0153,
TPM2_CC_LOAD = 0x0157,
+ TPM2_CC_RSA_DECRYPT = 0x0159,
TPM2_CC_SEQUENCE_UPDATE = 0x015C,
+ TPM2_CC_SIGN = 0x015D,
TPM2_CC_UNSEAL = 0x015E,
TPM2_CC_CONTEXT_LOAD = 0x0161,
TPM2_CC_CONTEXT_SAVE = 0x0162,
TPM2_CC_FLUSH_CONTEXT = 0x0165,
TPM2_CC_READ_PUBLIC = 0x0173,
+ TPM2_CC_RSA_ENCRYPT = 0x0174,
TPM2_CC_START_AUTH_SESS = 0x0176,
TPM2_CC_VERIFY_SIGNATURE = 0x0177,
TPM2_CC_GET_CAPABILITY = 0x017A,
--
2.47.3
^ permalink raw reply related
* [PATCH v8 2/3] crypto: Migrate TPMKey ASN.1 objects from trusted-keys
From: Jarkko Sakkinen @ 2026-05-24 5:15 UTC (permalink / raw)
To: keyrings
Cc: David Howells, linux-crypto, linux-integrity, David Woodhouse,
James Bottomley, Stefan Berger, Herbert Xu, Jarkko Sakkinen,
David S. Miller, James Bottomley, Mimi Zohar, Paul Moore,
James Morris, Serge E. Hallyn, open list,
open list:SECURITY SUBSYSTEM
In-Reply-To: <20260524051519.3708075-1-jarkko@kernel.org>
Migrate the TPMKey ASN.1 code from trusted-keys to the crypto subsystem,
and put the code behind CRYPTO_TPM2_KEY Kconfig flag.
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
crypto/Kconfig | 7 +
crypto/Makefile | 6 +
crypto/tpm2_key.asn1 | 11 ++
crypto/tpm2_key.c | 150 ++++++++++++++++++++++
include/crypto/tpm2_key.h | 46 +++++++
security/keys/trusted-keys/Kconfig | 2 +-
security/keys/trusted-keys/Makefile | 2 -
security/keys/trusted-keys/tpm2key.asn1 | 11 --
security/keys/trusted-keys/trusted_tpm2.c | 119 ++---------------
9 files changed, 232 insertions(+), 122 deletions(-)
create mode 100644 crypto/tpm2_key.asn1
create mode 100644 crypto/tpm2_key.c
create mode 100644 include/crypto/tpm2_key.h
delete mode 100644 security/keys/trusted-keys/tpm2key.asn1
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 103d1f58cb7c..5476d80372a1 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -3,6 +3,13 @@
# Generic algorithms support
#
+config CRYPTO_TPM2_KEY
+ bool
+ depends on CRYPTO
+ select ASN1
+ select OID_REGISTRY
+ default n
+
#
# async_tx api: hardware offloaded memory transfer/transform support
#
diff --git a/crypto/Makefile b/crypto/Makefile
index 162242593c7c..e232f9b9bee6 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -206,3 +206,9 @@ obj-$(CONFIG_CRYPTO_KDF800108_CTR) += kdf_sp800108.o
obj-$(CONFIG_CRYPTO_DF80090A) += df_sp80090a.o
obj-$(CONFIG_CRYPTO_KRB5) += krb5/
+
+ifdef CONFIG_CRYPTO_TPM2_KEY
+$(obj)/tpm2_key.asn1.o: $(obj)/tpm2_key.asn1.h $(obj)/tpm2_key.asn1.c
+$(obj)/tpm2_key.o: $(obj)/tpm2_key.asn1.h
+obj-y += tpm2_key.o tpm2_key.asn1.o
+endif
diff --git a/crypto/tpm2_key.asn1 b/crypto/tpm2_key.asn1
new file mode 100644
index 000000000000..553bf996af59
--- /dev/null
+++ b/crypto/tpm2_key.asn1
@@ -0,0 +1,11 @@
+---
+--- ASN.1 for TPM 2.0 keys
+---
+
+TPMKey ::= SEQUENCE {
+ type OBJECT IDENTIFIER ({tpm2_key_get_type}),
+ emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL ({tpm2_key_get_empty_auth}),
+ parent INTEGER ({tpm2_key_get_parent}),
+ pubkey OCTET STRING ({tpm2_get_public}),
+ privkey OCTET STRING ({tpm2_get_private})
+ }
diff --git a/crypto/tpm2_key.c b/crypto/tpm2_key.c
new file mode 100644
index 000000000000..5704ccdb7c0d
--- /dev/null
+++ b/crypto/tpm2_key.c
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <crypto/tpm2_key.h>
+#include <linux/oid_registry.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include "tpm2_key.asn1.h"
+
+#undef pr_fmt
+#define pr_fmt(fmt) "tpm2_key: "fmt
+
+struct tpm2_key_decoder_context {
+ u32 parent;
+ const u8 *pub;
+ u32 pub_len;
+ const u8 *priv;
+ u32 priv_len;
+ enum OID oid;
+ bool empty_auth;
+};
+
+int tpm2_key_get_parent(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct tpm2_key_decoder_context *decoder = context;
+ const u8 *v = value;
+ int i;
+
+ decoder->parent = 0;
+ for (i = 0; i < vlen; i++) {
+ decoder->parent <<= 8;
+ decoder->parent |= v[i];
+ }
+
+ return 0;
+}
+
+int tpm2_key_get_type(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct tpm2_key_decoder_context *decoder = context;
+
+ decoder->oid = look_up_OID(value, vlen);
+ return 0;
+}
+
+int tpm2_key_get_empty_auth(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct tpm2_key_decoder_context *decoder = context;
+ const u8 *bool_value = value;
+
+ if (!value || vlen != 1)
+ return -EBADMSG;
+
+ decoder->empty_auth = bool_value[0] != 0;
+ return 0;
+}
+
+static inline bool tpm2_key_is_valid(const void *value, size_t vlen)
+{
+ if (vlen < 2 || vlen > TPM2_KEY_BYTES_MAX)
+ return false;
+
+ if (get_unaligned_be16(value) != vlen - 2)
+ return false;
+
+ return true;
+}
+
+int tpm2_get_public(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct tpm2_key_decoder_context *decoder = context;
+
+ if (!tpm2_key_is_valid(value, vlen))
+ return -EBADMSG;
+
+ if (sizeof(struct tpm2_key_desc) > vlen - 2)
+ return -EBADMSG;
+
+ decoder->pub = value;
+ decoder->pub_len = vlen;
+ return 0;
+}
+
+int tpm2_get_private(void *context, size_t hdrlen, unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct tpm2_key_decoder_context *decoder = context;
+
+ if (!tpm2_key_is_valid(value, vlen))
+ return -EBADMSG;
+
+ decoder->priv = value;
+ decoder->priv_len = vlen;
+ return 0;
+}
+
+/**
+ * tpm2_key_decode() - Decode TPM2 ASN.1 key
+ * @src: ASN.1 source.
+ * @src_len: ASN.1 source length.
+ *
+ * Decodes the TPM2 ASN.1 key and validates that the public key data has all
+ * the shared fields of TPMT_PUBLIC. This is full coverage of the memory that
+ * can be validated before doing any key type specific validation.
+ *
+ * Return:
+ * - TPM2 ASN.1 key on success.
+ * - -EBADMSG when decoding fails.
+ * - -ENOMEM when OOM while allocating struct tpm2_key.
+ */
+struct tpm2_key *tpm2_key_decode(const u8 *src, u32 src_len)
+{
+ struct tpm2_key_decoder_context decoder;
+ struct tpm2_key *key;
+ u8 *data;
+ int ret;
+
+ memset(&decoder, 0, sizeof(decoder));
+ ret = asn1_ber_decoder(&tpm2_key_decoder, &decoder, src, src_len);
+ if (ret < 0) {
+ if (ret != -EBADMSG)
+ pr_info("Decoder error %d\n", ret);
+
+ return ERR_PTR(-EBADMSG);
+ }
+
+ key = kzalloc(sizeof(*key), GFP_KERNEL);
+ if (!key)
+ return ERR_PTR(-ENOMEM);
+
+ data = &key->data[0];
+ memcpy(&data[0], decoder.priv, decoder.priv_len);
+ memcpy(&data[decoder.priv_len], decoder.pub, decoder.pub_len);
+
+ key->oid = decoder.oid;
+ key->priv_len = decoder.priv_len;
+ key->pub_len = decoder.pub_len;
+ key->parent = decoder.parent;
+ key->desc = (struct tpm2_key_desc *)&data[decoder.priv_len + 2];
+ key->empty_auth = decoder.empty_auth;
+ return key;
+}
+EXPORT_SYMBOL_GPL(tpm2_key_decode);
diff --git a/include/crypto/tpm2_key.h b/include/crypto/tpm2_key.h
new file mode 100644
index 000000000000..883afaa596e5
--- /dev/null
+++ b/include/crypto/tpm2_key.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __LINUX_TPM2_KEY_H__
+#define __LINUX_TPM2_KEY_H__
+
+#include <linux/oid_registry.h>
+#include <linux/slab.h>
+
+#define TPM2_KEY_BYTES_MAX 1024
+
+/* TPM2 Structures 12.2.4: TPMT_PUBLIC */
+struct tpm2_key_desc {
+ __be16 type;
+ __be16 name_alg;
+ __be32 object_attributes;
+ __be16 policy_size;
+} __packed;
+
+/* Decoded TPM2 ASN.1 key. */
+struct tpm2_key {
+ u8 data[2 * TPM2_KEY_BYTES_MAX];
+ struct tpm2_key_desc *desc;
+ u16 priv_len;
+ u16 pub_len;
+ u32 parent;
+ enum OID oid;
+ bool empty_auth;
+};
+
+struct tpm2_key *tpm2_key_decode(const u8 *src, u32 src_len);
+
+static inline const void *tpm2_key_data(const struct tpm2_key *key)
+{
+ return &key->data[0];
+}
+
+static inline u16 tpm2_key_type(const struct tpm2_key *key)
+{
+ return be16_to_cpu(key->desc->type);
+}
+
+static inline int tpm2_key_policy_size(const struct tpm2_key *key)
+{
+ return be16_to_cpu(key->desc->policy_size);
+}
+
+#endif /* __LINUX_TPM2_KEY_H__ */
diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig
index e5a4a53aeab2..09b1ec1d5bc2 100644
--- a/security/keys/trusted-keys/Kconfig
+++ b/security/keys/trusted-keys/Kconfig
@@ -27,9 +27,9 @@ config TRUSTED_KEYS_TPM
select CRYPTO_HASH_INFO
select CRYPTO_LIB_SHA1
select CRYPTO_LIB_UTILS
+ select CRYPTO_TPM2_KEY
select ASN1_ENCODER
select OID_REGISTRY
- select ASN1
select HAVE_TRUSTED_KEYS
help
Enable use of the Trusted Platform Module (TPM) as trusted key
diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile
index 5fc053a21dad..ac09d2d90051 100644
--- a/security/keys/trusted-keys/Makefile
+++ b/security/keys/trusted-keys/Makefile
@@ -7,9 +7,7 @@ obj-$(CONFIG_TRUSTED_KEYS) += trusted.o
trusted-y += trusted_core.o
trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm1.o
-$(obj)/trusted_tpm2.o: $(obj)/tpm2key.asn1.h
trusted-$(CONFIG_TRUSTED_KEYS_TPM) += trusted_tpm2.o
-trusted-$(CONFIG_TRUSTED_KEYS_TPM) += tpm2key.asn1.o
trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o
diff --git a/security/keys/trusted-keys/tpm2key.asn1 b/security/keys/trusted-keys/tpm2key.asn1
deleted file mode 100644
index f57f869ad600..000000000000
--- a/security/keys/trusted-keys/tpm2key.asn1
+++ /dev/null
@@ -1,11 +0,0 @@
----
---- ASN.1 for TPM 2.0 keys
----
-
-TPMKey ::= SEQUENCE {
- type OBJECT IDENTIFIER ({tpm2_key_type}),
- emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL,
- parent INTEGER ({tpm2_key_parent}),
- pubkey OCTET STRING ({tpm2_key_pub}),
- privkey OCTET STRING ({tpm2_key_priv})
- }
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 6340823f8b53..5b079fe476d1 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -13,11 +13,10 @@
#include <keys/trusted-type.h>
#include <keys/trusted_tpm.h>
+#include <crypto/tpm2_key.h>
#include <linux/unaligned.h>
-#include "tpm2key.asn1.h"
-
static u32 tpm2key_oid[] = { 2, 23, 133, 10, 1, 5 };
static int tpm2_key_encode(struct trusted_key_payload *payload,
@@ -90,105 +89,6 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
return ret;
}
-struct tpm2_key_context {
- u32 parent;
- const u8 *pub;
- u32 pub_len;
- const u8 *priv;
- u32 priv_len;
-};
-
-static int tpm2_key_decode(struct trusted_key_payload *payload,
- struct trusted_key_options *options,
- u8 **buf)
-{
- int ret;
- struct tpm2_key_context ctx;
- u8 *blob;
-
- memset(&ctx, 0, sizeof(ctx));
-
- ret = asn1_ber_decoder(&tpm2key_decoder, &ctx, payload->blob,
- payload->blob_len);
- if (ret < 0)
- return ret;
-
- if (ctx.priv_len + ctx.pub_len > MAX_BLOB_SIZE)
- return -EINVAL;
-
- blob = kmalloc(ctx.priv_len + ctx.pub_len + 4, GFP_KERNEL);
- if (!blob)
- return -ENOMEM;
-
- *buf = blob;
- options->keyhandle = ctx.parent;
-
- memcpy(blob, ctx.priv, ctx.priv_len);
- blob += ctx.priv_len;
-
- memcpy(blob, ctx.pub, ctx.pub_len);
-
- return 0;
-}
-
-int tpm2_key_parent(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- struct tpm2_key_context *ctx = context;
- const u8 *v = value;
- int i;
-
- ctx->parent = 0;
- for (i = 0; i < vlen; i++) {
- ctx->parent <<= 8;
- ctx->parent |= v[i];
- }
-
- return 0;
-}
-
-int tpm2_key_type(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- enum OID oid = look_up_OID(value, vlen);
-
- if (oid != OID_TPMSealedData) {
- char buffer[50];
-
- sprint_oid(value, vlen, buffer, sizeof(buffer));
- pr_debug("OID is \"%s\" which is not TPMSealedData\n",
- buffer);
- return -EINVAL;
- }
-
- return 0;
-}
-
-int tpm2_key_pub(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- struct tpm2_key_context *ctx = context;
-
- ctx->pub = value;
- ctx->pub_len = vlen;
-
- return 0;
-}
-
-int tpm2_key_priv(void *context, size_t hdrlen,
- unsigned char tag,
- const void *value, size_t vlen)
-{
- struct tpm2_key_context *ctx = context;
-
- ctx->priv = value;
- ctx->priv_len = vlen;
-
- return 0;
-}
/**
* tpm2_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
@@ -372,23 +272,26 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
struct trusted_key_options *options,
u32 *blob_handle)
{
- u8 *blob_ref __free(kfree) = NULL;
+ struct tpm2_key *key __free(kfree) = NULL;
struct tpm_buf buf;
unsigned int private_len;
unsigned int public_len;
unsigned int blob_len;
- u8 *blob, *pub;
+ const u8 *blob, *pub;
int rc;
u32 attrs;
- rc = tpm2_key_decode(payload, options, &blob);
- if (rc) {
+ key = tpm2_key_decode(payload->blob, payload->blob_len);
+ if (IS_ERR(key))
+ key = NULL;
+
+ if (key && key->oid == OID_TPMSealedData) {
+ options->keyhandle = key->parent;
+ blob = tpm2_key_data(key);
+ } else {
/* old form */
blob = payload->blob;
payload->old_format = 1;
- } else {
- /* Bind for cleanup: */
- blob_ref = blob;
}
/* new format carries keyhandle but old format doesn't */
--
2.47.3
^ permalink raw reply related
* [PATCH v8 1/3] lib/asn1_encoder: Add asn1_encode_integer_bytes()
From: Jarkko Sakkinen @ 2026-05-24 5:15 UTC (permalink / raw)
To: keyrings
Cc: David Howells, linux-crypto, linux-integrity, David Woodhouse,
James Bottomley, Stefan Berger, Herbert Xu, Jarkko Sakkinen,
Andrew Morton, James Bottomley, Mimi Zohar, Paul Moore,
James Morris, Serge E. Hallyn, open list,
open list:SECURITY SUBSYSTEM
In-Reply-To: <20260524051519.3708075-1-jarkko@kernel.org>
Add a helper encoding a positive integer from a byte array in big-endian
format.
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
include/linux/asn1_encoder.h | 3 ++
lib/asn1_encoder.c | 62 ++++++++++++++++++++++++++++++++++++
2 files changed, 65 insertions(+)
diff --git a/include/linux/asn1_encoder.h b/include/linux/asn1_encoder.h
index d17484dffb74..e206bd425854 100644
--- a/include/linux/asn1_encoder.h
+++ b/include/linux/asn1_encoder.h
@@ -12,6 +12,9 @@ unsigned char *
asn1_encode_integer(unsigned char *data, const unsigned char *end_data,
s64 integer);
unsigned char *
+asn1_encode_integer_bytes(unsigned char *data, const unsigned char *end_data,
+ const unsigned char *integer, u32 integer_len);
+unsigned char *
asn1_encode_oid(unsigned char *data, const unsigned char *end_data,
u32 oid[], int oid_len);
unsigned char *
diff --git a/lib/asn1_encoder.c b/lib/asn1_encoder.c
index 92f35aae13b1..22e0acd6fe08 100644
--- a/lib/asn1_encoder.c
+++ b/lib/asn1_encoder.c
@@ -10,6 +10,8 @@
#include <linux/string.h>
#include <linux/module.h>
+static int asn1_encode_length(unsigned char **data, int *data_len, int len);
+
/**
* asn1_encode_integer() - encode positive integer to ASN.1
* @data: pointer to the pointer to the data
@@ -85,6 +87,66 @@ asn1_encode_integer(unsigned char *data, const unsigned char *end_data,
}
EXPORT_SYMBOL_GPL(asn1_encode_integer);
+/**
+ * asn1_encode_integer_bytes() - encode positive integer bytes to ASN.1
+ * @data: pointer to the pointer to the data
+ * @end_data: end of data pointer, points one beyond last usable byte in @data
+ * @bytes: integer bytes
+ * @bytes_len: amount of bytes
+ *
+ * Encode a positive integer from a byte array in big-endian format. Strip
+ * leading zeros.
+ */
+unsigned char *
+asn1_encode_integer_bytes(unsigned char *data, const unsigned char *end_data,
+ const unsigned char *bytes, u32 bytes_len)
+{
+ static const unsigned char zero;
+ int data_len = end_data - data;
+ bool add_pad = false;
+ int ret;
+
+ if (IS_ERR(data))
+ return data;
+
+ if (!bytes || !bytes_len)
+ return ERR_PTR(-EINVAL);
+
+ /* Strip leading zeros: */
+ while (bytes_len > 1 && bytes[0] == 0) {
+ bytes++;
+ bytes_len--;
+ }
+
+ if (!bytes_len) {
+ bytes = &zero;
+ bytes_len = 1;
+ } else {
+ add_pad = bytes[0] & 0x80;
+ }
+
+ if (data_len < 2)
+ return ERR_PTR(-EINVAL);
+
+ *(data++) = _tag(UNIV, PRIM, INT);
+ data_len--;
+
+ ret = asn1_encode_length(&data, &data_len, bytes_len + add_pad);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (data_len < bytes_len + add_pad)
+ return ERR_PTR(-EINVAL);
+
+ if (add_pad)
+ *(data++) = 0;
+
+ memcpy(data, bytes, bytes_len);
+ data += bytes_len;
+ return data;
+}
+EXPORT_SYMBOL_GPL(asn1_encode_integer_bytes);
+
/* calculate the base 128 digit values setting the top bit of the first octet */
static int asn1_encode_oid_digit(unsigned char **_data, int *data_len, u32 oid)
{
--
2.47.3
^ permalink raw reply related
* [PATCH v8 0/3]
From: Jarkko Sakkinen @ 2026-05-24 5:15 UTC (permalink / raw)
To: keyrings
Cc: David Howells, linux-crypto, linux-integrity, David Woodhouse,
James Bottomley, Stefan Berger, Herbert Xu, Jarkko Sakkinen,
James Bottomley, Mimi Zohar, Paul Moore, James Morris,
Serge E. Hallyn, open list:SECURITY SUBSYSTEM, open list
This series introduces key type for operating with asymmetric keys using
a TPM2 chip.
Change Log
==========
v8:
- Reset patch change logs given the overhaul of the code and patches.
- Have only single new subkey type.
- Make key type only use TPM operations.
- Use TPM2_Sign for both ECC and RSA keys.
- Align key descriptions with other key types.
Previous versions
=================
* v7: https://lore.kernel.org/linux-integrity/20240528210823.28798-1-jarkko@kernel.org/
* v6: https://lore.kernel.org/linux-integrity/20240528035136.11464-1-jarkko@kernel.org/
* v5: https://lore.kernel.org/linux-integrity/20240523212515.4875-1-jarkko@kernel.org/
* v4: https://lore.kernel.org/linux-integrity/20240522005252.17841-1-jarkko@kernel.org/
* v3: https://lore.kernel.org/linux-integrity/20240521152659.26438-1-jarkko@kernel.org/
* v2: https://lore.kernel.org/linux-integrity/336755.1716327854@warthog.procyon.org.uk/
* v1: https://lore.kernel.org/linux-integrity/20240520184727.22038-1-jarkko@kernel.org/
* Derived from https://lore.kernel.org/all/20200518172704.29608-1-prestwoj@gmail.com/
Jarkko Sakkinen (3):
lib/asn1_encoder: Add asn1_encode_integer_bytes()
crypto: Migrate TPMKey ASN.1 objects from trusted-keys
keys: asymmetric: tpm2_asymmetric
crypto/Kconfig | 7 +
crypto/Makefile | 6 +
crypto/asymmetric_keys/Kconfig | 17 +
crypto/asymmetric_keys/Makefile | 1 +
crypto/asymmetric_keys/tpm2_asymmetric.c | 1096 +++++++++++++++++++++
crypto/tpm2_key.asn1 | 11 +
crypto/tpm2_key.c | 150 +++
include/crypto/tpm2_key.h | 46 +
include/linux/asn1_encoder.h | 3 +
include/linux/tpm.h | 10 +
lib/asn1_encoder.c | 62 ++
security/keys/trusted-keys/Kconfig | 2 +-
security/keys/trusted-keys/Makefile | 2 -
security/keys/trusted-keys/tpm2key.asn1 | 11 -
security/keys/trusted-keys/trusted_tpm2.c | 119 +--
15 files changed, 1421 insertions(+), 122 deletions(-)
create mode 100644 crypto/asymmetric_keys/tpm2_asymmetric.c
create mode 100644 crypto/tpm2_key.asn1
create mode 100644 crypto/tpm2_key.c
create mode 100644 include/crypto/tpm2_key.h
delete mode 100644 security/keys/trusted-keys/tpm2key.asn1
--
2.47.3
^ permalink raw reply
* [PATCH 0/3] AF_ALG: Remove support for AIO and old-style drivers
From: Demi Marie Obenour via B4 Relay @ 2026-05-23 19:43 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, Jens Axboe, Jakub Kicinski,
Simon Horman, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Jonathan Corbet, Shuah Khan, Eric Biggers,
Ard Biesheuvel
Cc: linux-crypto, linux-kernel, io-uring, netdev, linux-perf-users,
linux-doc, Demi Marie Obenour
AF_ALG is a deprecated API only useful for compatibility with existing
userspace. It has had a lot of vulnerabilities, including the infamous
CopyFail.
Rip out support for offload drivers, which tend to be buggy. Also rip
out support for AIO, which actually bloats the entire socket subsystem.
Only compile-tested.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
---
Demi Marie Obenour (3):
net: Remove support for AIO on sockets
AF_ALG: Drop support for off-CPU cryptography
AF_ALG: Document that it is *always* slower
Documentation/crypto/userspace-if.rst | 26 ++++++++--
crypto/af_alg.c | 35 ++------------
crypto/algif_aead.c | 43 ++++-------------
crypto/algif_hash.c | 4 +-
crypto/algif_rng.c | 4 +-
crypto/algif_skcipher.c | 66 ++++++--------------------
include/crypto/if_alg.h | 19 ++++++--
include/linux/socket.h | 1 -
io_uring/net.c | 1 -
net/compat.c | 1 -
net/socket.c | 7 +--
tools/perf/trace/beauty/include/linux/socket.h | 1 -
12 files changed, 70 insertions(+), 138 deletions(-)
---
base-commit: 49e05bb00f2e8168695f7af4d694c39e1423e8a2
change-id: 20260502-af-alg-harden-900849451653
Best regards,
--
Demi Marie Obenour <demiobenour@gmail.com>
^ permalink raw reply
* [PATCH 2/3] AF_ALG: Drop support for off-CPU cryptography
From: Demi Marie Obenour via B4 Relay @ 2026-05-23 19:43 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, Jens Axboe, Jakub Kicinski,
Simon Horman, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Jonathan Corbet, Shuah Khan, Eric Biggers,
Ard Biesheuvel
Cc: linux-crypto, linux-kernel, io-uring, netdev, linux-perf-users,
linux-doc, Demi Marie Obenour
In-Reply-To: <20260523-af-alg-harden-v1-0-c76755c3a5c5@gmail.com>
From: Demi Marie Obenour <demiobenour@gmail.com>
AF_ALG is deprecated and exposed to unprivileged userspace. Only
use the least buggy algorithm implementations: the pure software ones.
This removes one of the main advantages of AF_ALG, which is the
ability to use it with off-CPU accelerators. However, using off-CPU
accelerators has huge overheads, both in performance and attack surface.
I have yet to see real-world, performance-critical workloads where using
an accelerator via AF_ALG is actually a win over doing cryptography in
userspace.
If using an off-CPU accelerator really does turn out to be a win, a new
API should be developed that is actually a good fit for it.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
---
Documentation/crypto/userspace-if.rst | 7 ++++++-
crypto/af_alg.c | 2 +-
crypto/algif_aead.c | 4 ++--
crypto/algif_hash.c | 4 ++--
crypto/algif_rng.c | 4 ++--
crypto/algif_skcipher.c | 4 ++--
include/crypto/if_alg.h | 14 +++++++++++++-
7 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst
index ea1b1b3f4049fd4673528dc2a6234f6376a3489f..b31117d4415dda6ad6ca36275e615bec7df9552e 100644
--- a/Documentation/crypto/userspace-if.rst
+++ b/Documentation/crypto/userspace-if.rst
@@ -9,7 +9,8 @@ symmetric cipher, AEAD, and RNG algorithms that are implemented in kernel-mode
code.
AF_ALG is insecure and is deprecated. Originally added to the kernel in 2010,
-most kernel developers now consider it to be a mistake.
+most kernel developers now consider it to be a mistake. Support for hardware
+accelerators, which was the original purpose of AF_ALG, has been removed.
AF_ALG continues to be supported only for backwards compatibility. On systems
where no programs using AF_ALG remain, the support for it should be disabled by
@@ -59,6 +60,10 @@ Some of the examples include:
- CVE-2013-7421
- CVE-2011-4081
+Hardware accelerator drivers are frequently buggy. To reduce attack surface,
+AF_ALG now only provides access to algorithms implemented in software. This
+means that AF_ALG no longer fulfills its original purpose.
+
It is recommended that, whenever possible, userspace programs be migrated to
userspace crypto code (which again, is what is normally used anyway) and
``CONFIG_CRYPTO_USER_API_*`` be disabled. On systems that use SELinux, SELinux
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 8ccf7a737cd6ca9a5d5bf47050c9afea0dfd61bf..cce000e8590e469927b5a5a0ceccfdf0ef54633d 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -181,7 +181,7 @@ static int alg_bind(struct socket *sock, struct sockaddr_unsized *uaddr, int add
if (IS_ERR(type))
return PTR_ERR(type);
- private = type->bind(sa->salg_name, sa->salg_feat, sa->salg_mask);
+ private = type->bind(sa->salg_name);
if (IS_ERR(private)) {
module_put(type->owner);
return PTR_ERR(private);
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 60f06597cb0b13036bc975641a0b02ea8a41ad03..787aac8aeb24eed128f08345ba730478113919b3 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -342,9 +342,9 @@ static struct proto_ops algif_aead_ops_nokey = {
.poll = af_alg_poll,
};
-static void *aead_bind(const char *name, u32 type, u32 mask)
+static void *aead_bind(const char *name)
{
- return crypto_alloc_aead(name, type, mask);
+ return crypto_alloc_aead(name, 0, AF_ALG_CRYPTOAPI_MASK);
}
static void aead_release(void *private)
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index 4d3dfc60a16a6d8b677d903d209df18d67202c98..5452ad6c15069c3cb0ff78fe58868fe7ce4b0fc3 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -380,9 +380,9 @@ static struct proto_ops algif_hash_ops_nokey = {
.accept = hash_accept_nokey,
};
-static void *hash_bind(const char *name, u32 type, u32 mask)
+static void *hash_bind(const char *name)
{
- return crypto_alloc_ahash(name, type, mask);
+ return crypto_alloc_ahash(name, 0, AF_ALG_CRYPTOAPI_MASK);
}
static void hash_release(void *private)
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index a9fb492e929a70c94476f296f5f5e7c42f0313b7..4dfe7899f8fa4ce82d5f2236297230fb44bc35d6 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -197,7 +197,7 @@ static struct proto_ops __maybe_unused algif_rng_test_ops = {
.sendmsg = rng_test_sendmsg,
};
-static void *rng_bind(const char *name, u32 type, u32 mask)
+static void *rng_bind(const char *name)
{
struct rng_parent_ctx *pctx;
struct crypto_rng *rng;
@@ -206,7 +206,7 @@ static void *rng_bind(const char *name, u32 type, u32 mask)
if (!pctx)
return ERR_PTR(-ENOMEM);
- rng = crypto_alloc_rng(name, type, mask);
+ rng = crypto_alloc_rng(name, 0, AF_ALG_CRYPTOAPI_MASK);
if (IS_ERR(rng)) {
kfree(pctx);
return ERR_CAST(rng);
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 9dbccabd87b13920c27aff5a450a235cc6a27d59..df20bdfe1f1f4e453782dee3b743dd1939ab4c6c 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -307,9 +307,9 @@ static struct proto_ops algif_skcipher_ops_nokey = {
.poll = af_alg_poll,
};
-static void *skcipher_bind(const char *name, u32 type, u32 mask)
+static void *skcipher_bind(const char *name)
{
- return crypto_alloc_skcipher(name, type, mask);
+ return crypto_alloc_skcipher(name, 0, AF_ALG_CRYPTOAPI_MASK);
}
static void skcipher_release(void *private)
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 62867daca47d76c9ea1a7ed233188788c5f6c3c0..7643ba954125aba0c06aaf19de087985325885ad 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -41,7 +41,7 @@ struct af_alg_control {
};
struct af_alg_type {
- void *(*bind)(const char *name, u32 type, u32 mask);
+ void *(*bind)(const char *name);
void (*release)(void *private);
int (*setkey)(void *private, const u8 *key, unsigned int keylen);
int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
@@ -243,4 +243,16 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
struct af_alg_async_req *areq, size_t maxsize,
size_t *outlen);
+/*
+ * Mask used to disable unsupported algorithm implementations.
+ *
+ * This is the same as FSCRYPT_CRYPTOAPI_MASK in fs/crypto/fscrypt_private.h.
+ * In additions to the motivations there, this API is exposed to userspace
+ * that might not be fully trusted.
+ */
+#define AF_ALG_CRYPTOAPI_MASK \
+ (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \
+ CRYPTO_ALG_KERN_DRIVER_ONLY)
+
+
#endif /* _CRYPTO_IF_ALG_H */
--
2.54.0
^ permalink raw reply related
* [PATCH 3/3] AF_ALG: Document that it is *always* slower
From: Demi Marie Obenour via B4 Relay @ 2026-05-23 19:43 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, Jens Axboe, Jakub Kicinski,
Simon Horman, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Jonathan Corbet, Shuah Khan, Eric Biggers,
Ard Biesheuvel
Cc: linux-crypto, linux-kernel, io-uring, netdev, linux-perf-users,
linux-doc, Demi Marie Obenour
In-Reply-To: <20260523-af-alg-harden-v1-0-c76755c3a5c5@gmail.com>
From: Demi Marie Obenour <demiobenour@gmail.com>
Without support for zero-copy or off-CPU offloads, AF_ALG is always
slower than software cryptography. Its only advantage is that it might
save code size. However, this is largely mitigated by lightweight
userspace cryptographic libraries.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
---
Documentation/crypto/userspace-if.rst | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/Documentation/crypto/userspace-if.rst b/Documentation/crypto/userspace-if.rst
index b31117d4415dda6ad6ca36275e615bec7df9552e..ab93300c8e04524469f284704c7c5ed582fdcbc0 100644
--- a/Documentation/crypto/userspace-if.rst
+++ b/Documentation/crypto/userspace-if.rst
@@ -28,8 +28,8 @@ functionality than that. It actually provides access to all software algorithms.
This includes arbitrary compositions of different algorithms created via a
complex template system, as well as algorithms that only make sense as internal
-implementation details of other algorithms. It also includes full zero-copy
-support, which is difficult for the kernel to implement securely.
+implementation details of other algorithms. In the past, it also included full
+zero-copy support, which was difficult for the kernel to implement securely.
Ultimately, these algorithms are just math computations. They use the same
instructions that userspace programs already have access to, just accessed in a
@@ -38,6 +38,21 @@ much more convoluted and less efficient way.
Indeed, userspace code is nearly always what is being used anyway. These same
algorithms are widely implemented in userspace crypto libraries.
+Even when zero-copy and off-CPU accelerators were supported, AF_ALG was usually
+much slower than optimized software cryptography in userspace. This was
+especially true for the small message sizes usually seen in performance-critical
+workloads. While it was possible to demonstrate performance wins for hashing
+large files on embedded devices, it is hard to imagine a situation where this
+would be performance-critical.
+
+Nowadays, AF_ALG no longer supports zero-copy or off-CPU accelerators.
+Therefore, it is *always* slower than an optimized userspace implementation,
+even for large messages. The only possible advantage left is that it avoids
+duplicating code between kernel and userspace. However, userspace
+implementations, especially hardware-accelerated ones, do not need to be large.
+Just because OpenSSL is huge does not mean that all userspace cryptography
+libraries are.
+
Meanwhile, AF_ALG hasn't been withstanding modern vulnerability discovery tools
such as syzbot and large language models. It receives a steady stream of CVEs.
Some of the examples include:
--
2.54.0
^ permalink raw reply related
* [PATCH 1/3] net: Remove support for AIO on sockets
From: Demi Marie Obenour via B4 Relay @ 2026-05-23 19:43 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, Jens Axboe, Jakub Kicinski,
Simon Horman, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Jonathan Corbet, Shuah Khan, Eric Biggers,
Ard Biesheuvel
Cc: linux-crypto, linux-kernel, io-uring, netdev, linux-perf-users,
linux-doc, Demi Marie Obenour
In-Reply-To: <20260523-af-alg-harden-v1-0-c76755c3a5c5@gmail.com>
From: Demi Marie Obenour <demiobenour@gmail.com>
The only user of msg->msg_iocb was AF_ALG, but that's deprecated.
It can be removed entirely at the cost of only supporting synchronous
operations. This doesn't break userspace, which will silently block
(for a bounded amount of time) in io_submit instead of operating
asynchronously.
This also makes struct msghdr smaller, helping every other caller of
sendmsg().
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
---
crypto/af_alg.c | 33 +-------------
crypto/algif_aead.c | 39 ++++------------
crypto/algif_skcipher.c | 62 +++++---------------------
include/crypto/if_alg.h | 5 +--
include/linux/socket.h | 1 -
io_uring/net.c | 1 -
net/compat.c | 1 -
net/socket.c | 7 +--
tools/perf/trace/beauty/include/linux/socket.h | 1 -
9 files changed, 25 insertions(+), 125 deletions(-)
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index 48c53f488e0fd30818e72439fe0c0d7e4cee1432..8ccf7a737cd6ca9a5d5bf47050c9afea0dfd61bf 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -1085,35 +1085,6 @@ void af_alg_free_resources(struct af_alg_async_req *areq)
}
EXPORT_SYMBOL_GPL(af_alg_free_resources);
-/**
- * af_alg_async_cb - AIO callback handler
- * @data: async request completion data
- * @err: if non-zero, error result to be returned via ki_complete();
- * otherwise return the AIO output length via ki_complete().
- *
- * This handler cleans up the struct af_alg_async_req upon completion of the
- * AIO operation.
- *
- * The number of bytes to be generated with the AIO operation must be set
- * in areq->outlen before the AIO callback handler is invoked.
- */
-void af_alg_async_cb(void *data, int err)
-{
- struct af_alg_async_req *areq = data;
- struct sock *sk = areq->sk;
- struct kiocb *iocb = areq->iocb;
- unsigned int resultlen;
-
- /* Buffer size written by crypto operation. */
- resultlen = areq->outlen;
-
- af_alg_free_resources(areq);
- sock_put(sk);
-
- iocb->ki_complete(iocb, err ? err : (int)resultlen);
-}
-EXPORT_SYMBOL_GPL(af_alg_async_cb);
-
/**
* af_alg_poll - poll system call handler
* @file: file pointer
@@ -1154,8 +1125,8 @@ struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
struct af_alg_ctx *ctx = alg_sk(sk)->private;
struct af_alg_async_req *areq;
- /* Only one AIO request can be in flight. */
- if (ctx->inflight)
+ /* Only one request can be in flight. */
+ if (WARN_ON_ONCE(ctx->inflight))
return ERR_PTR(-EBUSY);
areq = sock_kmalloc(sk, areqlen, GFP_KERNEL);
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index c6c2ce21895dd7df51dc825ed886ba7e1aa37130..60f06597cb0b13036bc975641a0b02ea8a41ad03 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -197,37 +197,14 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen);
aead_request_set_tfm(&areq->cra_u.aead_req, tfm);
- if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
- /* AIO operation */
- sock_hold(sk);
- areq->iocb = msg->msg_iocb;
-
- /* Remember output size that will be generated. */
- areq->outlen = outlen;
-
- aead_request_set_callback(&areq->cra_u.aead_req,
- CRYPTO_TFM_REQ_MAY_SLEEP,
- af_alg_async_cb, areq);
- err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) :
- crypto_aead_decrypt(&areq->cra_u.aead_req);
-
- /* AIO operation in progress */
- if (err == -EINPROGRESS)
- return -EIOCBQUEUED;
-
- sock_put(sk);
- } else {
- /* Synchronous operation */
- aead_request_set_callback(&areq->cra_u.aead_req,
- CRYPTO_TFM_REQ_MAY_SLEEP |
- CRYPTO_TFM_REQ_MAY_BACKLOG,
- crypto_req_done, &ctx->wait);
- err = crypto_wait_req(ctx->enc ?
- crypto_aead_encrypt(&areq->cra_u.aead_req) :
- crypto_aead_decrypt(&areq->cra_u.aead_req),
- &ctx->wait);
- }
-
+ aead_request_set_callback(&areq->cra_u.aead_req,
+ CRYPTO_TFM_REQ_MAY_SLEEP |
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &ctx->wait);
+ err = crypto_wait_req(ctx->enc ?
+ crypto_aead_encrypt(&areq->cra_u.aead_req) :
+ crypto_aead_decrypt(&areq->cra_u.aead_req),
+ &ctx->wait);
free:
af_alg_free_resources(areq);
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index ba0a17fd95aca22aa58ebf510c7d9b5f0cea2c2e..9dbccabd87b13920c27aff5a450a235cc6a27d59 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -79,20 +79,6 @@ static int algif_skcipher_export(struct sock *sk, struct skcipher_request *req)
return err;
}
-static void algif_skcipher_done(void *data, int err)
-{
- struct af_alg_async_req *areq = data;
- struct sock *sk = areq->sk;
-
- if (err)
- goto out;
-
- err = algif_skcipher_export(sk, &areq->cra_u.skcipher_req);
-
-out:
- af_alg_async_cb(data, err);
-}
-
static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
size_t ignored, int flags)
{
@@ -171,43 +157,19 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
cflags |= CRYPTO_SKCIPHER_REQ_CONT;
}
- if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) {
- /* AIO operation */
- sock_hold(sk);
- areq->iocb = msg->msg_iocb;
+ skcipher_request_set_callback(&areq->cra_u.skcipher_req,
+ cflags |
+ CRYPTO_TFM_REQ_MAY_SLEEP |
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
+ crypto_req_done, &ctx->wait);
+ err = crypto_wait_req(ctx->enc ?
+ crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
+ crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
+ &ctx->wait);
- /* Remember output size that will be generated. */
- areq->outlen = len;
-
- skcipher_request_set_callback(&areq->cra_u.skcipher_req,
- cflags |
- CRYPTO_TFM_REQ_MAY_SLEEP,
- algif_skcipher_done, areq);
- err = ctx->enc ?
- crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
- crypto_skcipher_decrypt(&areq->cra_u.skcipher_req);
-
- /* AIO operation in progress */
- if (err == -EINPROGRESS)
- return -EIOCBQUEUED;
-
- sock_put(sk);
- } else {
- /* Synchronous operation */
- skcipher_request_set_callback(&areq->cra_u.skcipher_req,
- cflags |
- CRYPTO_TFM_REQ_MAY_SLEEP |
- CRYPTO_TFM_REQ_MAY_BACKLOG,
- crypto_req_done, &ctx->wait);
- err = crypto_wait_req(ctx->enc ?
- crypto_skcipher_encrypt(&areq->cra_u.skcipher_req) :
- crypto_skcipher_decrypt(&areq->cra_u.skcipher_req),
- &ctx->wait);
-
- if (!err)
- err = algif_skcipher_export(
- sk, &areq->cra_u.skcipher_req);
- }
+ if (!err)
+ err = algif_skcipher_export(
+ sk, &areq->cra_u.skcipher_req);
free:
af_alg_free_resources(areq);
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 0cc8fa749f68d2356789f72771c9e550b79e0b3d..62867daca47d76c9ea1a7ed233188788c5f6c3c0 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -80,7 +80,6 @@ struct af_alg_rsgl {
/**
* struct af_alg_async_req - definition of crypto request
- * @iocb: IOCB for AIO operations
* @sk: Socket the request is associated with
* @first_rsgl: First RX SG
* @last_rsgl: Pointer to last RX SG
@@ -92,7 +91,6 @@ struct af_alg_rsgl {
* @cra_u: Cipher request
*/
struct af_alg_async_req {
- struct kiocb *iocb;
struct sock *sk;
struct af_alg_rsgl first_rsgl;
@@ -138,7 +136,7 @@ struct af_alg_async_req {
* @write: True if we are in the middle of a write.
* @init: True if metadata has been sent.
* @len: Length of memory allocated for this data structure.
- * @inflight: Non-zero when AIO requests are in flight.
+ * @inflight: Non-zero when requests are in flight, for debugging only.
*/
struct af_alg_ctx {
struct list_head tsgl_list;
@@ -237,7 +235,6 @@ int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
unsigned int ivsize);
void af_alg_free_resources(struct af_alg_async_req *areq);
-void af_alg_async_cb(void *data, int err);
__poll_t af_alg_poll(struct file *file, struct socket *sock,
poll_table *wait);
struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
diff --git a/include/linux/socket.h b/include/linux/socket.h
index ec4a0a0257939a5363c55bed3ccb20182965b2e3..3ffdfe184b23d0a739e095407e956885d116c299 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -89,7 +89,6 @@ struct msghdr {
bool msg_get_inq : 1;/* return INQ after receive */
unsigned int msg_flags; /* flags on received message */
__kernel_size_t msg_controllen; /* ancillary data buffer length */
- struct kiocb *msg_iocb; /* ptr to iocb for async requests */
struct ubuf_info *msg_ubuf;
int (*sg_from_iter)(struct sk_buff *skb,
struct iov_iter *from, size_t length);
diff --git a/io_uring/net.c b/io_uring/net.c
index 30cd22c0b934b97ce6e265756b24daca7d398361..22100933966af547dfe6a52e69fc6882b4197234 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -771,7 +771,6 @@ static int io_recvmsg_prep_setup(struct io_kiocb *req)
kmsg->msg.msg_control = NULL;
kmsg->msg.msg_get_inq = 1;
kmsg->msg.msg_controllen = 0;
- kmsg->msg.msg_iocb = NULL;
kmsg->msg.msg_ubuf = NULL;
if (req->flags & REQ_F_BUFFER_SELECT)
diff --git a/net/compat.c b/net/compat.c
index 2c9bd0edac997bc8c6ebd1bc8b92d8437ff32ea4..d68cf9c3aad5f7f1de84edbfffcf99d71e89292a 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -75,7 +75,6 @@ int __get_compat_msghdr(struct msghdr *kmsg,
if (msg->msg_iovlen > UIO_MAXIOV)
return -EMSGSIZE;
- kmsg->msg_iocb = NULL;
kmsg->msg_ubuf = NULL;
return 0;
}
diff --git a/net/socket.c b/net/socket.c
index 22a412fdec079cf8fd829a15236de9daea09d2f2..9785363858cef0c4e6f0efc45b17c3d2add5a53c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1213,8 +1213,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
{
struct file *file = iocb->ki_filp;
struct socket *sock = file->private_data;
- struct msghdr msg = {.msg_iter = *to,
- .msg_iocb = iocb};
+ struct msghdr msg = {.msg_iter = *to};
ssize_t res;
if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
@@ -1235,8 +1234,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
struct socket *sock = file->private_data;
- struct msghdr msg = {.msg_iter = *from,
- .msg_iocb = iocb};
+ struct msghdr msg = {.msg_iter = *from};
ssize_t res;
if (iocb->ki_pos != 0)
@@ -2612,7 +2610,6 @@ int __copy_msghdr(struct msghdr *kmsg,
if (msg->msg_iovlen > UIO_MAXIOV)
return -EMSGSIZE;
- kmsg->msg_iocb = NULL;
kmsg->msg_ubuf = NULL;
return 0;
}
diff --git a/tools/perf/trace/beauty/include/linux/socket.h b/tools/perf/trace/beauty/include/linux/socket.h
index ec715ad4bf25f5f759d2cab3c6b796fed84df932..2a0a50fd66f41589f2699f7288a143873ce1bba6 100644
--- a/tools/perf/trace/beauty/include/linux/socket.h
+++ b/tools/perf/trace/beauty/include/linux/socket.h
@@ -89,7 +89,6 @@ struct msghdr {
bool msg_get_inq : 1;/* return INQ after receive */
unsigned int msg_flags; /* flags on received message */
__kernel_size_t msg_controllen; /* ancillary data buffer length */
- struct kiocb *msg_iocb; /* ptr to iocb for async requests */
struct ubuf_info *msg_ubuf;
int (*sg_from_iter)(struct sk_buff *skb,
struct iov_iter *from, size_t length);
--
2.54.0
^ permalink raw reply related
* [PATCH 1/2] crypto: Delete Qualcomm crypto engine driver
From: Demi Marie Obenour via B4 Relay @ 2026-05-23 19:03 UTC (permalink / raw)
To: Herbert Xu, David S. Miller, Thara Gopinath, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Konrad Dybcio,
Russell King
Cc: linux-kernel, linux-crypto, linux-arm-msm, Eric Biggers,
Ard Biesheuvel, devicetree, linux-arm-kernel, Demi Marie Obenour
In-Reply-To: <20260523-delete-qce-v1-0-86105cd7f406@gmail.com>
From: Demi Marie Obenour <demiobenour@gmail.com>
It's slower than the generic C code and causes problems.
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
---
MAINTAINERS | 8 -
arch/arm/configs/multi_v7_defconfig | 1 -
arch/arm64/configs/defconfig | 1 -
drivers/crypto/Kconfig | 111 -----
drivers/crypto/Makefile | 1 -
drivers/crypto/qce/Makefile | 9 -
drivers/crypto/qce/aead.c | 841 ------------------------------------
drivers/crypto/qce/aead.h | 56 ---
drivers/crypto/qce/cipher.h | 56 ---
drivers/crypto/qce/common.c | 595 -------------------------
drivers/crypto/qce/common.h | 104 -----
drivers/crypto/qce/core.c | 271 ------------
drivers/crypto/qce/core.h | 64 ---
drivers/crypto/qce/dma.c | 135 ------
drivers/crypto/qce/dma.h | 47 --
drivers/crypto/qce/regs-v5.h | 326 --------------
drivers/crypto/qce/sha.c | 545 -----------------------
drivers/crypto/qce/sha.h | 72 ---
drivers/crypto/qce/skcipher.c | 529 -----------------------
19 files changed, 3772 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 882214b0e7db53bb8cc8e75b5d2269ee0591ea20..ff631ec4b025ed256d7ef74c313a88755c205797 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -21898,14 +21898,6 @@ F: Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
F: Documentation/devicetree/bindings/opp/opp-v2-kryo-cpu.yaml
F: drivers/cpufreq/qcom-cpufreq-nvmem.c
-QUALCOMM CRYPTO DRIVERS
-M: Thara Gopinath <thara.gopinath@gmail.com>
-L: linux-crypto@vger.kernel.org
-L: linux-arm-msm@vger.kernel.org
-S: Maintained
-F: Documentation/devicetree/bindings/crypto/qcom-qce.yaml
-F: drivers/crypto/qce/
-
QUALCOMM EMAC GIGABIT ETHERNET DRIVER
M: Timur Tabi <timur@kernel.org>
L: netdev@vger.kernel.org
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index bcc9aabc120283e8b98584964e0db3e24679724f..54960c8dc0989226ffd16c69cd26b69c33d22b79 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -1335,7 +1335,6 @@ CONFIG_CRYPTO_DEV_ATMEL_AES=m
CONFIG_CRYPTO_DEV_ATMEL_TDES=m
CONFIG_CRYPTO_DEV_ATMEL_SHA=m
CONFIG_CRYPTO_DEV_MARVELL_CESA=m
-CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_ROCKCHIP=m
CONFIG_CRYPTO_DEV_STM32_HASH=m
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index d905a0777f939c51cc39df6230591a31058b765f..6ba10b76026867dd4f4d3dead6d59dadf0e7d9aa 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -1952,7 +1952,6 @@ CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
CONFIG_CRYPTO_DEV_SUN8I_CE=m
CONFIG_CRYPTO_DEV_FSL_CAAM=m
CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
-CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_TEGRA=m
CONFIG_CRYPTO_DEV_XILINX_TRNG=m
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 3449b3c9c6adfdaf1ab5740d6b3542c39c7d5745..6da104e8c3c270968f4d7f0bdd2a03c90e2621a1 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -545,117 +545,6 @@ source "drivers/crypto/cavium/nitrox/Kconfig"
source "drivers/crypto/marvell/Kconfig"
source "drivers/crypto/intel/Kconfig"
-config CRYPTO_DEV_QCE
- tristate "Qualcomm crypto engine accelerator"
- depends on ARCH_QCOM || COMPILE_TEST
- depends on HAS_IOMEM
- help
- This driver supports Qualcomm crypto engine accelerator
- hardware. To compile this driver as a module, choose M here. The
- module will be called qcrypto.
-
-config CRYPTO_DEV_QCE_SKCIPHER
- bool
- depends on CRYPTO_DEV_QCE
- select CRYPTO_AES
- select CRYPTO_LIB_DES
- select CRYPTO_ECB
- select CRYPTO_CBC
- select CRYPTO_XTS
- select CRYPTO_CTR
- select CRYPTO_SKCIPHER
-
-config CRYPTO_DEV_QCE_SHA
- bool
- depends on CRYPTO_DEV_QCE
- select CRYPTO_SHA1
- select CRYPTO_SHA256
-
-config CRYPTO_DEV_QCE_AEAD
- bool
- depends on CRYPTO_DEV_QCE
- select CRYPTO_AUTHENC
- select CRYPTO_LIB_DES
-
-choice
- prompt "Algorithms enabled for QCE acceleration"
- default CRYPTO_DEV_QCE_ENABLE_ALL
- depends on CRYPTO_DEV_QCE
- help
- This option allows to choose whether to build support for all algorithms
- (default), hashes-only, or skciphers-only.
-
- The QCE engine does not appear to scale as well as the CPU to handle
- multiple crypto requests. While the ipq40xx chips have 4-core CPUs, the
- QCE handles only 2 requests in parallel.
-
- Ipsec throughput seems to improve when disabling either family of
- algorithms, sharing the load with the CPU. Enabling skciphers-only
- appears to work best.
-
- config CRYPTO_DEV_QCE_ENABLE_ALL
- bool "All supported algorithms"
- select CRYPTO_DEV_QCE_SKCIPHER
- select CRYPTO_DEV_QCE_SHA
- select CRYPTO_DEV_QCE_AEAD
- help
- Enable all supported algorithms:
- - AES (CBC, CTR, ECB, XTS)
- - 3DES (CBC, ECB)
- - DES (CBC, ECB)
- - SHA1, HMAC-SHA1
- - SHA256, HMAC-SHA256
-
- config CRYPTO_DEV_QCE_ENABLE_SKCIPHER
- bool "Symmetric-key ciphers only"
- select CRYPTO_DEV_QCE_SKCIPHER
- help
- Enable symmetric-key ciphers only:
- - AES (CBC, CTR, ECB, XTS)
- - 3DES (ECB, CBC)
- - DES (ECB, CBC)
-
- config CRYPTO_DEV_QCE_ENABLE_SHA
- bool "Hash/HMAC only"
- select CRYPTO_DEV_QCE_SHA
- help
- Enable hashes/HMAC algorithms only:
- - SHA1, HMAC-SHA1
- - SHA256, HMAC-SHA256
-
- config CRYPTO_DEV_QCE_ENABLE_AEAD
- bool "AEAD algorithms only"
- select CRYPTO_DEV_QCE_AEAD
- help
- Enable AEAD algorithms only:
- - authenc()
- - ccm(aes)
- - rfc4309(ccm(aes))
-endchoice
-
-config CRYPTO_DEV_QCE_SW_MAX_LEN
- int "Default maximum request size to use software for AES"
- depends on CRYPTO_DEV_QCE && CRYPTO_DEV_QCE_SKCIPHER
- default 512
- help
- This sets the default maximum request size to perform AES requests
- using software instead of the crypto engine. It can be changed by
- setting the aes_sw_max_len parameter.
-
- Small blocks are processed faster in software than hardware.
- Considering the 256-bit ciphers, software is 2-3 times faster than
- qce at 256-bytes, 30% faster at 512, and about even at 768-bytes.
- With 128-bit keys, the break-even point would be around 1024-bytes.
-
- The default is set a little lower, to 512 bytes, to balance the
- cost in CPU usage. The minimum recommended setting is 16-bytes
- (1 AES block), since AES-GCM will fail if you set it lower.
- Setting this to zero will send all requests to the hardware.
-
- Note that 192-bit keys are not supported by the hardware and are
- always processed by the software fallback, and all DES requests
- are done by the hardware.
-
config CRYPTO_DEV_QCOM_RNG
tristate "Qualcomm Random Number Generator Driver"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 283bbc650b5b22a3f2a5a1ec81ca42ae3d37a80f..9fcd55a8474e5a95c0c189d9ae5d890abcd5dbdc 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -27,7 +27,6 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
-obj-$(CONFIG_CRYPTO_DEV_QCE) += qce/
obj-$(CONFIG_CRYPTO_DEV_QCOM_RNG) += qcom-rng.o
obj-$(CONFIG_CRYPTO_DEV_ROCKCHIP) += rockchip/
obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o
diff --git a/drivers/crypto/qce/Makefile b/drivers/crypto/qce/Makefile
deleted file mode 100644
index 2cf8984e1b85161ab468bdec4d50950f40d070d0..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_CRYPTO_DEV_QCE) += qcrypto.o
-qcrypto-objs := core.o \
- common.o \
- dma.o
-
-qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SHA) += sha.o
-qcrypto-$(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) += skcipher.o
-qcrypto-$(CONFIG_CRYPTO_DEV_QCE_AEAD) += aead.o
diff --git a/drivers/crypto/qce/aead.c b/drivers/crypto/qce/aead.c
deleted file mode 100644
index 9cb11fada2c4ddecebcb5c48416245f402389bb1..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/aead.c
+++ /dev/null
@@ -1,841 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-
-/*
- * Copyright (C) 2021, Linaro Limited. All rights reserved.
- */
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <crypto/gcm.h>
-#include <crypto/authenc.h>
-#include <crypto/internal/aead.h>
-#include <crypto/internal/des.h>
-#include <crypto/sha1.h>
-#include <crypto/sha2.h>
-#include <crypto/scatterwalk.h>
-#include "aead.h"
-
-#define CCM_NONCE_ADATA_SHIFT 6
-#define CCM_NONCE_AUTHSIZE_SHIFT 3
-#define MAX_CCM_ADATA_HEADER_LEN 6
-
-static LIST_HEAD(aead_algs);
-
-static void qce_aead_done(void *data)
-{
- struct crypto_async_request *async_req = data;
- struct aead_request *req = aead_request_cast(async_req);
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- struct qce_result_dump *result_buf = qce->dma.result_buf;
- enum dma_data_direction dir_src, dir_dst;
- bool diff_dst;
- int error;
- u32 status;
- unsigned int totallen;
- unsigned char tag[SHA256_DIGEST_SIZE] = {0};
-
- diff_dst = (req->src != req->dst) ? true : false;
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
-
- error = qce_dma_terminate_all(&qce->dma);
- if (error)
- dev_dbg(qce->dev, "aead dma termination error (%d)\n",
- error);
- if (diff_dst)
- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
-
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
-
- if (IS_CCM(rctx->flags)) {
- if (req->assoclen) {
- sg_free_table(&rctx->src_tbl);
- if (diff_dst)
- sg_free_table(&rctx->dst_tbl);
- } else {
- if (!(IS_DECRYPT(rctx->flags) && !diff_dst))
- sg_free_table(&rctx->dst_tbl);
- }
- } else {
- sg_free_table(&rctx->dst_tbl);
- }
-
- error = qce_check_status(qce, &status);
- if (error < 0 && (error != -EBADMSG))
- dev_err(qce->dev, "aead operation error (%x)\n", status);
-
- if (IS_ENCRYPT(rctx->flags)) {
- totallen = req->cryptlen + req->assoclen;
- if (IS_CCM(rctx->flags))
- scatterwalk_map_and_copy(rctx->ccmresult_buf, req->dst,
- totallen, ctx->authsize, 1);
- else
- scatterwalk_map_and_copy(result_buf->auth_iv, req->dst,
- totallen, ctx->authsize, 1);
-
- } else if (!IS_CCM(rctx->flags)) {
- totallen = req->cryptlen + req->assoclen - ctx->authsize;
- scatterwalk_map_and_copy(tag, req->src, totallen, ctx->authsize, 0);
- if (memcmp(result_buf->auth_iv, tag, ctx->authsize)) {
- pr_err("Bad message error\n");
- error = -EBADMSG;
- }
- }
-
- qce->async_req_done(qce, error);
-}
-
-static struct scatterlist *
-qce_aead_prepare_result_buf(struct sg_table *tbl, struct aead_request *req)
-{
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
-
- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
- return qce_sgtable_add(tbl, &rctx->result_sg, QCE_RESULT_BUF_SZ);
-}
-
-static struct scatterlist *
-qce_aead_prepare_ccm_result_buf(struct sg_table *tbl, struct aead_request *req)
-{
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
-
- sg_init_one(&rctx->result_sg, rctx->ccmresult_buf, QCE_BAM_BURST_SIZE);
- return qce_sgtable_add(tbl, &rctx->result_sg, QCE_BAM_BURST_SIZE);
-}
-
-static struct scatterlist *
-qce_aead_prepare_dst_buf(struct aead_request *req)
-{
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- struct scatterlist *sg, *msg_sg, __sg[2];
- gfp_t gfp;
- unsigned int assoclen = req->assoclen;
- unsigned int totallen;
- int ret;
-
- totallen = rctx->cryptlen + assoclen;
- rctx->dst_nents = sg_nents_for_len(req->dst, totallen);
- if (rctx->dst_nents < 0) {
- dev_err(qce->dev, "Invalid numbers of dst SG.\n");
- return ERR_PTR(-EINVAL);
- }
- if (IS_CCM(rctx->flags))
- rctx->dst_nents += 2;
- else
- rctx->dst_nents += 1;
-
- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC;
- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
- if (ret)
- return ERR_PTR(ret);
-
- if (IS_CCM(rctx->flags) && assoclen) {
- /* Get the dst buffer */
- msg_sg = scatterwalk_ffwd(__sg, req->dst, assoclen);
-
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->adata_sg,
- rctx->assoclen);
- if (IS_ERR(sg))
- goto dst_tbl_free;
- /* dst buffer */
- sg = qce_sgtable_add(&rctx->dst_tbl, msg_sg, rctx->cryptlen);
- if (IS_ERR(sg))
- goto dst_tbl_free;
- totallen = rctx->cryptlen + rctx->assoclen;
- } else {
- if (totallen) {
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, totallen);
- if (IS_ERR(sg))
- goto dst_tbl_free;
- }
- }
- if (IS_CCM(rctx->flags))
- sg = qce_aead_prepare_ccm_result_buf(&rctx->dst_tbl, req);
- else
- sg = qce_aead_prepare_result_buf(&rctx->dst_tbl, req);
-
- if (IS_ERR(sg))
- goto dst_tbl_free;
-
- sg_mark_end(sg);
- rctx->dst_sg = rctx->dst_tbl.sgl;
- rctx->dst_nents = sg_nents_for_len(rctx->dst_sg, totallen) + 1;
-
- return sg;
-
-dst_tbl_free:
- sg_free_table(&rctx->dst_tbl);
- return sg;
-}
-
-static int
-qce_aead_ccm_prepare_buf_assoclen(struct aead_request *req)
-{
- struct scatterlist *sg, *msg_sg, __sg[2];
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- unsigned int assoclen = rctx->assoclen;
- unsigned int adata_header_len, cryptlen, totallen;
- gfp_t gfp;
- bool diff_dst;
- int ret;
-
- if (IS_DECRYPT(rctx->flags))
- cryptlen = rctx->cryptlen + ctx->authsize;
- else
- cryptlen = rctx->cryptlen;
- totallen = cryptlen + req->assoclen;
-
- /* Get the msg */
- msg_sg = scatterwalk_ffwd(__sg, req->src, req->assoclen);
-
- rctx->adata = kzalloc((ALIGN(assoclen, 16) + MAX_CCM_ADATA_HEADER_LEN) *
- sizeof(unsigned char), GFP_ATOMIC);
- if (!rctx->adata)
- return -ENOMEM;
-
- /*
- * Format associated data (RFC3610 and NIST 800-38C)
- * Even though specification allows for AAD to be up to 2^64 - 1 bytes,
- * the assoclen field in aead_request is unsigned int and thus limits
- * the AAD to be up to 2^32 - 1 bytes. So we handle only two scenarios
- * while forming the header for AAD.
- */
- if (assoclen < 0xff00) {
- adata_header_len = 2;
- *(__be16 *)rctx->adata = cpu_to_be16(assoclen);
- } else {
- adata_header_len = 6;
- *(__be16 *)rctx->adata = cpu_to_be16(0xfffe);
- *(__be32 *)(rctx->adata + 2) = cpu_to_be32(assoclen);
- }
-
- /* Copy the associated data */
- if (sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, assoclen),
- rctx->adata + adata_header_len,
- assoclen) != assoclen)
- return -EINVAL;
-
- /* Pad associated data to block size */
- rctx->assoclen = ALIGN(assoclen + adata_header_len, 16);
-
- diff_dst = (req->src != req->dst) ? true : false;
-
- if (diff_dst)
- rctx->src_nents = sg_nents_for_len(req->src, totallen) + 1;
- else
- rctx->src_nents = sg_nents_for_len(req->src, totallen) + 2;
-
- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? GFP_KERNEL : GFP_ATOMIC;
- ret = sg_alloc_table(&rctx->src_tbl, rctx->src_nents, gfp);
- if (ret)
- return ret;
-
- /* Associated Data */
- sg_init_one(&rctx->adata_sg, rctx->adata, rctx->assoclen);
- sg = qce_sgtable_add(&rctx->src_tbl, &rctx->adata_sg,
- rctx->assoclen);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto err_free;
- }
- /* src msg */
- sg = qce_sgtable_add(&rctx->src_tbl, msg_sg, cryptlen);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto err_free;
- }
- if (!diff_dst) {
- /*
- * For decrypt, when src and dst buffers are same, there is already space
- * in the buffer for padded 0's which is output in lieu of
- * the MAC that is input. So skip the below.
- */
- if (!IS_DECRYPT(rctx->flags)) {
- sg = qce_aead_prepare_ccm_result_buf(&rctx->src_tbl, req);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto err_free;
- }
- }
- }
- sg_mark_end(sg);
- rctx->src_sg = rctx->src_tbl.sgl;
- totallen = cryptlen + rctx->assoclen;
- rctx->src_nents = sg_nents_for_len(rctx->src_sg, totallen);
-
- if (diff_dst) {
- sg = qce_aead_prepare_dst_buf(req);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto err_free;
- }
- } else {
- if (IS_ENCRYPT(rctx->flags))
- rctx->dst_nents = rctx->src_nents + 1;
- else
- rctx->dst_nents = rctx->src_nents;
- rctx->dst_sg = rctx->src_sg;
- }
-
- return 0;
-err_free:
- sg_free_table(&rctx->src_tbl);
- return ret;
-}
-
-static int qce_aead_prepare_buf(struct aead_request *req)
-{
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- struct scatterlist *sg;
- bool diff_dst = (req->src != req->dst) ? true : false;
- unsigned int totallen;
-
- totallen = rctx->cryptlen + rctx->assoclen;
-
- sg = qce_aead_prepare_dst_buf(req);
- if (IS_ERR(sg))
- return PTR_ERR(sg);
- if (diff_dst) {
- rctx->src_nents = sg_nents_for_len(req->src, totallen);
- if (rctx->src_nents < 0) {
- dev_err(qce->dev, "Invalid numbers of src SG.\n");
- return -EINVAL;
- }
- rctx->src_sg = req->src;
- } else {
- rctx->src_nents = rctx->dst_nents - 1;
- rctx->src_sg = rctx->dst_sg;
- }
- return 0;
-}
-
-static int qce_aead_ccm_prepare_buf(struct aead_request *req)
-{
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- struct scatterlist *sg;
- bool diff_dst = (req->src != req->dst) ? true : false;
- unsigned int cryptlen;
-
- if (rctx->assoclen)
- return qce_aead_ccm_prepare_buf_assoclen(req);
-
- if (IS_ENCRYPT(rctx->flags))
- return qce_aead_prepare_buf(req);
-
- cryptlen = rctx->cryptlen + ctx->authsize;
- if (diff_dst) {
- rctx->src_nents = sg_nents_for_len(req->src, cryptlen);
- rctx->src_sg = req->src;
- sg = qce_aead_prepare_dst_buf(req);
- if (IS_ERR(sg))
- return PTR_ERR(sg);
- } else {
- rctx->src_nents = sg_nents_for_len(req->src, cryptlen);
- rctx->src_sg = req->src;
- rctx->dst_nents = rctx->src_nents;
- rctx->dst_sg = rctx->src_sg;
- }
-
- return 0;
-}
-
-static int qce_aead_create_ccm_nonce(struct qce_aead_reqctx *rctx, struct qce_aead_ctx *ctx)
-{
- unsigned int msglen_size, ivsize;
- u8 msg_len[4];
- int i;
-
- if (!rctx || !rctx->iv)
- return -EINVAL;
-
- msglen_size = rctx->iv[0] + 1;
-
- /* Verify that msg len size is valid */
- if (msglen_size < 2 || msglen_size > 8)
- return -EINVAL;
-
- ivsize = rctx->ivsize;
-
- /*
- * Clear the msglen bytes in IV.
- * Else the h/w engine and nonce will use any stray value pending there.
- */
- if (!IS_CCM_RFC4309(rctx->flags)) {
- for (i = 0; i < msglen_size; i++)
- rctx->iv[ivsize - i - 1] = 0;
- }
-
- /*
- * The crypto framework encodes cryptlen as unsigned int. Thus, even though
- * spec allows for upto 8 bytes to encode msg_len only 4 bytes are needed.
- */
- if (msglen_size > 4)
- msglen_size = 4;
-
- memcpy(&msg_len[0], &rctx->cryptlen, 4);
-
- memcpy(&rctx->ccm_nonce[0], rctx->iv, rctx->ivsize);
- if (rctx->assoclen)
- rctx->ccm_nonce[0] |= 1 << CCM_NONCE_ADATA_SHIFT;
- rctx->ccm_nonce[0] |= ((ctx->authsize - 2) / 2) <<
- CCM_NONCE_AUTHSIZE_SHIFT;
- for (i = 0; i < msglen_size; i++)
- rctx->ccm_nonce[QCE_MAX_NONCE - i - 1] = msg_len[i];
-
- return 0;
-}
-
-static int
-qce_aead_async_req_handle(struct crypto_async_request *async_req)
-{
- struct aead_request *req = aead_request_cast(async_req);
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- enum dma_data_direction dir_src, dir_dst;
- bool diff_dst;
- int dst_nents, src_nents, ret;
-
- if (IS_CCM_RFC4309(rctx->flags)) {
- memset(rctx->ccm_rfc4309_iv, 0, QCE_MAX_IV_SIZE);
- rctx->ccm_rfc4309_iv[0] = 3;
- memcpy(&rctx->ccm_rfc4309_iv[1], ctx->ccm4309_salt, QCE_CCM4309_SALT_SIZE);
- memcpy(&rctx->ccm_rfc4309_iv[4], req->iv, 8);
- rctx->iv = rctx->ccm_rfc4309_iv;
- rctx->ivsize = AES_BLOCK_SIZE;
- } else {
- rctx->iv = req->iv;
- rctx->ivsize = crypto_aead_ivsize(tfm);
- }
- if (IS_CCM_RFC4309(rctx->flags))
- rctx->assoclen = req->assoclen - 8;
- else
- rctx->assoclen = req->assoclen;
-
- diff_dst = (req->src != req->dst) ? true : false;
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
-
- if (IS_CCM(rctx->flags)) {
- ret = qce_aead_create_ccm_nonce(rctx, ctx);
- if (ret)
- return ret;
- }
- if (IS_CCM(rctx->flags))
- ret = qce_aead_ccm_prepare_buf(req);
- else
- ret = qce_aead_prepare_buf(req);
-
- if (ret)
- return ret;
- dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
- if (!dst_nents) {
- ret = -EIO;
- goto error_free;
- }
-
- if (diff_dst) {
- src_nents = dma_map_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
- if (src_nents < 0) {
- ret = src_nents;
- goto error_unmap_dst;
- }
- } else {
- if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags))
- src_nents = dst_nents;
- else
- src_nents = dst_nents - 1;
- }
-
- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, rctx->dst_sg, dst_nents,
- qce_aead_done, async_req);
- if (ret)
- goto error_unmap_src;
-
- qce_dma_issue_pending(&qce->dma);
-
- ret = qce_start(async_req, tmpl->crypto_alg_type);
- if (ret)
- goto error_terminate;
-
- return 0;
-
-error_terminate:
- qce_dma_terminate_all(&qce->dma);
-error_unmap_src:
- if (diff_dst)
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
-error_unmap_dst:
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
-error_free:
- if (IS_CCM(rctx->flags) && rctx->assoclen) {
- sg_free_table(&rctx->src_tbl);
- if (diff_dst)
- sg_free_table(&rctx->dst_tbl);
- } else {
- sg_free_table(&rctx->dst_tbl);
- }
- return ret;
-}
-
-static int qce_aead_crypt(struct aead_request *req, int encrypt)
-{
- struct crypto_aead *tfm = crypto_aead_reqtfm(req);
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- struct qce_alg_template *tmpl = to_aead_tmpl(tfm);
- unsigned int blocksize = crypto_aead_blocksize(tfm);
-
- rctx->flags = tmpl->alg_flags;
- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
-
- if (encrypt)
- rctx->cryptlen = req->cryptlen;
- else
- rctx->cryptlen = req->cryptlen - ctx->authsize;
-
- /* CE does not handle 0 length messages */
- if (!rctx->cryptlen) {
- if (!(IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags)))
- ctx->need_fallback = true;
- }
-
- /* If fallback is needed, schedule and exit */
- if (ctx->need_fallback) {
- /* Reset need_fallback in case the same ctx is used for another transaction */
- ctx->need_fallback = false;
-
- aead_request_set_tfm(&rctx->fallback_req, ctx->fallback);
- aead_request_set_callback(&rctx->fallback_req, req->base.flags,
- req->base.complete, req->base.data);
- aead_request_set_crypt(&rctx->fallback_req, req->src,
- req->dst, req->cryptlen, req->iv);
- aead_request_set_ad(&rctx->fallback_req, req->assoclen);
-
- return encrypt ? crypto_aead_encrypt(&rctx->fallback_req) :
- crypto_aead_decrypt(&rctx->fallback_req);
- }
-
- /*
- * CBC algorithms require message lengths to be
- * multiples of block size.
- */
- if (IS_CBC(rctx->flags) && !IS_ALIGNED(rctx->cryptlen, blocksize))
- return -EINVAL;
-
- /* RFC4309 supported AAD size 16 bytes/20 bytes */
- if (IS_CCM_RFC4309(rctx->flags))
- if (crypto_ipsec_check_assoclen(req->assoclen))
- return -EINVAL;
-
- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
-}
-
-static int qce_aead_encrypt(struct aead_request *req)
-{
- return qce_aead_crypt(req, 1);
-}
-
-static int qce_aead_decrypt(struct aead_request *req)
-{
- return qce_aead_crypt(req, 0);
-}
-
-static int qce_aead_ccm_setkey(struct crypto_aead *tfm, const u8 *key,
- unsigned int keylen)
-{
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- unsigned long flags = to_aead_tmpl(tfm)->alg_flags;
-
- if (IS_CCM_RFC4309(flags)) {
- if (keylen < QCE_CCM4309_SALT_SIZE)
- return -EINVAL;
- keylen -= QCE_CCM4309_SALT_SIZE;
- memcpy(ctx->ccm4309_salt, key + keylen, QCE_CCM4309_SALT_SIZE);
- }
-
- if (keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256 && keylen != AES_KEYSIZE_192)
- return -EINVAL;
-
- ctx->enc_keylen = keylen;
- ctx->auth_keylen = keylen;
-
- memcpy(ctx->enc_key, key, keylen);
- memcpy(ctx->auth_key, key, keylen);
-
- if (keylen == AES_KEYSIZE_192)
- ctx->need_fallback = true;
-
- return IS_CCM_RFC4309(flags) ?
- crypto_aead_setkey(ctx->fallback, key, keylen + QCE_CCM4309_SALT_SIZE) :
- crypto_aead_setkey(ctx->fallback, key, keylen);
-}
-
-static int qce_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
-{
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- struct crypto_authenc_keys authenc_keys;
- unsigned long flags = to_aead_tmpl(tfm)->alg_flags;
- u32 _key[6];
- int err;
-
- err = crypto_authenc_extractkeys(&authenc_keys, key, keylen);
- if (err)
- return err;
-
- if (authenc_keys.enckeylen > QCE_MAX_KEY_SIZE ||
- authenc_keys.authkeylen > QCE_MAX_KEY_SIZE)
- return -EINVAL;
-
- if (IS_DES(flags)) {
- err = verify_aead_des_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen);
- if (err)
- return err;
- } else if (IS_3DES(flags)) {
- err = verify_aead_des3_key(tfm, authenc_keys.enckey, authenc_keys.enckeylen);
- if (err)
- return err;
- /*
- * The crypto engine does not support any two keys
- * being the same for triple des algorithms. The
- * verify_skcipher_des3_key does not check for all the
- * below conditions. Schedule fallback in this case.
- */
- memcpy(_key, authenc_keys.enckey, DES3_EDE_KEY_SIZE);
- if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) ||
- !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) ||
- !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5])))
- ctx->need_fallback = true;
- } else if (IS_AES(flags)) {
- /* No random key sizes */
- if (authenc_keys.enckeylen != AES_KEYSIZE_128 &&
- authenc_keys.enckeylen != AES_KEYSIZE_192 &&
- authenc_keys.enckeylen != AES_KEYSIZE_256)
- return -EINVAL;
- if (authenc_keys.enckeylen == AES_KEYSIZE_192)
- ctx->need_fallback = true;
- }
-
- ctx->enc_keylen = authenc_keys.enckeylen;
- ctx->auth_keylen = authenc_keys.authkeylen;
-
- memcpy(ctx->enc_key, authenc_keys.enckey, authenc_keys.enckeylen);
-
- memcpy_and_pad(ctx->auth_key, sizeof(ctx->auth_key),
- authenc_keys.authkey, authenc_keys.authkeylen, 0);
-
- return crypto_aead_setkey(ctx->fallback, key, keylen);
-}
-
-static int qce_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
-{
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
- unsigned long flags = to_aead_tmpl(tfm)->alg_flags;
-
- if (IS_CCM(flags)) {
- if (authsize < 4 || authsize > 16 || authsize % 2)
- return -EINVAL;
- if (IS_CCM_RFC4309(flags) && (authsize < 8 || authsize % 4))
- return -EINVAL;
- }
- ctx->authsize = authsize;
-
- return crypto_aead_setauthsize(ctx->fallback, authsize);
-}
-
-static int qce_aead_init(struct crypto_aead *tfm)
-{
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
-
- ctx->need_fallback = false;
- ctx->fallback = crypto_alloc_aead(crypto_tfm_alg_name(&tfm->base),
- 0, CRYPTO_ALG_NEED_FALLBACK);
-
- if (IS_ERR(ctx->fallback))
- return PTR_ERR(ctx->fallback);
-
- crypto_aead_set_reqsize_dma(tfm, sizeof(struct qce_aead_reqctx) +
- crypto_aead_reqsize(ctx->fallback));
- return 0;
-}
-
-static void qce_aead_exit(struct crypto_aead *tfm)
-{
- struct qce_aead_ctx *ctx = crypto_aead_ctx(tfm);
-
- crypto_free_aead(ctx->fallback);
-}
-
-struct qce_aead_def {
- unsigned long flags;
- const char *name;
- const char *drv_name;
- unsigned int blocksize;
- unsigned int chunksize;
- unsigned int ivsize;
- unsigned int maxauthsize;
-};
-
-static const struct qce_aead_def aead_def[] = {
- {
- .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC,
- .name = "authenc(hmac(sha1),cbc(des))",
- .drv_name = "authenc-hmac-sha1-cbc-des-qce",
- .blocksize = DES_BLOCK_SIZE,
- .ivsize = DES_BLOCK_SIZE,
- .maxauthsize = SHA1_DIGEST_SIZE,
- },
- {
- .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA1_HMAC,
- .name = "authenc(hmac(sha1),cbc(des3_ede))",
- .drv_name = "authenc-hmac-sha1-cbc-3des-qce",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .maxauthsize = SHA1_DIGEST_SIZE,
- },
- {
- .flags = QCE_ALG_DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC,
- .name = "authenc(hmac(sha256),cbc(des))",
- .drv_name = "authenc-hmac-sha256-cbc-des-qce",
- .blocksize = DES_BLOCK_SIZE,
- .ivsize = DES_BLOCK_SIZE,
- .maxauthsize = SHA256_DIGEST_SIZE,
- },
- {
- .flags = QCE_ALG_3DES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC,
- .name = "authenc(hmac(sha256),cbc(des3_ede))",
- .drv_name = "authenc-hmac-sha256-cbc-3des-qce",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .maxauthsize = SHA256_DIGEST_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_CBC | QCE_HASH_SHA256_HMAC,
- .name = "authenc(hmac(sha256),cbc(aes))",
- .drv_name = "authenc-hmac-sha256-cbc-aes-qce",
- .blocksize = AES_BLOCK_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .maxauthsize = SHA256_DIGEST_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_CCM,
- .name = "ccm(aes)",
- .drv_name = "ccm-aes-qce",
- .blocksize = 1,
- .ivsize = AES_BLOCK_SIZE,
- .maxauthsize = AES_BLOCK_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_CCM | QCE_MODE_CCM_RFC4309,
- .name = "rfc4309(ccm(aes))",
- .drv_name = "rfc4309-ccm-aes-qce",
- .blocksize = 1,
- .ivsize = 8,
- .maxauthsize = AES_BLOCK_SIZE,
- },
-};
-
-static int qce_aead_register_one(const struct qce_aead_def *def, struct qce_device *qce)
-{
- struct qce_alg_template *tmpl;
- struct aead_alg *alg;
- int ret;
-
- tmpl = kzalloc_obj(*tmpl);
- if (!tmpl)
- return -ENOMEM;
-
- alg = &tmpl->alg.aead;
-
- strscpy(alg->base.cra_name, def->name);
- strscpy(alg->base.cra_driver_name, def->drv_name);
-
- alg->base.cra_blocksize = def->blocksize;
- alg->chunksize = def->chunksize;
- alg->ivsize = def->ivsize;
- alg->maxauthsize = def->maxauthsize;
- if (IS_CCM(def->flags))
- alg->setkey = qce_aead_ccm_setkey;
- else
- alg->setkey = qce_aead_setkey;
- alg->setauthsize = qce_aead_setauthsize;
- alg->encrypt = qce_aead_encrypt;
- alg->decrypt = qce_aead_decrypt;
- alg->init = qce_aead_init;
- alg->exit = qce_aead_exit;
-
- alg->base.cra_priority = 275;
- alg->base.cra_flags = CRYPTO_ALG_ASYNC |
- CRYPTO_ALG_ALLOCATES_MEMORY |
- CRYPTO_ALG_KERN_DRIVER_ONLY |
- CRYPTO_ALG_NEED_FALLBACK;
- alg->base.cra_ctxsize = sizeof(struct qce_aead_ctx);
- alg->base.cra_alignmask = 0;
- alg->base.cra_module = THIS_MODULE;
-
- INIT_LIST_HEAD(&tmpl->entry);
- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_AEAD;
- tmpl->alg_flags = def->flags;
- tmpl->qce = qce;
-
- ret = crypto_register_aead(alg);
- if (ret) {
- dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name);
- kfree(tmpl);
- return ret;
- }
-
- list_add_tail(&tmpl->entry, &aead_algs);
- dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name);
- return 0;
-}
-
-static void qce_aead_unregister(struct qce_device *qce)
-{
- struct qce_alg_template *tmpl, *n;
-
- list_for_each_entry_safe(tmpl, n, &aead_algs, entry) {
- crypto_unregister_aead(&tmpl->alg.aead);
- list_del(&tmpl->entry);
- kfree(tmpl);
- }
-}
-
-static int qce_aead_register(struct qce_device *qce)
-{
- int ret, i;
-
- for (i = 0; i < ARRAY_SIZE(aead_def); i++) {
- ret = qce_aead_register_one(&aead_def[i], qce);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- qce_aead_unregister(qce);
- return ret;
-}
-
-const struct qce_algo_ops aead_ops = {
- .type = CRYPTO_ALG_TYPE_AEAD,
- .register_algs = qce_aead_register,
- .unregister_algs = qce_aead_unregister,
- .async_req_handle = qce_aead_async_req_handle,
-};
diff --git a/drivers/crypto/qce/aead.h b/drivers/crypto/qce/aead.h
deleted file mode 100644
index efb8477cc088712fe73bf7e700c206b6b9bee8ae..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/aead.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2021, Linaro Limited. All rights reserved.
- */
-
-#ifndef _AEAD_H_
-#define _AEAD_H_
-
-#include "common.h"
-#include "core.h"
-
-#define QCE_MAX_KEY_SIZE 64
-#define QCE_CCM4309_SALT_SIZE 3
-
-struct qce_aead_ctx {
- u8 enc_key[QCE_MAX_KEY_SIZE];
- u8 auth_key[QCE_MAX_KEY_SIZE];
- u8 ccm4309_salt[QCE_CCM4309_SALT_SIZE];
- unsigned int enc_keylen;
- unsigned int auth_keylen;
- unsigned int authsize;
- bool need_fallback;
- struct crypto_aead *fallback;
-};
-
-struct qce_aead_reqctx {
- unsigned long flags;
- u8 *iv;
- unsigned int ivsize;
- int src_nents;
- int dst_nents;
- struct scatterlist result_sg;
- struct scatterlist adata_sg;
- struct sg_table dst_tbl;
- struct sg_table src_tbl;
- struct scatterlist *dst_sg;
- struct scatterlist *src_sg;
- unsigned int cryptlen;
- unsigned int assoclen;
- unsigned char *adata;
- u8 ccm_nonce[QCE_MAX_NONCE];
- u8 ccmresult_buf[QCE_BAM_BURST_SIZE];
- u8 ccm_rfc4309_iv[QCE_MAX_IV_SIZE];
- struct aead_request fallback_req;
-};
-
-static inline struct qce_alg_template *to_aead_tmpl(struct crypto_aead *tfm)
-{
- struct aead_alg *alg = crypto_aead_alg(tfm);
-
- return container_of(alg, struct qce_alg_template, alg.aead);
-}
-
-extern const struct qce_algo_ops aead_ops;
-
-#endif /* _AEAD_H_ */
diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h
deleted file mode 100644
index 850f257d00f3aca0397adc1f703aea690c754d60..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/cipher.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _CIPHER_H_
-#define _CIPHER_H_
-
-#include "common.h"
-#include "core.h"
-
-#define QCE_MAX_KEY_SIZE 64
-
-struct qce_cipher_ctx {
- u8 enc_key[QCE_MAX_KEY_SIZE];
- unsigned int enc_keylen;
- struct crypto_skcipher *fallback;
-};
-
-/**
- * struct qce_cipher_reqctx - holds private cipher objects per request
- * @flags: operation flags
- * @iv: pointer to the IV
- * @ivsize: IV size
- * @src_nents: source entries
- * @dst_nents: destination entries
- * @result_sg: scatterlist used for result buffer
- * @dst_tbl: destination sg table
- * @dst_sg: destination sg pointer table beginning
- * @src_tbl: source sg table
- * @src_sg: source sg pointer table beginning;
- * @cryptlen: crypto length
- */
-struct qce_cipher_reqctx {
- unsigned long flags;
- u8 *iv;
- unsigned int ivsize;
- int src_nents;
- int dst_nents;
- struct scatterlist result_sg;
- struct sg_table dst_tbl;
- struct scatterlist *dst_sg;
- struct scatterlist *src_sg;
- unsigned int cryptlen;
- struct skcipher_request fallback_req; // keep at the end
-};
-
-static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_skcipher *tfm)
-{
- struct skcipher_alg *alg = crypto_skcipher_alg(tfm);
- return container_of(alg, struct qce_alg_template, alg.skcipher);
-}
-
-extern const struct qce_algo_ops skcipher_ops;
-
-#endif /* _CIPHER_H_ */
diff --git a/drivers/crypto/qce/common.c b/drivers/crypto/qce/common.c
deleted file mode 100644
index 54a78a57f63028f01870a3edeb8e390f523bb190..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/common.c
+++ /dev/null
@@ -1,595 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
- */
-
-#include <crypto/internal/hash.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <crypto/scatterwalk.h>
-#include <crypto/sha1.h>
-#include <crypto/sha2.h>
-
-#include "cipher.h"
-#include "common.h"
-#include "core.h"
-#include "regs-v5.h"
-#include "sha.h"
-#include "aead.h"
-
-static inline u32 qce_read(struct qce_device *qce, u32 offset)
-{
- return readl(qce->base + offset);
-}
-
-static inline void qce_write(struct qce_device *qce, u32 offset, u32 val)
-{
- writel(val, qce->base + offset);
-}
-
-static inline void qce_write_array(struct qce_device *qce, u32 offset,
- const u32 *val, unsigned int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- qce_write(qce, offset + i * sizeof(u32), val[i]);
-}
-
-static inline void
-qce_clear_array(struct qce_device *qce, u32 offset, unsigned int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- qce_write(qce, offset + i * sizeof(u32), 0);
-}
-
-static u32 qce_config_reg(struct qce_device *qce, int little)
-{
- u32 beats = (qce->burst_size >> 3) - 1;
- u32 pipe_pair = qce->pipe_pair_id;
- u32 config;
-
- config = (beats << REQ_SIZE_SHIFT) & REQ_SIZE_MASK;
- config |= BIT(MASK_DOUT_INTR_SHIFT) | BIT(MASK_DIN_INTR_SHIFT) |
- BIT(MASK_OP_DONE_INTR_SHIFT) | BIT(MASK_ERR_INTR_SHIFT);
- config |= (pipe_pair << PIPE_SET_SELECT_SHIFT) & PIPE_SET_SELECT_MASK;
- config &= ~HIGH_SPD_EN_N_SHIFT;
-
- if (little)
- config |= BIT(LITTLE_ENDIAN_MODE_SHIFT);
-
- return config;
-}
-
-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len)
-{
- __be32 *d = dst;
- const u8 *s = src;
- unsigned int n;
-
- n = len / sizeof(u32);
- for (; n > 0; n--) {
- *d = cpu_to_be32p((const __u32 *) s);
- s += sizeof(__u32);
- d++;
- }
-}
-
-static void qce_setup_config(struct qce_device *qce)
-{
- u32 config;
-
- /* get big endianness */
- config = qce_config_reg(qce, 0);
-
- /* clear status */
- qce_write(qce, REG_STATUS, 0);
- qce_write(qce, REG_CONFIG, config);
-}
-
-static inline void qce_crypto_go(struct qce_device *qce, bool result_dump)
-{
- if (result_dump)
- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT) | BIT(RESULTS_DUMP_SHIFT));
- else
- qce_write(qce, REG_GOPROC, BIT(GO_SHIFT));
-}
-
-#if defined(CONFIG_CRYPTO_DEV_QCE_SHA) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD)
-static u32 qce_auth_cfg(unsigned long flags, u32 key_size, u32 auth_size)
-{
- u32 cfg = 0;
-
- if (IS_CCM(flags) || IS_CMAC(flags))
- cfg |= AUTH_ALG_AES << AUTH_ALG_SHIFT;
- else
- cfg |= AUTH_ALG_SHA << AUTH_ALG_SHIFT;
-
- if (IS_CCM(flags) || IS_CMAC(flags)) {
- if (key_size == AES_KEYSIZE_128)
- cfg |= AUTH_KEY_SZ_AES128 << AUTH_KEY_SIZE_SHIFT;
- else if (key_size == AES_KEYSIZE_256)
- cfg |= AUTH_KEY_SZ_AES256 << AUTH_KEY_SIZE_SHIFT;
- }
-
- if (IS_SHA1(flags) || IS_SHA1_HMAC(flags))
- cfg |= AUTH_SIZE_SHA1 << AUTH_SIZE_SHIFT;
- else if (IS_SHA256(flags) || IS_SHA256_HMAC(flags))
- cfg |= AUTH_SIZE_SHA256 << AUTH_SIZE_SHIFT;
- else if (IS_CMAC(flags))
- cfg |= AUTH_SIZE_ENUM_16_BYTES << AUTH_SIZE_SHIFT;
- else if (IS_CCM(flags))
- cfg |= (auth_size - 1) << AUTH_SIZE_SHIFT;
-
- if (IS_SHA1(flags) || IS_SHA256(flags))
- cfg |= AUTH_MODE_HASH << AUTH_MODE_SHIFT;
- else if (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags))
- cfg |= AUTH_MODE_HMAC << AUTH_MODE_SHIFT;
- else if (IS_CCM(flags))
- cfg |= AUTH_MODE_CCM << AUTH_MODE_SHIFT;
- else if (IS_CMAC(flags))
- cfg |= AUTH_MODE_CMAC << AUTH_MODE_SHIFT;
-
- if (IS_SHA(flags) || IS_SHA_HMAC(flags))
- cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT;
-
- if (IS_CCM(flags))
- cfg |= QCE_MAX_NONCE_WORDS << AUTH_NONCE_NUM_WORDS_SHIFT;
-
- return cfg;
-}
-#endif
-
-#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
-static int qce_setup_regs_ahash(struct crypto_async_request *async_req)
-{
- struct ahash_request *req = ahash_request_cast(async_req);
- struct crypto_ahash *ahash = __crypto_ahash_cast(async_req->tfm);
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
- struct qce_device *qce = tmpl->qce;
- unsigned int digestsize = crypto_ahash_digestsize(ahash);
- unsigned int blocksize = crypto_tfm_alg_blocksize(async_req->tfm);
- __be32 auth[SHA256_DIGEST_SIZE / sizeof(__be32)] = {0};
- __be32 mackey[QCE_SHA_HMAC_KEY_SIZE / sizeof(__be32)] = {0};
- u32 auth_cfg = 0, config;
- unsigned int iv_words;
-
- /* if not the last, the size has to be on the block boundary */
- if (!rctx->last_blk && req->nbytes % blocksize)
- return -EINVAL;
-
- qce_setup_config(qce);
-
- if (IS_CMAC(rctx->flags)) {
- qce_write(qce, REG_AUTH_SEG_CFG, 0);
- qce_write(qce, REG_ENCR_SEG_CFG, 0);
- qce_write(qce, REG_ENCR_SEG_SIZE, 0);
- qce_clear_array(qce, REG_AUTH_IV0, 16);
- qce_clear_array(qce, REG_AUTH_KEY0, 16);
- qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
-
- auth_cfg = qce_auth_cfg(rctx->flags, rctx->authklen, digestsize);
- }
-
- if (IS_SHA_HMAC(rctx->flags) || IS_CMAC(rctx->flags)) {
- u32 authkey_words = rctx->authklen / sizeof(u32);
-
- qce_cpu_to_be32p_array(mackey, rctx->authkey, rctx->authklen);
- qce_write_array(qce, REG_AUTH_KEY0, (u32 *)mackey,
- authkey_words);
- }
-
- if (IS_CMAC(rctx->flags))
- goto go_proc;
-
- if (rctx->first_blk)
- memcpy(auth, rctx->digest, digestsize);
- else
- qce_cpu_to_be32p_array(auth, rctx->digest, digestsize);
-
- iv_words = (IS_SHA1(rctx->flags) || IS_SHA1_HMAC(rctx->flags)) ? 5 : 8;
- qce_write_array(qce, REG_AUTH_IV0, (u32 *)auth, iv_words);
-
- if (rctx->first_blk)
- qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
- else
- qce_write_array(qce, REG_AUTH_BYTECNT0,
- (u32 *)rctx->byte_count, 2);
-
- auth_cfg = qce_auth_cfg(rctx->flags, 0, digestsize);
-
- if (rctx->last_blk)
- auth_cfg |= BIT(AUTH_LAST_SHIFT);
- else
- auth_cfg &= ~BIT(AUTH_LAST_SHIFT);
-
- if (rctx->first_blk)
- auth_cfg |= BIT(AUTH_FIRST_SHIFT);
- else
- auth_cfg &= ~BIT(AUTH_FIRST_SHIFT);
-
-go_proc:
- qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
- qce_write(qce, REG_AUTH_SEG_SIZE, req->nbytes);
- qce_write(qce, REG_AUTH_SEG_START, 0);
- qce_write(qce, REG_ENCR_SEG_CFG, 0);
- qce_write(qce, REG_SEG_SIZE, req->nbytes);
-
- /* get little endianness */
- config = qce_config_reg(qce, 1);
- qce_write(qce, REG_CONFIG, config);
-
- qce_crypto_go(qce, true);
-
- return 0;
-}
-#endif
-
-#if defined(CONFIG_CRYPTO_DEV_QCE_SKCIPHER) || defined(CONFIG_CRYPTO_DEV_QCE_AEAD)
-static u32 qce_encr_cfg(unsigned long flags, u32 aes_key_size)
-{
- u32 cfg = 0;
-
- if (IS_AES(flags)) {
- if (aes_key_size == AES_KEYSIZE_128)
- cfg |= ENCR_KEY_SZ_AES128 << ENCR_KEY_SZ_SHIFT;
- else if (aes_key_size == AES_KEYSIZE_256)
- cfg |= ENCR_KEY_SZ_AES256 << ENCR_KEY_SZ_SHIFT;
- }
-
- if (IS_AES(flags))
- cfg |= ENCR_ALG_AES << ENCR_ALG_SHIFT;
- else if (IS_DES(flags) || IS_3DES(flags))
- cfg |= ENCR_ALG_DES << ENCR_ALG_SHIFT;
-
- if (IS_DES(flags))
- cfg |= ENCR_KEY_SZ_DES << ENCR_KEY_SZ_SHIFT;
-
- if (IS_3DES(flags))
- cfg |= ENCR_KEY_SZ_3DES << ENCR_KEY_SZ_SHIFT;
-
- switch (flags & QCE_MODE_MASK) {
- case QCE_MODE_ECB:
- cfg |= ENCR_MODE_ECB << ENCR_MODE_SHIFT;
- break;
- case QCE_MODE_CBC:
- cfg |= ENCR_MODE_CBC << ENCR_MODE_SHIFT;
- break;
- case QCE_MODE_CTR:
- cfg |= ENCR_MODE_CTR << ENCR_MODE_SHIFT;
- break;
- case QCE_MODE_XTS:
- cfg |= ENCR_MODE_XTS << ENCR_MODE_SHIFT;
- break;
- case QCE_MODE_CCM:
- cfg |= ENCR_MODE_CCM << ENCR_MODE_SHIFT;
- cfg |= LAST_CCM_XFR << LAST_CCM_SHIFT;
- break;
- default:
- return ~0;
- }
-
- return cfg;
-}
-#endif
-
-#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
-static void qce_xts_swapiv(__be32 *dst, const u8 *src, unsigned int ivsize)
-{
- u8 swap[QCE_AES_IV_LENGTH] = {0};
- unsigned int i, offset;
-
- if (ivsize > QCE_AES_IV_LENGTH)
- return;
-
- offset = QCE_AES_IV_LENGTH - ivsize;
-
- /* Reverse and right-align IV bytes. */
- for (i = 0; i < ivsize; i++)
- swap[offset + i] = src[ivsize - 1 - i];
-
- qce_cpu_to_be32p_array(dst, swap, QCE_AES_IV_LENGTH);
-}
-
-static void qce_xtskey(struct qce_device *qce, const u8 *enckey,
- unsigned int enckeylen, unsigned int cryptlen)
-{
- u32 xtskey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
- unsigned int xtsklen = enckeylen / (2 * sizeof(u32));
-
- qce_cpu_to_be32p_array((__be32 *)xtskey, enckey + enckeylen / 2,
- enckeylen / 2);
- qce_write_array(qce, REG_ENCR_XTS_KEY0, xtskey, xtsklen);
-
- /* Set data unit size to cryptlen. Anything else causes
- * crypto engine to return back incorrect results.
- */
- qce_write(qce, REG_ENCR_XTS_DU_SIZE, cryptlen);
-}
-
-static int qce_setup_regs_skcipher(struct crypto_async_request *async_req)
-{
- struct skcipher_request *req = skcipher_request_cast(async_req);
- struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
- struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- __be32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(__be32)] = {0};
- __be32 enciv[QCE_MAX_IV_SIZE / sizeof(__be32)] = {0};
- unsigned int enckey_words, enciv_words;
- unsigned int keylen;
- u32 encr_cfg = 0, auth_cfg = 0, config;
- unsigned int ivsize = rctx->ivsize;
- unsigned long flags = rctx->flags;
-
- qce_setup_config(qce);
-
- if (IS_XTS(flags))
- keylen = ctx->enc_keylen / 2;
- else
- keylen = ctx->enc_keylen;
-
- qce_cpu_to_be32p_array(enckey, ctx->enc_key, keylen);
- enckey_words = keylen / sizeof(u32);
-
- qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
-
- encr_cfg = qce_encr_cfg(flags, keylen);
-
- if (IS_DES(flags)) {
- enciv_words = 2;
- enckey_words = 2;
- } else if (IS_3DES(flags)) {
- enciv_words = 2;
- enckey_words = 6;
- } else if (IS_AES(flags)) {
- if (IS_XTS(flags))
- qce_xtskey(qce, ctx->enc_key, ctx->enc_keylen,
- rctx->cryptlen);
- enciv_words = 4;
- } else {
- return -EINVAL;
- }
-
- qce_write_array(qce, REG_ENCR_KEY0, (u32 *)enckey, enckey_words);
-
- if (!IS_ECB(flags)) {
- if (IS_XTS(flags))
- qce_xts_swapiv(enciv, rctx->iv, ivsize);
- else
- qce_cpu_to_be32p_array(enciv, rctx->iv, ivsize);
-
- qce_write_array(qce, REG_CNTR0_IV0, (u32 *)enciv, enciv_words);
- }
-
- if (IS_ENCRYPT(flags))
- encr_cfg |= BIT(ENCODE_SHIFT);
-
- qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg);
- qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen);
- qce_write(qce, REG_ENCR_SEG_START, 0);
-
- if (IS_CTR(flags)) {
- qce_write(qce, REG_CNTR_MASK, ~0);
- qce_write(qce, REG_CNTR_MASK0, ~0);
- qce_write(qce, REG_CNTR_MASK1, ~0);
- qce_write(qce, REG_CNTR_MASK2, ~0);
- }
-
- qce_write(qce, REG_SEG_SIZE, rctx->cryptlen);
-
- /* get little endianness */
- config = qce_config_reg(qce, 1);
- qce_write(qce, REG_CONFIG, config);
-
- qce_crypto_go(qce, true);
-
- return 0;
-}
-#endif
-
-#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD
-static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = {
- SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0
-};
-
-static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = {
- SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
- SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7
-};
-
-static unsigned int qce_be32_to_cpu_array(u32 *dst, const u8 *src, unsigned int len)
-{
- u32 *d = dst;
- const u8 *s = src;
- unsigned int n;
-
- n = len / sizeof(u32);
- for (; n > 0; n--) {
- *d = be32_to_cpup((const __be32 *)s);
- s += sizeof(u32);
- d++;
- }
- return DIV_ROUND_UP(len, sizeof(u32));
-}
-
-static int qce_setup_regs_aead(struct crypto_async_request *async_req)
-{
- struct aead_request *req = aead_request_cast(async_req);
- struct qce_aead_reqctx *rctx = aead_request_ctx_dma(req);
- struct qce_aead_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
- struct qce_alg_template *tmpl = to_aead_tmpl(crypto_aead_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- u32 enckey[QCE_MAX_CIPHER_KEY_SIZE / sizeof(u32)] = {0};
- u32 enciv[QCE_MAX_IV_SIZE / sizeof(u32)] = {0};
- u32 authkey[QCE_SHA_HMAC_KEY_SIZE / sizeof(u32)] = {0};
- u32 authiv[SHA256_DIGEST_SIZE / sizeof(u32)] = {0};
- u32 authnonce[QCE_MAX_NONCE / sizeof(u32)] = {0};
- unsigned int enc_keylen = ctx->enc_keylen;
- unsigned int auth_keylen = ctx->auth_keylen;
- unsigned int enc_ivsize = rctx->ivsize;
- unsigned int auth_ivsize = 0;
- unsigned int enckey_words, enciv_words;
- unsigned int authkey_words, authiv_words, authnonce_words;
- unsigned long flags = rctx->flags;
- u32 encr_cfg, auth_cfg, config, totallen;
- u32 iv_last_word;
-
- qce_setup_config(qce);
-
- /* Write encryption key */
- enckey_words = qce_be32_to_cpu_array(enckey, ctx->enc_key, enc_keylen);
- qce_write_array(qce, REG_ENCR_KEY0, enckey, enckey_words);
-
- /* Write encryption iv */
- enciv_words = qce_be32_to_cpu_array(enciv, rctx->iv, enc_ivsize);
- qce_write_array(qce, REG_CNTR0_IV0, enciv, enciv_words);
-
- if (IS_CCM(rctx->flags)) {
- iv_last_word = enciv[enciv_words - 1];
- qce_write(qce, REG_CNTR3_IV3, iv_last_word + 1);
- qce_write_array(qce, REG_ENCR_CCM_INT_CNTR0, (u32 *)enciv, enciv_words);
- qce_write(qce, REG_CNTR_MASK, ~0);
- qce_write(qce, REG_CNTR_MASK0, ~0);
- qce_write(qce, REG_CNTR_MASK1, ~0);
- qce_write(qce, REG_CNTR_MASK2, ~0);
- }
-
- /* Clear authentication IV and KEY registers of previous values */
- qce_clear_array(qce, REG_AUTH_IV0, 16);
- qce_clear_array(qce, REG_AUTH_KEY0, 16);
-
- /* Clear byte count */
- qce_clear_array(qce, REG_AUTH_BYTECNT0, 4);
-
- /* Write authentication key */
- authkey_words = qce_be32_to_cpu_array(authkey, ctx->auth_key, auth_keylen);
- qce_write_array(qce, REG_AUTH_KEY0, (u32 *)authkey, authkey_words);
-
- /* Write initial authentication IV only for HMAC algorithms */
- if (IS_SHA_HMAC(rctx->flags)) {
- /* Write default authentication iv */
- if (IS_SHA1_HMAC(rctx->flags)) {
- auth_ivsize = SHA1_DIGEST_SIZE;
- memcpy(authiv, std_iv_sha1, auth_ivsize);
- } else if (IS_SHA256_HMAC(rctx->flags)) {
- auth_ivsize = SHA256_DIGEST_SIZE;
- memcpy(authiv, std_iv_sha256, auth_ivsize);
- }
- authiv_words = auth_ivsize / sizeof(u32);
- qce_write_array(qce, REG_AUTH_IV0, (u32 *)authiv, authiv_words);
- } else if (IS_CCM(rctx->flags)) {
- /* Write nonce for CCM algorithms */
- authnonce_words = qce_be32_to_cpu_array(authnonce, rctx->ccm_nonce, QCE_MAX_NONCE);
- qce_write_array(qce, REG_AUTH_INFO_NONCE0, authnonce, authnonce_words);
- }
-
- /* Set up ENCR_SEG_CFG */
- encr_cfg = qce_encr_cfg(flags, enc_keylen);
- if (IS_ENCRYPT(flags))
- encr_cfg |= BIT(ENCODE_SHIFT);
- qce_write(qce, REG_ENCR_SEG_CFG, encr_cfg);
-
- /* Set up AUTH_SEG_CFG */
- auth_cfg = qce_auth_cfg(rctx->flags, auth_keylen, ctx->authsize);
- auth_cfg |= BIT(AUTH_LAST_SHIFT);
- auth_cfg |= BIT(AUTH_FIRST_SHIFT);
- if (IS_ENCRYPT(flags)) {
- if (IS_CCM(rctx->flags))
- auth_cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT;
- else
- auth_cfg |= AUTH_POS_AFTER << AUTH_POS_SHIFT;
- } else {
- if (IS_CCM(rctx->flags))
- auth_cfg |= AUTH_POS_AFTER << AUTH_POS_SHIFT;
- else
- auth_cfg |= AUTH_POS_BEFORE << AUTH_POS_SHIFT;
- }
- qce_write(qce, REG_AUTH_SEG_CFG, auth_cfg);
-
- totallen = rctx->cryptlen + rctx->assoclen;
-
- /* Set the encryption size and start offset */
- if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags))
- qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen + ctx->authsize);
- else
- qce_write(qce, REG_ENCR_SEG_SIZE, rctx->cryptlen);
- qce_write(qce, REG_ENCR_SEG_START, rctx->assoclen & 0xffff);
-
- /* Set the authentication size and start offset */
- qce_write(qce, REG_AUTH_SEG_SIZE, totallen);
- qce_write(qce, REG_AUTH_SEG_START, 0);
-
- /* Write total length */
- if (IS_CCM(rctx->flags) && IS_DECRYPT(rctx->flags))
- qce_write(qce, REG_SEG_SIZE, totallen + ctx->authsize);
- else
- qce_write(qce, REG_SEG_SIZE, totallen);
-
- /* get little endianness */
- config = qce_config_reg(qce, 1);
- qce_write(qce, REG_CONFIG, config);
-
- /* Start the process */
- qce_crypto_go(qce, !IS_CCM(flags));
-
- return 0;
-}
-#endif
-
-int qce_start(struct crypto_async_request *async_req, u32 type)
-{
- switch (type) {
-#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
- case CRYPTO_ALG_TYPE_SKCIPHER:
- return qce_setup_regs_skcipher(async_req);
-#endif
-#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
- case CRYPTO_ALG_TYPE_AHASH:
- return qce_setup_regs_ahash(async_req);
-#endif
-#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD
- case CRYPTO_ALG_TYPE_AEAD:
- return qce_setup_regs_aead(async_req);
-#endif
- default:
- return -EINVAL;
- }
-}
-
-#define STATUS_ERRORS \
- (BIT(SW_ERR_SHIFT) | BIT(AXI_ERR_SHIFT) | BIT(HSD_ERR_SHIFT))
-
-int qce_check_status(struct qce_device *qce, u32 *status)
-{
- int ret = 0;
-
- *status = qce_read(qce, REG_STATUS);
-
- /*
- * Don't use result dump status. The operation may not be complete.
- * Instead, use the status we just read from device. In case, we need to
- * use result_status from result dump the result_status needs to be byte
- * swapped, since we set the device to little endian.
- */
- if (*status & STATUS_ERRORS || !(*status & BIT(OPERATION_DONE_SHIFT)))
- ret = -ENXIO;
- else if (*status & BIT(MAC_FAILED_SHIFT))
- ret = -EBADMSG;
-
- return ret;
-}
-
-void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step)
-{
- u32 val;
-
- val = qce_read(qce, REG_VERSION);
- *major = (val & CORE_MAJOR_REV_MASK) >> CORE_MAJOR_REV_SHIFT;
- *minor = (val & CORE_MINOR_REV_MASK) >> CORE_MINOR_REV_SHIFT;
- *step = (val & CORE_STEP_REV_MASK) >> CORE_STEP_REV_SHIFT;
-}
diff --git a/drivers/crypto/qce/common.h b/drivers/crypto/qce/common.h
deleted file mode 100644
index 02e63ad9f24557c2238caa70b0ec521d49da4f13..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/common.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _COMMON_H_
-#define _COMMON_H_
-
-#include <linux/crypto.h>
-#include <linux/types.h>
-#include <crypto/aes.h>
-#include <crypto/hash.h>
-#include <crypto/internal/skcipher.h>
-#include <crypto/internal/aead.h>
-
-/* xts du size */
-#define QCE_SECTOR_SIZE 512
-
-/* key size in bytes */
-#define QCE_SHA_HMAC_KEY_SIZE 64
-#define QCE_MAX_CIPHER_KEY_SIZE AES_KEYSIZE_256
-
-/* IV length in bytes */
-#define QCE_AES_IV_LENGTH AES_BLOCK_SIZE
-/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
-#define QCE_MAX_IV_SIZE AES_BLOCK_SIZE
-
-/* maximum nonce bytes */
-#define QCE_MAX_NONCE 16
-#define QCE_MAX_NONCE_WORDS (QCE_MAX_NONCE / sizeof(u32))
-
-/* burst size alignment requirement */
-#define QCE_MAX_ALIGN_SIZE 64
-
-/* cipher algorithms */
-#define QCE_ALG_DES BIT(0)
-#define QCE_ALG_3DES BIT(1)
-#define QCE_ALG_AES BIT(2)
-
-/* hash and hmac algorithms */
-#define QCE_HASH_SHA1 BIT(3)
-#define QCE_HASH_SHA256 BIT(4)
-#define QCE_HASH_SHA1_HMAC BIT(5)
-#define QCE_HASH_SHA256_HMAC BIT(6)
-#define QCE_HASH_AES_CMAC BIT(7)
-
-/* cipher modes */
-#define QCE_MODE_CBC BIT(8)
-#define QCE_MODE_ECB BIT(9)
-#define QCE_MODE_CTR BIT(10)
-#define QCE_MODE_XTS BIT(11)
-#define QCE_MODE_CCM BIT(12)
-#define QCE_MODE_MASK GENMASK(12, 8)
-
-#define QCE_MODE_CCM_RFC4309 BIT(13)
-
-/* cipher encryption/decryption operations */
-#define QCE_ENCRYPT BIT(30)
-#define QCE_DECRYPT BIT(31)
-
-#define IS_DES(flags) (flags & QCE_ALG_DES)
-#define IS_3DES(flags) (flags & QCE_ALG_3DES)
-#define IS_AES(flags) (flags & QCE_ALG_AES)
-
-#define IS_SHA1(flags) (flags & QCE_HASH_SHA1)
-#define IS_SHA256(flags) (flags & QCE_HASH_SHA256)
-#define IS_SHA1_HMAC(flags) (flags & QCE_HASH_SHA1_HMAC)
-#define IS_SHA256_HMAC(flags) (flags & QCE_HASH_SHA256_HMAC)
-#define IS_CMAC(flags) (flags & QCE_HASH_AES_CMAC)
-#define IS_SHA(flags) (IS_SHA1(flags) || IS_SHA256(flags))
-#define IS_SHA_HMAC(flags) \
- (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags))
-
-#define IS_CBC(mode) (mode & QCE_MODE_CBC)
-#define IS_ECB(mode) (mode & QCE_MODE_ECB)
-#define IS_CTR(mode) (mode & QCE_MODE_CTR)
-#define IS_XTS(mode) (mode & QCE_MODE_XTS)
-#define IS_CCM(mode) (mode & QCE_MODE_CCM)
-#define IS_CCM_RFC4309(mode) ((mode) & QCE_MODE_CCM_RFC4309)
-
-#define IS_ENCRYPT(dir) (dir & QCE_ENCRYPT)
-#define IS_DECRYPT(dir) (dir & QCE_DECRYPT)
-
-struct qce_alg_template {
- struct list_head entry;
- u32 crypto_alg_type;
- unsigned long alg_flags;
- const u32 *std_iv;
- union {
- struct skcipher_alg skcipher;
- struct ahash_alg ahash;
- struct aead_alg aead;
- } alg;
- struct qce_device *qce;
- const u8 *hash_zero;
- const u32 digest_size;
-};
-
-void qce_cpu_to_be32p_array(__be32 *dst, const u8 *src, unsigned int len);
-int qce_check_status(struct qce_device *qce, u32 *status);
-void qce_get_version(struct qce_device *qce, u32 *major, u32 *minor, u32 *step);
-int qce_start(struct crypto_async_request *async_req, u32 type);
-
-#endif /* _COMMON_H_ */
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
deleted file mode 100644
index b966f3365b7de8d2a8f6707397a34aa4facdc4ac..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/core.c
+++ /dev/null
@@ -1,271 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/cleanup.h>
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/interconnect.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <crypto/algapi.h>
-#include <crypto/internal/hash.h>
-
-#include "core.h"
-#include "cipher.h"
-#include "sha.h"
-#include "aead.h"
-
-#define QCE_QUEUE_LENGTH 1
-
-#define QCE_DEFAULT_MEM_BANDWIDTH 393600
-
-static const struct qce_algo_ops *qce_ops[] = {
-#ifdef CONFIG_CRYPTO_DEV_QCE_SKCIPHER
- &skcipher_ops,
-#endif
-#ifdef CONFIG_CRYPTO_DEV_QCE_SHA
- &ahash_ops,
-#endif
-#ifdef CONFIG_CRYPTO_DEV_QCE_AEAD
- &aead_ops,
-#endif
-};
-
-static void qce_unregister_algs(void *data)
-{
- const struct qce_algo_ops *ops;
- struct qce_device *qce = data;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
- ops = qce_ops[i];
- ops->unregister_algs(qce);
- }
-}
-
-static int devm_qce_register_algs(struct qce_device *qce)
-{
- const struct qce_algo_ops *ops;
- int i, j, ret = -ENODEV;
-
- for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
- ops = qce_ops[i];
- ret = ops->register_algs(qce);
- if (ret) {
- for (j = i - 1; j >= 0; j--)
- ops->unregister_algs(qce);
- return ret;
- }
- }
-
- return devm_add_action_or_reset(qce->dev, qce_unregister_algs, qce);
-}
-
-static int qce_handle_request(struct crypto_async_request *async_req)
-{
- int ret = -EINVAL, i;
- const struct qce_algo_ops *ops;
- u32 type = crypto_tfm_alg_type(async_req->tfm);
-
- for (i = 0; i < ARRAY_SIZE(qce_ops); i++) {
- ops = qce_ops[i];
- if (type != ops->type)
- continue;
- ret = ops->async_req_handle(async_req);
- break;
- }
-
- return ret;
-}
-
-static int qce_handle_queue(struct qce_device *qce,
- struct crypto_async_request *req)
-{
- struct crypto_async_request *async_req, *backlog;
- int ret = 0, err;
-
- scoped_guard(mutex, &qce->lock) {
- if (req)
- ret = crypto_enqueue_request(&qce->queue, req);
-
- /* busy, do not dequeue request */
- if (qce->req)
- return ret;
-
- backlog = crypto_get_backlog(&qce->queue);
- async_req = crypto_dequeue_request(&qce->queue);
- if (async_req)
- qce->req = async_req;
- }
-
- if (!async_req)
- return ret;
-
- if (backlog) {
- scoped_guard(mutex, &qce->lock)
- crypto_request_complete(backlog, -EINPROGRESS);
- }
-
- err = qce_handle_request(async_req);
- if (err) {
- qce->result = err;
- schedule_work(&qce->done_work);
- }
-
- return ret;
-}
-
-static void qce_req_done_work(struct work_struct *work)
-{
- struct qce_device *qce = container_of(work, struct qce_device,
- done_work);
- struct crypto_async_request *req;
-
- scoped_guard(mutex, &qce->lock) {
- req = qce->req;
- qce->req = NULL;
- }
-
- if (req)
- crypto_request_complete(req, qce->result);
-
- qce_handle_queue(qce, NULL);
-}
-
-static int qce_async_request_enqueue(struct qce_device *qce,
- struct crypto_async_request *req)
-{
- return qce_handle_queue(qce, req);
-}
-
-static void qce_async_request_done(struct qce_device *qce, int ret)
-{
- qce->result = ret;
- schedule_work(&qce->done_work);
-}
-
-static int qce_check_version(struct qce_device *qce)
-{
- u32 major, minor, step;
-
- qce_get_version(qce, &major, &minor, &step);
-
- /*
- * the driver does not support v5 with minor 0 because it has special
- * alignment requirements.
- */
- if (major == 5 && minor == 0)
- return -ENODEV;
-
- qce->burst_size = QCE_BAM_BURST_SIZE;
-
- /*
- * Rx and tx pipes are treated as a pair inside CE.
- * Pipe pair number depends on the actual BAM dma pipe
- * that is used for transfers. The BAM dma pipes are passed
- * from the device tree and used to derive the pipe pair
- * id in the CE driver as follows.
- * BAM dma pipes(rx, tx) CE pipe pair id
- * 0,1 0
- * 2,3 1
- * 4,5 2
- * 6,7 3
- * ...
- */
- qce->pipe_pair_id = qce->dma.rxchan->chan_id >> 1;
-
- dev_dbg(qce->dev, "Crypto device found, version %d.%d.%d\n",
- major, minor, step);
-
- return 0;
-}
-
-static int qce_crypto_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct qce_device *qce;
- int ret;
-
- qce = devm_kzalloc(dev, sizeof(*qce), GFP_KERNEL);
- if (!qce)
- return -ENOMEM;
-
- qce->dev = dev;
- platform_set_drvdata(pdev, qce);
-
- qce->base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(qce->base))
- return PTR_ERR(qce->base);
-
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
- if (ret < 0)
- return ret;
-
- qce->core = devm_clk_get_optional_enabled(qce->dev, "core");
- if (IS_ERR(qce->core))
- return PTR_ERR(qce->core);
-
- qce->iface = devm_clk_get_optional_enabled(qce->dev, "iface");
- if (IS_ERR(qce->iface))
- return PTR_ERR(qce->iface);
-
- qce->bus = devm_clk_get_optional_enabled(qce->dev, "bus");
- if (IS_ERR(qce->bus))
- return PTR_ERR(qce->bus);
-
- qce->mem_path = devm_of_icc_get(qce->dev, "memory");
- if (IS_ERR(qce->mem_path))
- return PTR_ERR(qce->mem_path);
-
- ret = icc_set_bw(qce->mem_path, QCE_DEFAULT_MEM_BANDWIDTH, QCE_DEFAULT_MEM_BANDWIDTH);
- if (ret)
- return ret;
-
- ret = devm_qce_dma_request(qce->dev, &qce->dma);
- if (ret)
- return ret;
-
- ret = qce_check_version(qce);
- if (ret)
- return ret;
-
- ret = devm_mutex_init(qce->dev, &qce->lock);
- if (ret)
- return ret;
-
- INIT_WORK(&qce->done_work, qce_req_done_work);
- crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
-
- qce->async_req_enqueue = qce_async_request_enqueue;
- qce->async_req_done = qce_async_request_done;
-
- return devm_qce_register_algs(qce);
-}
-
-static const struct of_device_id qce_crypto_of_match[] = {
- { .compatible = "qcom,crypto-v5.1", },
- { .compatible = "qcom,crypto-v5.4", },
- { .compatible = "qcom,qce", },
- {}
-};
-MODULE_DEVICE_TABLE(of, qce_crypto_of_match);
-
-static struct platform_driver qce_crypto_driver = {
- .probe = qce_crypto_probe,
- .driver = {
- .name = KBUILD_MODNAME,
- .of_match_table = qce_crypto_of_match,
- },
-};
-module_platform_driver(qce_crypto_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Qualcomm crypto engine driver");
-MODULE_ALIAS("platform:" KBUILD_MODNAME);
-MODULE_AUTHOR("The Linux Foundation");
diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h
deleted file mode 100644
index eb6fa7a8b64a81daf9ad5304a3ae4e5e597a70b8..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/core.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _CORE_H_
-#define _CORE_H_
-
-#include <linux/mutex.h>
-#include <linux/workqueue.h>
-
-#include "dma.h"
-
-/**
- * struct qce_device - crypto engine device structure
- * @queue: crypto request queue
- * @lock: the lock protects queue and req
- * @done_work: workqueue context
- * @req: current active request
- * @result: result of current transform
- * @base: virtual IO base
- * @dev: pointer to device structure
- * @core: core device clock
- * @iface: interface clock
- * @bus: bus clock
- * @dma: pointer to dma data
- * @burst_size: the crypto burst size
- * @pipe_pair_id: which pipe pair id the device using
- * @async_req_enqueue: invoked by every algorithm to enqueue a request
- * @async_req_done: invoked by every algorithm to finish its request
- */
-struct qce_device {
- struct crypto_queue queue;
- struct mutex lock;
- struct work_struct done_work;
- struct crypto_async_request *req;
- int result;
- void __iomem *base;
- struct device *dev;
- struct clk *core, *iface, *bus;
- struct icc_path *mem_path;
- struct qce_dma_data dma;
- int burst_size;
- unsigned int pipe_pair_id;
- int (*async_req_enqueue)(struct qce_device *qce,
- struct crypto_async_request *req);
- void (*async_req_done)(struct qce_device *qce, int ret);
-};
-
-/**
- * struct qce_algo_ops - algorithm operations per crypto type
- * @type: should be CRYPTO_ALG_TYPE_XXX
- * @register_algs: invoked by core to register the algorithms
- * @unregister_algs: invoked by core to unregister the algorithms
- * @async_req_handle: invoked by core to handle enqueued request
- */
-struct qce_algo_ops {
- u32 type;
- int (*register_algs)(struct qce_device *qce);
- void (*unregister_algs)(struct qce_device *qce);
- int (*async_req_handle)(struct crypto_async_request *async_req);
-};
-
-#endif /* _CORE_H_ */
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
deleted file mode 100644
index 68cafd4741ad3d91906d39e817fc7873b028d498..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/dma.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <crypto/scatterwalk.h>
-
-#include "dma.h"
-
-static void qce_dma_release(void *data)
-{
- struct qce_dma_data *dma = data;
-
- dma_release_channel(dma->txchan);
- dma_release_channel(dma->rxchan);
- kfree(dma->result_buf);
-}
-
-int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma)
-{
- int ret;
-
- dma->txchan = dma_request_chan(dev, "tx");
- if (IS_ERR(dma->txchan))
- return dev_err_probe(dev, PTR_ERR(dma->txchan),
- "Failed to get TX DMA channel\n");
-
- dma->rxchan = dma_request_chan(dev, "rx");
- if (IS_ERR(dma->rxchan)) {
- ret = dev_err_probe(dev, PTR_ERR(dma->rxchan),
- "Failed to get RX DMA channel\n");
- goto error_rx;
- }
-
- dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ,
- GFP_KERNEL);
- if (!dma->result_buf) {
- ret = -ENOMEM;
- goto error_nomem;
- }
-
- dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ;
-
- return devm_add_action_or_reset(dev, qce_dma_release, dma);
-
-error_nomem:
- dma_release_channel(dma->rxchan);
-error_rx:
- dma_release_channel(dma->txchan);
- return ret;
-}
-
-struct scatterlist *
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *new_sgl,
- unsigned int max_len)
-{
- struct scatterlist *sg = sgt->sgl, *sg_last = NULL;
- unsigned int new_len;
-
- while (sg) {
- if (!sg_page(sg))
- break;
- sg = sg_next(sg);
- }
-
- if (!sg)
- return ERR_PTR(-EINVAL);
-
- while (new_sgl && sg && max_len) {
- new_len = new_sgl->length > max_len ? max_len : new_sgl->length;
- sg_set_page(sg, sg_page(new_sgl), new_len, new_sgl->offset);
- sg_last = sg;
- sg = sg_next(sg);
- new_sgl = sg_next(new_sgl);
- max_len -= new_len;
- }
-
- return sg_last;
-}
-
-static int qce_dma_prep_sg(struct dma_chan *chan, struct scatterlist *sg,
- int nents, unsigned long flags,
- enum dma_transfer_direction dir,
- dma_async_tx_callback cb, void *cb_param)
-{
- struct dma_async_tx_descriptor *desc;
- dma_cookie_t cookie;
-
- if (!sg || !nents)
- return -EINVAL;
-
- desc = dmaengine_prep_slave_sg(chan, sg, nents, dir, flags);
- if (!desc)
- return -EINVAL;
-
- desc->callback = cb;
- desc->callback_param = cb_param;
- cookie = dmaengine_submit(desc);
-
- return dma_submit_error(cookie);
-}
-
-int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *rx_sg,
- int rx_nents, struct scatterlist *tx_sg, int tx_nents,
- dma_async_tx_callback cb, void *cb_param)
-{
- struct dma_chan *rxchan = dma->rxchan;
- struct dma_chan *txchan = dma->txchan;
- unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
- int ret;
-
- ret = qce_dma_prep_sg(rxchan, rx_sg, rx_nents, flags, DMA_MEM_TO_DEV,
- NULL, NULL);
- if (ret)
- return ret;
-
- return qce_dma_prep_sg(txchan, tx_sg, tx_nents, flags, DMA_DEV_TO_MEM,
- cb, cb_param);
-}
-
-void qce_dma_issue_pending(struct qce_dma_data *dma)
-{
- dma_async_issue_pending(dma->rxchan);
- dma_async_issue_pending(dma->txchan);
-}
-
-int qce_dma_terminate_all(struct qce_dma_data *dma)
-{
- int ret;
-
- ret = dmaengine_terminate_all(dma->rxchan);
- return ret ?: dmaengine_terminate_all(dma->txchan);
-}
diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h
deleted file mode 100644
index 31629185000e12242fa07c2cc08b95fcbd5d4b8c..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/dma.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _DMA_H_
-#define _DMA_H_
-
-#include <linux/dmaengine.h>
-
-/* maximum data transfer block size between BAM and CE */
-#define QCE_BAM_BURST_SIZE 64
-
-#define QCE_AUTHIV_REGS_CNT 16
-#define QCE_AUTH_BYTECOUNT_REGS_CNT 4
-#define QCE_CNTRIV_REGS_CNT 4
-
-struct qce_result_dump {
- u32 auth_iv[QCE_AUTHIV_REGS_CNT];
- u32 auth_byte_count[QCE_AUTH_BYTECOUNT_REGS_CNT];
- u32 encr_cntr_iv[QCE_CNTRIV_REGS_CNT];
- u32 status;
- u32 status2;
-};
-
-#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
-#define QCE_RESULT_BUF_SZ \
- ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE)
-
-struct qce_dma_data {
- struct dma_chan *txchan;
- struct dma_chan *rxchan;
- struct qce_result_dump *result_buf;
- void *ignore_buf;
-};
-
-int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma);
-int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in,
- int in_ents, struct scatterlist *sg_out, int out_ents,
- dma_async_tx_callback cb, void *cb_param);
-void qce_dma_issue_pending(struct qce_dma_data *dma);
-int qce_dma_terminate_all(struct qce_dma_data *dma);
-struct scatterlist *
-qce_sgtable_add(struct sg_table *sgt, struct scatterlist *sg_add,
- unsigned int max_len);
-
-#endif /* _DMA_H_ */
diff --git a/drivers/crypto/qce/regs-v5.h b/drivers/crypto/qce/regs-v5.h
deleted file mode 100644
index d59ed279890621a8e2e6f4cdb20692dbf39f1461..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/regs-v5.h
+++ /dev/null
@@ -1,326 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _REGS_V5_H_
-#define _REGS_V5_H_
-
-#include <linux/bitops.h>
-
-#define REG_VERSION 0x000
-#define REG_STATUS 0x100
-#define REG_STATUS2 0x104
-#define REG_ENGINES_AVAIL 0x108
-#define REG_FIFO_SIZES 0x10c
-#define REG_SEG_SIZE 0x110
-#define REG_GOPROC 0x120
-#define REG_ENCR_SEG_CFG 0x200
-#define REG_ENCR_SEG_SIZE 0x204
-#define REG_ENCR_SEG_START 0x208
-#define REG_CNTR0_IV0 0x20c
-#define REG_CNTR1_IV1 0x210
-#define REG_CNTR2_IV2 0x214
-#define REG_CNTR3_IV3 0x218
-#define REG_CNTR_MASK 0x21C
-#define REG_ENCR_CCM_INT_CNTR0 0x220
-#define REG_ENCR_CCM_INT_CNTR1 0x224
-#define REG_ENCR_CCM_INT_CNTR2 0x228
-#define REG_ENCR_CCM_INT_CNTR3 0x22c
-#define REG_ENCR_XTS_DU_SIZE 0x230
-#define REG_CNTR_MASK2 0x234
-#define REG_CNTR_MASK1 0x238
-#define REG_CNTR_MASK0 0x23c
-#define REG_AUTH_SEG_CFG 0x300
-#define REG_AUTH_SEG_SIZE 0x304
-#define REG_AUTH_SEG_START 0x308
-#define REG_AUTH_IV0 0x310
-#define REG_AUTH_IV1 0x314
-#define REG_AUTH_IV2 0x318
-#define REG_AUTH_IV3 0x31c
-#define REG_AUTH_IV4 0x320
-#define REG_AUTH_IV5 0x324
-#define REG_AUTH_IV6 0x328
-#define REG_AUTH_IV7 0x32c
-#define REG_AUTH_IV8 0x330
-#define REG_AUTH_IV9 0x334
-#define REG_AUTH_IV10 0x338
-#define REG_AUTH_IV11 0x33c
-#define REG_AUTH_IV12 0x340
-#define REG_AUTH_IV13 0x344
-#define REG_AUTH_IV14 0x348
-#define REG_AUTH_IV15 0x34c
-#define REG_AUTH_INFO_NONCE0 0x350
-#define REG_AUTH_INFO_NONCE1 0x354
-#define REG_AUTH_INFO_NONCE2 0x358
-#define REG_AUTH_INFO_NONCE3 0x35c
-#define REG_AUTH_BYTECNT0 0x390
-#define REG_AUTH_BYTECNT1 0x394
-#define REG_AUTH_BYTECNT2 0x398
-#define REG_AUTH_BYTECNT3 0x39c
-#define REG_AUTH_EXP_MAC0 0x3a0
-#define REG_AUTH_EXP_MAC1 0x3a4
-#define REG_AUTH_EXP_MAC2 0x3a8
-#define REG_AUTH_EXP_MAC3 0x3ac
-#define REG_AUTH_EXP_MAC4 0x3b0
-#define REG_AUTH_EXP_MAC5 0x3b4
-#define REG_AUTH_EXP_MAC6 0x3b8
-#define REG_AUTH_EXP_MAC7 0x3bc
-#define REG_CONFIG 0x400
-#define REG_GOPROC_QC_KEY 0x1000
-#define REG_GOPROC_OEM_KEY 0x2000
-#define REG_ENCR_KEY0 0x3000
-#define REG_ENCR_KEY1 0x3004
-#define REG_ENCR_KEY2 0x3008
-#define REG_ENCR_KEY3 0x300c
-#define REG_ENCR_KEY4 0x3010
-#define REG_ENCR_KEY5 0x3014
-#define REG_ENCR_KEY6 0x3018
-#define REG_ENCR_KEY7 0x301c
-#define REG_ENCR_XTS_KEY0 0x3020
-#define REG_ENCR_XTS_KEY1 0x3024
-#define REG_ENCR_XTS_KEY2 0x3028
-#define REG_ENCR_XTS_KEY3 0x302c
-#define REG_ENCR_XTS_KEY4 0x3030
-#define REG_ENCR_XTS_KEY5 0x3034
-#define REG_ENCR_XTS_KEY6 0x3038
-#define REG_ENCR_XTS_KEY7 0x303c
-#define REG_AUTH_KEY0 0x3040
-#define REG_AUTH_KEY1 0x3044
-#define REG_AUTH_KEY2 0x3048
-#define REG_AUTH_KEY3 0x304c
-#define REG_AUTH_KEY4 0x3050
-#define REG_AUTH_KEY5 0x3054
-#define REG_AUTH_KEY6 0x3058
-#define REG_AUTH_KEY7 0x305c
-#define REG_AUTH_KEY8 0x3060
-#define REG_AUTH_KEY9 0x3064
-#define REG_AUTH_KEY10 0x3068
-#define REG_AUTH_KEY11 0x306c
-#define REG_AUTH_KEY12 0x3070
-#define REG_AUTH_KEY13 0x3074
-#define REG_AUTH_KEY14 0x3078
-#define REG_AUTH_KEY15 0x307c
-
-/* Register bits - REG_VERSION */
-#define CORE_STEP_REV_SHIFT 0
-#define CORE_STEP_REV_MASK GENMASK(15, 0)
-#define CORE_MINOR_REV_SHIFT 16
-#define CORE_MINOR_REV_MASK GENMASK(23, 16)
-#define CORE_MAJOR_REV_SHIFT 24
-#define CORE_MAJOR_REV_MASK GENMASK(31, 24)
-
-/* Register bits - REG_STATUS */
-#define MAC_FAILED_SHIFT 31
-#define DOUT_SIZE_AVAIL_SHIFT 26
-#define DOUT_SIZE_AVAIL_MASK GENMASK(30, 26)
-#define DIN_SIZE_AVAIL_SHIFT 21
-#define DIN_SIZE_AVAIL_MASK GENMASK(25, 21)
-#define HSD_ERR_SHIFT 20
-#define ACCESS_VIOL_SHIFT 19
-#define PIPE_ACTIVE_ERR_SHIFT 18
-#define CFG_CHNG_ERR_SHIFT 17
-#define DOUT_ERR_SHIFT 16
-#define DIN_ERR_SHIFT 15
-#define AXI_ERR_SHIFT 14
-#define CRYPTO_STATE_SHIFT 10
-#define CRYPTO_STATE_MASK GENMASK(13, 10)
-#define ENCR_BUSY_SHIFT 9
-#define AUTH_BUSY_SHIFT 8
-#define DOUT_INTR_SHIFT 7
-#define DIN_INTR_SHIFT 6
-#define OP_DONE_INTR_SHIFT 5
-#define ERR_INTR_SHIFT 4
-#define DOUT_RDY_SHIFT 3
-#define DIN_RDY_SHIFT 2
-#define OPERATION_DONE_SHIFT 1
-#define SW_ERR_SHIFT 0
-
-/* Register bits - REG_STATUS2 */
-#define AXI_EXTRA_SHIFT 1
-#define LOCKED_SHIFT 2
-
-/* Register bits - REG_CONFIG */
-#define REQ_SIZE_SHIFT 17
-#define REQ_SIZE_MASK GENMASK(20, 17)
-#define REQ_SIZE_ENUM_1_BEAT 0
-#define REQ_SIZE_ENUM_2_BEAT 1
-#define REQ_SIZE_ENUM_3_BEAT 2
-#define REQ_SIZE_ENUM_4_BEAT 3
-#define REQ_SIZE_ENUM_5_BEAT 4
-#define REQ_SIZE_ENUM_6_BEAT 5
-#define REQ_SIZE_ENUM_7_BEAT 6
-#define REQ_SIZE_ENUM_8_BEAT 7
-#define REQ_SIZE_ENUM_9_BEAT 8
-#define REQ_SIZE_ENUM_10_BEAT 9
-#define REQ_SIZE_ENUM_11_BEAT 10
-#define REQ_SIZE_ENUM_12_BEAT 11
-#define REQ_SIZE_ENUM_13_BEAT 12
-#define REQ_SIZE_ENUM_14_BEAT 13
-#define REQ_SIZE_ENUM_15_BEAT 14
-#define REQ_SIZE_ENUM_16_BEAT 15
-
-#define MAX_QUEUED_REQ_SHIFT 14
-#define MAX_QUEUED_REQ_MASK GENMASK(24, 16)
-#define ENUM_1_QUEUED_REQS 0
-#define ENUM_2_QUEUED_REQS 1
-#define ENUM_3_QUEUED_REQS 2
-
-#define IRQ_ENABLES_SHIFT 10
-#define IRQ_ENABLES_MASK GENMASK(13, 10)
-
-#define LITTLE_ENDIAN_MODE_SHIFT 9
-#define PIPE_SET_SELECT_SHIFT 5
-#define PIPE_SET_SELECT_MASK GENMASK(8, 5)
-
-#define HIGH_SPD_EN_N_SHIFT 4
-#define MASK_DOUT_INTR_SHIFT 3
-#define MASK_DIN_INTR_SHIFT 2
-#define MASK_OP_DONE_INTR_SHIFT 1
-#define MASK_ERR_INTR_SHIFT 0
-
-/* Register bits - REG_AUTH_SEG_CFG */
-#define COMP_EXP_MAC_SHIFT 24
-#define COMP_EXP_MAC_DISABLED 0
-#define COMP_EXP_MAC_ENABLED 1
-
-#define F9_DIRECTION_SHIFT 23
-#define F9_DIRECTION_UPLINK 0
-#define F9_DIRECTION_DOWNLINK 1
-
-#define AUTH_NONCE_NUM_WORDS_SHIFT 20
-#define AUTH_NONCE_NUM_WORDS_MASK GENMASK(22, 20)
-
-#define USE_PIPE_KEY_AUTH_SHIFT 19
-#define USE_HW_KEY_AUTH_SHIFT 18
-#define AUTH_FIRST_SHIFT 17
-#define AUTH_LAST_SHIFT 16
-
-#define AUTH_POS_SHIFT 14
-#define AUTH_POS_MASK GENMASK(15, 14)
-#define AUTH_POS_BEFORE 0
-#define AUTH_POS_AFTER 1
-
-#define AUTH_SIZE_SHIFT 9
-#define AUTH_SIZE_MASK GENMASK(13, 9)
-#define AUTH_SIZE_SHA1 0
-#define AUTH_SIZE_SHA256 1
-#define AUTH_SIZE_ENUM_1_BYTES 0
-#define AUTH_SIZE_ENUM_2_BYTES 1
-#define AUTH_SIZE_ENUM_3_BYTES 2
-#define AUTH_SIZE_ENUM_4_BYTES 3
-#define AUTH_SIZE_ENUM_5_BYTES 4
-#define AUTH_SIZE_ENUM_6_BYTES 5
-#define AUTH_SIZE_ENUM_7_BYTES 6
-#define AUTH_SIZE_ENUM_8_BYTES 7
-#define AUTH_SIZE_ENUM_9_BYTES 8
-#define AUTH_SIZE_ENUM_10_BYTES 9
-#define AUTH_SIZE_ENUM_11_BYTES 10
-#define AUTH_SIZE_ENUM_12_BYTES 11
-#define AUTH_SIZE_ENUM_13_BYTES 12
-#define AUTH_SIZE_ENUM_14_BYTES 13
-#define AUTH_SIZE_ENUM_15_BYTES 14
-#define AUTH_SIZE_ENUM_16_BYTES 15
-
-#define AUTH_MODE_SHIFT 6
-#define AUTH_MODE_MASK GENMASK(8, 6)
-#define AUTH_MODE_HASH 0
-#define AUTH_MODE_HMAC 1
-#define AUTH_MODE_CCM 0
-#define AUTH_MODE_CMAC 1
-
-#define AUTH_KEY_SIZE_SHIFT 3
-#define AUTH_KEY_SIZE_MASK GENMASK(5, 3)
-#define AUTH_KEY_SZ_AES128 0
-#define AUTH_KEY_SZ_AES256 2
-
-#define AUTH_ALG_SHIFT 0
-#define AUTH_ALG_MASK GENMASK(2, 0)
-#define AUTH_ALG_NONE 0
-#define AUTH_ALG_SHA 1
-#define AUTH_ALG_AES 2
-#define AUTH_ALG_KASUMI 3
-#define AUTH_ALG_SNOW3G 4
-#define AUTH_ALG_ZUC 5
-
-/* Register bits - REG_ENCR_XTS_DU_SIZE */
-#define ENCR_XTS_DU_SIZE_SHIFT 0
-#define ENCR_XTS_DU_SIZE_MASK GENMASK(19, 0)
-
-/* Register bits - REG_ENCR_SEG_CFG */
-#define F8_KEYSTREAM_ENABLE_SHIFT 17
-#define F8_KEYSTREAM_DISABLED 0
-#define F8_KEYSTREAM_ENABLED 1
-
-#define F8_DIRECTION_SHIFT 16
-#define F8_DIRECTION_UPLINK 0
-#define F8_DIRECTION_DOWNLINK 1
-
-#define USE_PIPE_KEY_ENCR_SHIFT 15
-#define USE_PIPE_KEY_ENCR_ENABLED 1
-#define USE_KEY_REGISTERS 0
-
-#define USE_HW_KEY_ENCR_SHIFT 14
-#define USE_KEY_REG 0
-#define USE_HW_KEY 1
-
-#define LAST_CCM_SHIFT 13
-#define LAST_CCM_XFR 1
-#define INTERM_CCM_XFR 0
-
-#define CNTR_ALG_SHIFT 11
-#define CNTR_ALG_MASK GENMASK(12, 11)
-#define CNTR_ALG_NIST 0
-
-#define ENCODE_SHIFT 10
-
-#define ENCR_MODE_SHIFT 6
-#define ENCR_MODE_MASK GENMASK(9, 6)
-#define ENCR_MODE_ECB 0
-#define ENCR_MODE_CBC 1
-#define ENCR_MODE_CTR 2
-#define ENCR_MODE_XTS 3
-#define ENCR_MODE_CCM 4
-
-#define ENCR_KEY_SZ_SHIFT 3
-#define ENCR_KEY_SZ_MASK GENMASK(5, 3)
-#define ENCR_KEY_SZ_DES 0
-#define ENCR_KEY_SZ_3DES 1
-#define ENCR_KEY_SZ_AES128 0
-#define ENCR_KEY_SZ_AES256 2
-
-#define ENCR_ALG_SHIFT 0
-#define ENCR_ALG_MASK GENMASK(2, 0)
-#define ENCR_ALG_NONE 0
-#define ENCR_ALG_DES 1
-#define ENCR_ALG_AES 2
-#define ENCR_ALG_KASUMI 4
-#define ENCR_ALG_SNOW_3G 5
-#define ENCR_ALG_ZUC 6
-
-/* Register bits - REG_GOPROC */
-#define GO_SHIFT 0
-#define CLR_CNTXT_SHIFT 1
-#define RESULTS_DUMP_SHIFT 2
-
-/* Register bits - REG_ENGINES_AVAIL */
-#define ENCR_AES_SEL_SHIFT 0
-#define DES_SEL_SHIFT 1
-#define ENCR_SNOW3G_SEL_SHIFT 2
-#define ENCR_KASUMI_SEL_SHIFT 3
-#define SHA_SEL_SHIFT 4
-#define SHA512_SEL_SHIFT 5
-#define AUTH_AES_SEL_SHIFT 6
-#define AUTH_SNOW3G_SEL_SHIFT 7
-#define AUTH_KASUMI_SEL_SHIFT 8
-#define BAM_PIPE_SETS_SHIFT 9
-#define BAM_PIPE_SETS_MASK GENMASK(12, 9)
-#define AXI_WR_BEATS_SHIFT 13
-#define AXI_WR_BEATS_MASK GENMASK(18, 13)
-#define AXI_RD_BEATS_SHIFT 19
-#define AXI_RD_BEATS_MASK GENMASK(24, 19)
-#define ENCR_ZUC_SEL_SHIFT 26
-#define AUTH_ZUC_SEL_SHIFT 27
-#define ZUC_ENABLE_SHIFT 28
-
-#endif /* _REGS_V5_H_ */
diff --git a/drivers/crypto/qce/sha.c b/drivers/crypto/qce/sha.c
deleted file mode 100644
index 1b37121cbcdcb70ea02cc8b9cbbd6f03abb79851..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/sha.c
+++ /dev/null
@@ -1,545 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-#include <crypto/internal/hash.h>
-
-#include "common.h"
-#include "core.h"
-#include "sha.h"
-
-struct qce_sha_saved_state {
- u8 pending_buf[QCE_SHA_MAX_BLOCKSIZE];
- u8 partial_digest[QCE_SHA_MAX_DIGESTSIZE];
- __be32 byte_count[2];
- unsigned int pending_buflen;
- unsigned int flags;
- u64 count;
- bool first_blk;
-};
-
-static LIST_HEAD(ahash_algs);
-
-static const u32 std_iv_sha1[SHA256_DIGEST_SIZE / sizeof(u32)] = {
- SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4, 0, 0, 0
-};
-
-static const u32 std_iv_sha256[SHA256_DIGEST_SIZE / sizeof(u32)] = {
- SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
- SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7
-};
-
-static void qce_ahash_done(void *data)
-{
- struct crypto_async_request *async_req = data;
- struct ahash_request *req = ahash_request_cast(async_req);
- struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
- struct qce_device *qce = tmpl->qce;
- struct qce_result_dump *result = qce->dma.result_buf;
- unsigned int digestsize = crypto_ahash_digestsize(ahash);
- int error;
- u32 status;
-
- error = qce_dma_terminate_all(&qce->dma);
- if (error)
- dev_dbg(qce->dev, "ahash dma termination error (%d)\n", error);
-
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
- dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
-
- memcpy(rctx->digest, result->auth_iv, digestsize);
- if (req->result && rctx->last_blk)
- memcpy(req->result, result->auth_iv, digestsize);
-
- rctx->byte_count[0] = cpu_to_be32(result->auth_byte_count[0]);
- rctx->byte_count[1] = cpu_to_be32(result->auth_byte_count[1]);
-
- error = qce_check_status(qce, &status);
- if (error < 0)
- dev_dbg(qce->dev, "ahash operation error (%x)\n", status);
-
- req->src = rctx->src_orig;
- req->nbytes = rctx->nbytes_orig;
- rctx->last_blk = false;
- rctx->first_blk = false;
-
- qce->async_req_done(tmpl->qce, error);
-}
-
-static int qce_ahash_async_req_handle(struct crypto_async_request *async_req)
-{
- struct ahash_request *req = ahash_request_cast(async_req);
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_sha_ctx *ctx = crypto_tfm_ctx(async_req->tfm);
- struct qce_alg_template *tmpl = to_ahash_tmpl(async_req->tfm);
- struct qce_device *qce = tmpl->qce;
- unsigned long flags = rctx->flags;
- int ret;
-
- if (IS_SHA_HMAC(flags)) {
- rctx->authkey = ctx->authkey;
- rctx->authklen = QCE_SHA_HMAC_KEY_SIZE;
- } else if (IS_CMAC(flags)) {
- rctx->authkey = ctx->authkey;
- rctx->authklen = AES_KEYSIZE_128;
- }
-
- rctx->src_nents = sg_nents_for_len(req->src, req->nbytes);
- if (rctx->src_nents < 0) {
- dev_err(qce->dev, "Invalid numbers of src SG.\n");
- return rctx->src_nents;
- }
-
- ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
- if (!ret)
- return -EIO;
-
- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
-
- ret = dma_map_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
- if (!ret) {
- ret = -EIO;
- goto error_unmap_src;
- }
-
- ret = qce_dma_prep_sgs(&qce->dma, req->src, rctx->src_nents,
- &rctx->result_sg, 1, qce_ahash_done, async_req);
- if (ret)
- goto error_unmap_dst;
-
- qce_dma_issue_pending(&qce->dma);
-
- ret = qce_start(async_req, tmpl->crypto_alg_type);
- if (ret)
- goto error_terminate;
-
- return 0;
-
-error_terminate:
- qce_dma_terminate_all(&qce->dma);
-error_unmap_dst:
- dma_unmap_sg(qce->dev, &rctx->result_sg, 1, DMA_FROM_DEVICE);
-error_unmap_src:
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, DMA_TO_DEVICE);
- return ret;
-}
-
-static int qce_ahash_init(struct ahash_request *req)
-{
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
- const u32 *std_iv = tmpl->std_iv;
-
- memset(rctx, 0, sizeof(*rctx));
- rctx->first_blk = true;
- rctx->last_blk = false;
- rctx->flags = tmpl->alg_flags;
- memcpy(rctx->digest, std_iv, sizeof(rctx->digest));
-
- return 0;
-}
-
-static int qce_ahash_export(struct ahash_request *req, void *out)
-{
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_sha_saved_state *export_state = out;
-
- memcpy(export_state->pending_buf, rctx->buf, rctx->buflen);
- memcpy(export_state->partial_digest, rctx->digest, sizeof(rctx->digest));
- export_state->byte_count[0] = rctx->byte_count[0];
- export_state->byte_count[1] = rctx->byte_count[1];
- export_state->pending_buflen = rctx->buflen;
- export_state->count = rctx->count;
- export_state->first_blk = rctx->first_blk;
- export_state->flags = rctx->flags;
-
- return 0;
-}
-
-static int qce_ahash_import(struct ahash_request *req, const void *in)
-{
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- const struct qce_sha_saved_state *import_state = in;
-
- memset(rctx, 0, sizeof(*rctx));
- rctx->count = import_state->count;
- rctx->buflen = import_state->pending_buflen;
- rctx->first_blk = import_state->first_blk;
- rctx->flags = import_state->flags;
- rctx->byte_count[0] = import_state->byte_count[0];
- rctx->byte_count[1] = import_state->byte_count[1];
- memcpy(rctx->buf, import_state->pending_buf, rctx->buflen);
- memcpy(rctx->digest, import_state->partial_digest, sizeof(rctx->digest));
-
- return 0;
-}
-
-static int qce_ahash_update(struct ahash_request *req)
-{
- struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
- struct qce_device *qce = tmpl->qce;
- struct scatterlist *sg_last, *sg;
- unsigned int total, len;
- unsigned int hash_later;
- unsigned int nbytes;
- unsigned int blocksize;
-
- blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
- rctx->count += req->nbytes;
-
- /* check for buffer from previous updates and append it */
- total = req->nbytes + rctx->buflen;
-
- if (total <= blocksize) {
- scatterwalk_map_and_copy(rctx->buf + rctx->buflen, req->src,
- 0, req->nbytes, 0);
- rctx->buflen += req->nbytes;
- return 0;
- }
-
- /* save the original req structure fields */
- rctx->src_orig = req->src;
- rctx->nbytes_orig = req->nbytes;
-
- /*
- * if we have data from previous update copy them on buffer. The old
- * data will be combined with current request bytes.
- */
- if (rctx->buflen)
- memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
-
- /* calculate how many bytes will be hashed later */
- hash_later = total % blocksize;
-
- /*
- * At this point, there is more than one block size of data. If
- * the available data to transfer is exactly a multiple of block
- * size, save the last block to be transferred in qce_ahash_final
- * (with the last block bit set) if this is indeed the end of data
- * stream. If not this saved block will be transferred as part of
- * next update. If this block is not held back and if this is
- * indeed the end of data stream, the digest obtained will be wrong
- * since qce_ahash_final will see that rctx->buflen is 0 and return
- * doing nothing which in turn means that a digest will not be
- * copied to the destination result buffer. qce_ahash_final cannot
- * be made to alter this behavior and allowed to proceed if
- * rctx->buflen is 0 because the crypto engine BAM does not allow
- * for zero length transfers.
- */
- if (!hash_later)
- hash_later = blocksize;
-
- if (hash_later) {
- unsigned int src_offset = req->nbytes - hash_later;
- scatterwalk_map_and_copy(rctx->buf, req->src, src_offset,
- hash_later, 0);
- }
-
- /* here nbytes is multiple of blocksize */
- nbytes = total - hash_later;
-
- len = rctx->buflen;
- sg = sg_last = req->src;
-
- while (len < nbytes && sg) {
- if (len + sg_dma_len(sg) > nbytes)
- break;
- len += sg_dma_len(sg);
- sg_last = sg;
- sg = sg_next(sg);
- }
-
- if (!sg_last)
- return -EINVAL;
-
- if (rctx->buflen) {
- sg_init_table(rctx->sg, 2);
- sg_set_buf(rctx->sg, rctx->tmpbuf, rctx->buflen);
- sg_chain(rctx->sg, 2, req->src);
- req->src = rctx->sg;
- }
-
- req->nbytes = nbytes;
- rctx->buflen = hash_later;
-
- return qce->async_req_enqueue(tmpl->qce, &req->base);
-}
-
-static int qce_ahash_final(struct ahash_request *req)
-{
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
- struct qce_device *qce = tmpl->qce;
-
- if (!rctx->buflen) {
- if (tmpl->hash_zero)
- memcpy(req->result, tmpl->hash_zero,
- tmpl->alg.ahash.halg.digestsize);
- return 0;
- }
-
- rctx->last_blk = true;
-
- rctx->src_orig = req->src;
- rctx->nbytes_orig = req->nbytes;
-
- memcpy(rctx->tmpbuf, rctx->buf, rctx->buflen);
- sg_init_one(rctx->sg, rctx->tmpbuf, rctx->buflen);
-
- req->src = rctx->sg;
- req->nbytes = rctx->buflen;
-
- return qce->async_req_enqueue(tmpl->qce, &req->base);
-}
-
-static int qce_ahash_digest(struct ahash_request *req)
-{
- struct qce_sha_reqctx *rctx = ahash_request_ctx_dma(req);
- struct qce_alg_template *tmpl = to_ahash_tmpl(req->base.tfm);
- struct qce_device *qce = tmpl->qce;
- int ret;
-
- ret = qce_ahash_init(req);
- if (ret)
- return ret;
-
- rctx->src_orig = req->src;
- rctx->nbytes_orig = req->nbytes;
- rctx->first_blk = true;
- rctx->last_blk = true;
-
- if (!rctx->nbytes_orig) {
- if (tmpl->hash_zero)
- memcpy(req->result, tmpl->hash_zero,
- tmpl->alg.ahash.halg.digestsize);
- return 0;
- }
-
- return qce->async_req_enqueue(tmpl->qce, &req->base);
-}
-
-static int qce_ahash_hmac_setkey(struct crypto_ahash *tfm, const u8 *key,
- unsigned int keylen)
-{
- unsigned int digestsize = crypto_ahash_digestsize(tfm);
- struct qce_sha_ctx *ctx = crypto_tfm_ctx(&tfm->base);
- struct crypto_wait wait;
- struct ahash_request *req;
- struct scatterlist sg;
- unsigned int blocksize;
- struct crypto_ahash *ahash_tfm;
- u8 *buf;
- int ret;
- const char *alg_name;
-
- blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
- memset(ctx->authkey, 0, sizeof(ctx->authkey));
-
- if (keylen <= blocksize) {
- memcpy(ctx->authkey, key, keylen);
- return 0;
- }
-
- if (digestsize == SHA1_DIGEST_SIZE)
- alg_name = "sha1-qce";
- else if (digestsize == SHA256_DIGEST_SIZE)
- alg_name = "sha256-qce";
- else
- return -EINVAL;
-
- ahash_tfm = crypto_alloc_ahash(alg_name, 0, 0);
- if (IS_ERR(ahash_tfm))
- return PTR_ERR(ahash_tfm);
-
- req = ahash_request_alloc(ahash_tfm, GFP_KERNEL);
- if (!req) {
- ret = -ENOMEM;
- goto err_free_ahash;
- }
-
- crypto_init_wait(&wait);
- ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- crypto_req_done, &wait);
- crypto_ahash_clear_flags(ahash_tfm, ~0);
-
- buf = kzalloc(keylen + QCE_MAX_ALIGN_SIZE, GFP_KERNEL);
- if (!buf) {
- ret = -ENOMEM;
- goto err_free_req;
- }
-
- memcpy(buf, key, keylen);
- sg_init_one(&sg, buf, keylen);
- ahash_request_set_crypt(req, &sg, ctx->authkey, keylen);
-
- ret = crypto_wait_req(crypto_ahash_digest(req), &wait);
-
- kfree(buf);
-err_free_req:
- ahash_request_free(req);
-err_free_ahash:
- crypto_free_ahash(ahash_tfm);
- return ret;
-}
-
-static int qce_ahash_cra_init(struct crypto_tfm *tfm)
-{
- struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
- struct qce_sha_ctx *ctx = crypto_tfm_ctx(tfm);
-
- crypto_ahash_set_reqsize_dma(ahash, sizeof(struct qce_sha_reqctx));
- memset(ctx, 0, sizeof(*ctx));
- return 0;
-}
-
-struct qce_ahash_def {
- unsigned long flags;
- const char *name;
- const char *drv_name;
- unsigned int digestsize;
- unsigned int blocksize;
- unsigned int statesize;
- const u32 *std_iv;
-};
-
-static const struct qce_ahash_def ahash_def[] = {
- {
- .flags = QCE_HASH_SHA1,
- .name = "sha1",
- .drv_name = "sha1-qce",
- .digestsize = SHA1_DIGEST_SIZE,
- .blocksize = SHA1_BLOCK_SIZE,
- .statesize = sizeof(struct qce_sha_saved_state),
- .std_iv = std_iv_sha1,
- },
- {
- .flags = QCE_HASH_SHA256,
- .name = "sha256",
- .drv_name = "sha256-qce",
- .digestsize = SHA256_DIGEST_SIZE,
- .blocksize = SHA256_BLOCK_SIZE,
- .statesize = sizeof(struct qce_sha_saved_state),
- .std_iv = std_iv_sha256,
- },
- {
- .flags = QCE_HASH_SHA1_HMAC,
- .name = "hmac(sha1)",
- .drv_name = "hmac-sha1-qce",
- .digestsize = SHA1_DIGEST_SIZE,
- .blocksize = SHA1_BLOCK_SIZE,
- .statesize = sizeof(struct qce_sha_saved_state),
- .std_iv = std_iv_sha1,
- },
- {
- .flags = QCE_HASH_SHA256_HMAC,
- .name = "hmac(sha256)",
- .drv_name = "hmac-sha256-qce",
- .digestsize = SHA256_DIGEST_SIZE,
- .blocksize = SHA256_BLOCK_SIZE,
- .statesize = sizeof(struct qce_sha_saved_state),
- .std_iv = std_iv_sha256,
- },
-};
-
-static int qce_ahash_register_one(const struct qce_ahash_def *def,
- struct qce_device *qce)
-{
- struct qce_alg_template *tmpl;
- struct ahash_alg *alg;
- struct crypto_alg *base;
- int ret;
-
- tmpl = kzalloc_obj(*tmpl);
- if (!tmpl)
- return -ENOMEM;
-
- tmpl->std_iv = def->std_iv;
-
- alg = &tmpl->alg.ahash;
- alg->init = qce_ahash_init;
- alg->update = qce_ahash_update;
- alg->final = qce_ahash_final;
- alg->digest = qce_ahash_digest;
- alg->export = qce_ahash_export;
- alg->import = qce_ahash_import;
- if (IS_SHA_HMAC(def->flags))
- alg->setkey = qce_ahash_hmac_setkey;
- alg->halg.digestsize = def->digestsize;
- alg->halg.statesize = def->statesize;
-
- if (IS_SHA1(def->flags))
- tmpl->hash_zero = sha1_zero_message_hash;
- else if (IS_SHA256(def->flags))
- tmpl->hash_zero = sha256_zero_message_hash;
-
- base = &alg->halg.base;
- base->cra_blocksize = def->blocksize;
- base->cra_priority = 175;
- base->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
- base->cra_ctxsize = sizeof(struct qce_sha_ctx);
- base->cra_alignmask = 0;
- base->cra_module = THIS_MODULE;
- base->cra_init = qce_ahash_cra_init;
-
- strscpy(base->cra_name, def->name);
- strscpy(base->cra_driver_name, def->drv_name);
-
- INIT_LIST_HEAD(&tmpl->entry);
- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_AHASH;
- tmpl->alg_flags = def->flags;
- tmpl->qce = qce;
-
- ret = crypto_register_ahash(alg);
- if (ret) {
- dev_err(qce->dev, "%s registration failed\n", base->cra_name);
- kfree(tmpl);
- return ret;
- }
-
- list_add_tail(&tmpl->entry, &ahash_algs);
- dev_dbg(qce->dev, "%s is registered\n", base->cra_name);
- return 0;
-}
-
-static void qce_ahash_unregister(struct qce_device *qce)
-{
- struct qce_alg_template *tmpl, *n;
-
- list_for_each_entry_safe(tmpl, n, &ahash_algs, entry) {
- crypto_unregister_ahash(&tmpl->alg.ahash);
- list_del(&tmpl->entry);
- kfree(tmpl);
- }
-}
-
-static int qce_ahash_register(struct qce_device *qce)
-{
- int ret, i;
-
- for (i = 0; i < ARRAY_SIZE(ahash_def); i++) {
- ret = qce_ahash_register_one(&ahash_def[i], qce);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- qce_ahash_unregister(qce);
- return ret;
-}
-
-const struct qce_algo_ops ahash_ops = {
- .type = CRYPTO_ALG_TYPE_AHASH,
- .register_algs = qce_ahash_register,
- .unregister_algs = qce_ahash_unregister,
- .async_req_handle = qce_ahash_async_req_handle,
-};
diff --git a/drivers/crypto/qce/sha.h b/drivers/crypto/qce/sha.h
deleted file mode 100644
index a22695361f1654cc94325ec5d886a158fa4bfb9c..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/sha.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#ifndef _SHA_H_
-#define _SHA_H_
-
-#include <crypto/scatterwalk.h>
-#include <crypto/sha1.h>
-#include <crypto/sha2.h>
-
-#include "common.h"
-#include "core.h"
-
-#define QCE_SHA_MAX_BLOCKSIZE SHA256_BLOCK_SIZE
-#define QCE_SHA_MAX_DIGESTSIZE SHA256_DIGEST_SIZE
-
-struct qce_sha_ctx {
- u8 authkey[QCE_SHA_MAX_BLOCKSIZE];
-};
-
-/**
- * struct qce_sha_reqctx - holds private ahash objects per request
- * @buf: used during update, import and export
- * @tmpbuf: buffer for internal use
- * @digest: calculated digest buffer
- * @buflen: length of the buffer
- * @flags: operation flags
- * @src_orig: original request sg list
- * @nbytes_orig: original request number of bytes
- * @src_nents: source number of entries
- * @byte_count: byte count
- * @count: save count in states during update, import and export
- * @first_blk: is it the first block
- * @last_blk: is it the last block
- * @sg: used to chain sg lists
- * @authkey: pointer to auth key in sha ctx
- * @authklen: auth key length
- * @result_sg: scatterlist used for result buffer
- */
-struct qce_sha_reqctx {
- u8 buf[QCE_SHA_MAX_BLOCKSIZE];
- u8 tmpbuf[QCE_SHA_MAX_BLOCKSIZE];
- u8 digest[QCE_SHA_MAX_DIGESTSIZE];
- unsigned int buflen;
- unsigned long flags;
- struct scatterlist *src_orig;
- unsigned int nbytes_orig;
- int src_nents;
- __be32 byte_count[2];
- u64 count;
- bool first_blk;
- bool last_blk;
- struct scatterlist sg[2];
- u8 *authkey;
- unsigned int authklen;
- struct scatterlist result_sg;
-};
-
-static inline struct qce_alg_template *to_ahash_tmpl(struct crypto_tfm *tfm)
-{
- struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
- struct ahash_alg *alg = container_of(crypto_hash_alg_common(ahash),
- struct ahash_alg, halg);
-
- return container_of(alg, struct qce_alg_template, alg.ahash);
-}
-
-extern const struct qce_algo_ops ahash_ops;
-
-#endif /* _SHA_H_ */
diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c
deleted file mode 100644
index db0b648a56eb1adb2e50285468112d051649aa9e..0000000000000000000000000000000000000000
--- a/drivers/crypto/qce/skcipher.c
+++ /dev/null
@@ -1,529 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
- */
-
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <crypto/aes.h>
-#include <crypto/internal/des.h>
-#include <crypto/internal/skcipher.h>
-
-#include "cipher.h"
-
-static unsigned int aes_sw_max_len = CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN;
-module_param(aes_sw_max_len, uint, 0644);
-MODULE_PARM_DESC(aes_sw_max_len,
- "Only use hardware for AES requests larger than this "
- "[0=always use hardware; anything <16 breaks AES-GCM; default="
- __stringify(CONFIG_CRYPTO_DEV_QCE_SW_MAX_LEN)"]");
-
-static LIST_HEAD(skcipher_algs);
-
-static void qce_skcipher_done(void *data)
-{
- struct crypto_async_request *async_req = data;
- struct skcipher_request *req = skcipher_request_cast(async_req);
- struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
- struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- struct qce_result_dump *result_buf = qce->dma.result_buf;
- enum dma_data_direction dir_src, dir_dst;
- u32 status;
- int error;
- bool diff_dst;
-
- diff_dst = (req->src != req->dst) ? true : false;
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
-
- error = qce_dma_terminate_all(&qce->dma);
- if (error)
- dev_dbg(qce->dev, "skcipher dma termination error (%d)\n",
- error);
-
- if (diff_dst)
- dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
-
- sg_free_table(&rctx->dst_tbl);
-
- error = qce_check_status(qce, &status);
- if (error < 0)
- dev_dbg(qce->dev, "skcipher operation error (%x)\n", status);
-
- memcpy(rctx->iv, result_buf->encr_cntr_iv, rctx->ivsize);
- qce->async_req_done(tmpl->qce, error);
-}
-
-static int
-qce_skcipher_async_req_handle(struct crypto_async_request *async_req)
-{
- struct skcipher_request *req = skcipher_request_cast(async_req);
- struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
- struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req);
- struct qce_alg_template *tmpl = to_cipher_tmpl(crypto_skcipher_reqtfm(req));
- struct qce_device *qce = tmpl->qce;
- enum dma_data_direction dir_src, dir_dst;
- struct scatterlist *sg;
- bool diff_dst;
- gfp_t gfp;
- int dst_nents, src_nents, ret;
-
- rctx->iv = req->iv;
- rctx->ivsize = crypto_skcipher_ivsize(skcipher);
- rctx->cryptlen = req->cryptlen;
-
- diff_dst = (req->src != req->dst) ? true : false;
- dir_src = diff_dst ? DMA_TO_DEVICE : DMA_BIDIRECTIONAL;
- dir_dst = diff_dst ? DMA_FROM_DEVICE : DMA_BIDIRECTIONAL;
-
- rctx->src_nents = sg_nents_for_len(req->src, req->cryptlen);
- if (diff_dst)
- rctx->dst_nents = sg_nents_for_len(req->dst, req->cryptlen);
- else
- rctx->dst_nents = rctx->src_nents;
- if (rctx->src_nents < 0) {
- dev_err(qce->dev, "Invalid numbers of src SG.\n");
- return rctx->src_nents;
- }
- if (rctx->dst_nents < 0) {
- dev_err(qce->dev, "Invalid numbers of dst SG.\n");
- return -rctx->dst_nents;
- }
-
- rctx->dst_nents += 1;
-
- gfp = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
- GFP_KERNEL : GFP_ATOMIC;
-
- ret = sg_alloc_table(&rctx->dst_tbl, rctx->dst_nents, gfp);
- if (ret)
- return ret;
-
- sg_init_one(&rctx->result_sg, qce->dma.result_buf, QCE_RESULT_BUF_SZ);
-
- sg = qce_sgtable_add(&rctx->dst_tbl, req->dst, req->cryptlen);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto error_free;
- }
-
- sg = qce_sgtable_add(&rctx->dst_tbl, &rctx->result_sg,
- QCE_RESULT_BUF_SZ);
- if (IS_ERR(sg)) {
- ret = PTR_ERR(sg);
- goto error_free;
- }
-
- sg_mark_end(sg);
- rctx->dst_sg = rctx->dst_tbl.sgl;
-
- dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
- if (!dst_nents) {
- ret = -EIO;
- goto error_free;
- }
-
- if (diff_dst) {
- src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src);
- if (!src_nents) {
- ret = -EIO;
- goto error_unmap_dst;
- }
- rctx->src_sg = req->src;
- } else {
- rctx->src_sg = rctx->dst_sg;
- src_nents = dst_nents - 1;
- }
-
- ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents,
- rctx->dst_sg, dst_nents,
- qce_skcipher_done, async_req);
- if (ret)
- goto error_unmap_src;
-
- qce_dma_issue_pending(&qce->dma);
-
- ret = qce_start(async_req, tmpl->crypto_alg_type);
- if (ret)
- goto error_terminate;
-
- return 0;
-
-error_terminate:
- qce_dma_terminate_all(&qce->dma);
-error_unmap_src:
- if (diff_dst)
- dma_unmap_sg(qce->dev, req->src, rctx->src_nents, dir_src);
-error_unmap_dst:
- dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
-error_free:
- sg_free_table(&rctx->dst_tbl);
- return ret;
-}
-
-static int qce_skcipher_setkey(struct crypto_skcipher *ablk, const u8 *key,
- unsigned int keylen)
-{
- struct crypto_tfm *tfm = crypto_skcipher_tfm(ablk);
- struct qce_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
- unsigned long flags = to_cipher_tmpl(ablk)->alg_flags;
- unsigned int __keylen;
- int ret;
-
- if (!key || !keylen)
- return -EINVAL;
-
- /*
- * AES XTS key1 = key2 not supported by crypto engine.
- * Revisit to request a fallback cipher in this case.
- */
- if (IS_XTS(flags)) {
- __keylen = keylen >> 1;
- if (!memcmp(key, key + __keylen, __keylen))
- return -ENOKEY;
- } else {
- __keylen = keylen;
- }
-
- switch (__keylen) {
- case AES_KEYSIZE_128:
- case AES_KEYSIZE_256:
- memcpy(ctx->enc_key, key, keylen);
- break;
- case AES_KEYSIZE_192:
- break;
- default:
- return -EINVAL;
- }
-
- ret = crypto_skcipher_setkey(ctx->fallback, key, keylen);
- if (!ret)
- ctx->enc_keylen = keylen;
- return ret;
-}
-
-static int qce_des_setkey(struct crypto_skcipher *ablk, const u8 *key,
- unsigned int keylen)
-{
- struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
- int err;
-
- err = verify_skcipher_des_key(ablk, key);
- if (err)
- return err;
-
- ctx->enc_keylen = keylen;
- memcpy(ctx->enc_key, key, keylen);
- return 0;
-}
-
-static int qce_des3_setkey(struct crypto_skcipher *ablk, const u8 *key,
- unsigned int keylen)
-{
- struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(ablk);
- u32 _key[6];
- int err;
-
- err = verify_skcipher_des3_key(ablk, key);
- if (err)
- return err;
-
- /*
- * The crypto engine does not support any two keys
- * being the same for triple des algorithms. The
- * verify_skcipher_des3_key does not check for all the
- * below conditions. Return -ENOKEY in case any two keys
- * are the same. Revisit to see if a fallback cipher
- * is needed to handle this condition.
- */
- memcpy(_key, key, DES3_EDE_KEY_SIZE);
- if (!((_key[0] ^ _key[2]) | (_key[1] ^ _key[3])) ||
- !((_key[2] ^ _key[4]) | (_key[3] ^ _key[5])) ||
- !((_key[0] ^ _key[4]) | (_key[1] ^ _key[5])))
- return -ENOKEY;
-
- ctx->enc_keylen = keylen;
- memcpy(ctx->enc_key, key, keylen);
- return 0;
-}
-
-static int qce_skcipher_crypt(struct skcipher_request *req, int encrypt)
-{
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
- struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
- struct qce_cipher_reqctx *rctx = skcipher_request_ctx(req);
- struct qce_alg_template *tmpl = to_cipher_tmpl(tfm);
- unsigned int blocksize = crypto_skcipher_blocksize(tfm);
- int keylen;
- int ret;
-
- rctx->flags = tmpl->alg_flags;
- rctx->flags |= encrypt ? QCE_ENCRYPT : QCE_DECRYPT;
- keylen = IS_XTS(rctx->flags) ? ctx->enc_keylen >> 1 : ctx->enc_keylen;
-
- /* CE does not handle 0 length messages */
- if (!req->cryptlen)
- return 0;
-
- /*
- * ECB and CBC algorithms require message lengths to be
- * multiples of block size.
- */
- if (IS_ECB(rctx->flags) || IS_CBC(rctx->flags))
- if (!IS_ALIGNED(req->cryptlen, blocksize))
- return -EINVAL;
-
- /*
- * Conditions for requesting a fallback cipher
- * AES-192 (not supported by crypto engine (CE))
- * AES-XTS request with len <= 512 byte (not recommended to use CE)
- * AES-XTS request with len > QCE_SECTOR_SIZE and
- * is not a multiple of it.(Revisit this condition to check if it is
- * needed in all versions of CE)
- */
- if (IS_AES(rctx->flags) &&
- ((keylen != AES_KEYSIZE_128 && keylen != AES_KEYSIZE_256) ||
- (IS_XTS(rctx->flags) && ((req->cryptlen <= aes_sw_max_len) ||
- (req->cryptlen > QCE_SECTOR_SIZE &&
- req->cryptlen % QCE_SECTOR_SIZE))))) {
- skcipher_request_set_tfm(&rctx->fallback_req, ctx->fallback);
- skcipher_request_set_callback(&rctx->fallback_req,
- req->base.flags,
- req->base.complete,
- req->base.data);
- skcipher_request_set_crypt(&rctx->fallback_req, req->src,
- req->dst, req->cryptlen, req->iv);
- ret = encrypt ? crypto_skcipher_encrypt(&rctx->fallback_req) :
- crypto_skcipher_decrypt(&rctx->fallback_req);
- return ret;
- }
-
- return tmpl->qce->async_req_enqueue(tmpl->qce, &req->base);
-}
-
-static int qce_skcipher_encrypt(struct skcipher_request *req)
-{
- return qce_skcipher_crypt(req, 1);
-}
-
-static int qce_skcipher_decrypt(struct skcipher_request *req)
-{
- return qce_skcipher_crypt(req, 0);
-}
-
-static int qce_skcipher_init(struct crypto_skcipher *tfm)
-{
- /* take the size without the fallback skcipher_request at the end */
- crypto_skcipher_set_reqsize(tfm, offsetof(struct qce_cipher_reqctx,
- fallback_req));
- return 0;
-}
-
-static int qce_skcipher_init_fallback(struct crypto_skcipher *tfm)
-{
- struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
-
- ctx->fallback = crypto_alloc_skcipher(crypto_tfm_alg_name(&tfm->base),
- 0, CRYPTO_ALG_NEED_FALLBACK);
- if (IS_ERR(ctx->fallback))
- return PTR_ERR(ctx->fallback);
-
- crypto_skcipher_set_reqsize(tfm, sizeof(struct qce_cipher_reqctx) +
- crypto_skcipher_reqsize(ctx->fallback));
- return 0;
-}
-
-static void qce_skcipher_exit(struct crypto_skcipher *tfm)
-{
- struct qce_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
-
- crypto_free_skcipher(ctx->fallback);
-}
-
-struct qce_skcipher_def {
- unsigned long flags;
- const char *name;
- const char *drv_name;
- unsigned int blocksize;
- unsigned int chunksize;
- unsigned int ivsize;
- unsigned int min_keysize;
- unsigned int max_keysize;
-};
-
-static const struct qce_skcipher_def skcipher_def[] = {
- {
- .flags = QCE_ALG_AES | QCE_MODE_ECB,
- .name = "ecb(aes)",
- .drv_name = "ecb-aes-qce",
- .blocksize = AES_BLOCK_SIZE,
- .ivsize = 0,
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_CBC,
- .name = "cbc(aes)",
- .drv_name = "cbc-aes-qce",
- .blocksize = AES_BLOCK_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_CTR,
- .name = "ctr(aes)",
- .drv_name = "ctr-aes-qce",
- .blocksize = 1,
- .chunksize = AES_BLOCK_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .min_keysize = AES_MIN_KEY_SIZE,
- .max_keysize = AES_MAX_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_AES | QCE_MODE_XTS,
- .name = "xts(aes)",
- .drv_name = "xts-aes-qce",
- .blocksize = AES_BLOCK_SIZE,
- .ivsize = AES_BLOCK_SIZE,
- .min_keysize = AES_MIN_KEY_SIZE * 2,
- .max_keysize = AES_MAX_KEY_SIZE * 2,
- },
- {
- .flags = QCE_ALG_DES | QCE_MODE_ECB,
- .name = "ecb(des)",
- .drv_name = "ecb-des-qce",
- .blocksize = DES_BLOCK_SIZE,
- .ivsize = 0,
- .min_keysize = DES_KEY_SIZE,
- .max_keysize = DES_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_DES | QCE_MODE_CBC,
- .name = "cbc(des)",
- .drv_name = "cbc-des-qce",
- .blocksize = DES_BLOCK_SIZE,
- .ivsize = DES_BLOCK_SIZE,
- .min_keysize = DES_KEY_SIZE,
- .max_keysize = DES_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_3DES | QCE_MODE_ECB,
- .name = "ecb(des3_ede)",
- .drv_name = "ecb-3des-qce",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .ivsize = 0,
- .min_keysize = DES3_EDE_KEY_SIZE,
- .max_keysize = DES3_EDE_KEY_SIZE,
- },
- {
- .flags = QCE_ALG_3DES | QCE_MODE_CBC,
- .name = "cbc(des3_ede)",
- .drv_name = "cbc-3des-qce",
- .blocksize = DES3_EDE_BLOCK_SIZE,
- .ivsize = DES3_EDE_BLOCK_SIZE,
- .min_keysize = DES3_EDE_KEY_SIZE,
- .max_keysize = DES3_EDE_KEY_SIZE,
- },
-};
-
-static int qce_skcipher_register_one(const struct qce_skcipher_def *def,
- struct qce_device *qce)
-{
- struct qce_alg_template *tmpl;
- struct skcipher_alg *alg;
- int ret;
-
- tmpl = kzalloc_obj(*tmpl);
- if (!tmpl)
- return -ENOMEM;
-
- alg = &tmpl->alg.skcipher;
-
- strscpy(alg->base.cra_name, def->name);
- strscpy(alg->base.cra_driver_name, def->drv_name);
-
- alg->base.cra_blocksize = def->blocksize;
- alg->chunksize = def->chunksize;
- alg->ivsize = def->ivsize;
- alg->min_keysize = def->min_keysize;
- alg->max_keysize = def->max_keysize;
- alg->setkey = IS_3DES(def->flags) ? qce_des3_setkey :
- IS_DES(def->flags) ? qce_des_setkey :
- qce_skcipher_setkey;
- alg->encrypt = qce_skcipher_encrypt;
- alg->decrypt = qce_skcipher_decrypt;
-
- alg->base.cra_priority = 275;
- alg->base.cra_flags = CRYPTO_ALG_ASYNC |
- CRYPTO_ALG_ALLOCATES_MEMORY |
- CRYPTO_ALG_KERN_DRIVER_ONLY;
- alg->base.cra_ctxsize = sizeof(struct qce_cipher_ctx);
- alg->base.cra_alignmask = 0;
- alg->base.cra_module = THIS_MODULE;
-
- if (IS_AES(def->flags)) {
- alg->base.cra_flags |= CRYPTO_ALG_NEED_FALLBACK;
- alg->init = qce_skcipher_init_fallback;
- alg->exit = qce_skcipher_exit;
- } else {
- alg->init = qce_skcipher_init;
- }
-
- INIT_LIST_HEAD(&tmpl->entry);
- tmpl->crypto_alg_type = CRYPTO_ALG_TYPE_SKCIPHER;
- tmpl->alg_flags = def->flags;
- tmpl->qce = qce;
-
- ret = crypto_register_skcipher(alg);
- if (ret) {
- dev_err(qce->dev, "%s registration failed\n", alg->base.cra_name);
- kfree(tmpl);
- return ret;
- }
-
- list_add_tail(&tmpl->entry, &skcipher_algs);
- dev_dbg(qce->dev, "%s is registered\n", alg->base.cra_name);
- return 0;
-}
-
-static void qce_skcipher_unregister(struct qce_device *qce)
-{
- struct qce_alg_template *tmpl, *n;
-
- list_for_each_entry_safe(tmpl, n, &skcipher_algs, entry) {
- crypto_unregister_skcipher(&tmpl->alg.skcipher);
- list_del(&tmpl->entry);
- kfree(tmpl);
- }
-}
-
-static int qce_skcipher_register(struct qce_device *qce)
-{
- int ret, i;
-
- for (i = 0; i < ARRAY_SIZE(skcipher_def); i++) {
- ret = qce_skcipher_register_one(&skcipher_def[i], qce);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- qce_skcipher_unregister(qce);
- return ret;
-}
-
-const struct qce_algo_ops skcipher_ops = {
- .type = CRYPTO_ALG_TYPE_SKCIPHER,
- .register_algs = qce_skcipher_register,
- .unregister_algs = qce_skcipher_unregister,
- .async_req_handle = qce_skcipher_async_req_handle,
-};
--
2.54.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox