[PATCH 09/15] crypto: zynqmp-aes-gcm: Fix setkey operation to select HW keys
Harsh Jain
h.jain at amd.com
Wed Oct 29 03:21:52 PDT 2025
Currently keylen 1 is used to select hw key. There are -ve self test
which can fail for setkey length 1. Update driver to use 4 bytes
with magic number to select H/W key type.
Signed-off-by: Harsh Jain <h.jain at amd.com>
---
drivers/crypto/xilinx/zynqmp-aes-gcm.c | 94 ++++++++++++++++----------
1 file changed, 60 insertions(+), 34 deletions(-)
diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
index 9be1305b79d2..bc12340487be 100644
--- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c
+++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
@@ -22,14 +22,14 @@
#define ZYNQMP_AES_KEY_SIZE AES_KEYSIZE_256
#define ZYNQMP_AES_AUTH_SIZE 16U
-#define ZYNQMP_KEY_SRC_SEL_KEY_LEN 1U
#define ZYNQMP_AES_BLK_SIZE 1U
#define ZYNQMP_AES_MIN_INPUT_BLK_SIZE 4U
#define ZYNQMP_AES_WORD_LEN 4U
-#define ZYNQMP_AES_GCM_TAG_MISMATCH_ERR 0x01
-#define ZYNQMP_AES_WRONG_KEY_SRC_ERR 0x13
-#define ZYNQMP_AES_PUF_NOT_PROGRAMMED 0xE300
+#define ZYNQMP_AES_GCM_TAG_MISMATCH_ERR 0x01
+#define ZYNQMP_AES_WRONG_KEY_SRC_ERR 0x13
+#define ZYNQMP_AES_PUF_NOT_PROGRAMMED 0xE300
+#define XILINX_KEY_MAGIC 0x3EA0
enum zynqmp_aead_op {
ZYNQMP_AES_DECRYPT = 0,
@@ -48,6 +48,11 @@ struct zynqmp_aead_drv_ctx {
struct crypto_engine *engine;
};
+struct xilinx_hwkey_info {
+ u16 magic;
+ u16 type;
+} __packed;
+
struct zynqmp_aead_hw_req {
u64 src;
u64 iv;
@@ -64,7 +69,7 @@ struct zynqmp_aead_tfm_ctx {
u8 *iv;
u32 keylen;
u32 authsize;
- enum zynqmp_aead_keysrc keysrc;
+ u8 keysrc;
struct crypto_aead *fbk_cipher;
};
@@ -175,32 +180,29 @@ static int zynqmp_aes_aead_cipher(struct aead_request *req)
static int zynqmp_fallback_check(struct zynqmp_aead_tfm_ctx *tfm_ctx,
struct aead_request *req)
{
- int need_fallback = 0;
struct zynqmp_aead_req_ctx *rq_ctx = aead_request_ctx(req);
if (tfm_ctx->authsize != ZYNQMP_AES_AUTH_SIZE && rq_ctx->op == ZYNQMP_AES_DECRYPT)
return 1;
- if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY &&
- tfm_ctx->keylen != ZYNQMP_AES_KEY_SIZE) {
- need_fallback = 1;
- }
if (req->assoclen != 0 ||
- req->cryptlen < ZYNQMP_AES_MIN_INPUT_BLK_SIZE) {
- need_fallback = 1;
- }
+ req->cryptlen < ZYNQMP_AES_MIN_INPUT_BLK_SIZE)
+ return 1;
+ if (tfm_ctx->keylen == AES_KEYSIZE_128 ||
+ tfm_ctx->keylen == AES_KEYSIZE_192)
+ return 1;
+
if ((req->cryptlen % ZYNQMP_AES_WORD_LEN) != 0)
- need_fallback = 1;
+ return 1;
if (rq_ctx->op == ZYNQMP_AES_DECRYPT &&
- req->cryptlen <= ZYNQMP_AES_AUTH_SIZE) {
- need_fallback = 1;
- }
- return need_fallback;
+ req->cryptlen <= ZYNQMP_AES_AUTH_SIZE)
+ return 1;
+
+ return 0;
}
-static int zynqmp_handle_aes_req(struct crypto_engine *engine,
- void *req)
+static int zynqmp_handle_aes_req(struct crypto_engine *engine, void *req)
{
struct aead_request *areq =
container_of(req, struct aead_request, base);
@@ -218,32 +220,42 @@ static int zynqmp_aes_aead_setkey(struct crypto_aead *aead, const u8 *key,
unsigned int keylen)
{
struct crypto_tfm *tfm = crypto_aead_tfm(aead);
- struct zynqmp_aead_tfm_ctx *tfm_ctx =
- (struct zynqmp_aead_tfm_ctx *)crypto_tfm_ctx(tfm);
+ struct zynqmp_aead_tfm_ctx *tfm_ctx = crypto_tfm_ctx(tfm);
+ struct xilinx_hwkey_info hwkey;
unsigned char keysrc;
+ int err;
- if (keylen == ZYNQMP_KEY_SRC_SEL_KEY_LEN) {
- keysrc = *key;
+ if (keylen == sizeof(struct xilinx_hwkey_info)) {
+ memcpy(&hwkey, key, sizeof(struct xilinx_hwkey_info));
+ if (hwkey.magic != XILINX_KEY_MAGIC)
+ return -EINVAL;
+ keysrc = hwkey.type;
if (keysrc == ZYNQMP_AES_KUP_KEY ||
keysrc == ZYNQMP_AES_DEV_KEY ||
keysrc == ZYNQMP_AES_PUF_KEY) {
- tfm_ctx->keysrc = (enum zynqmp_aead_keysrc)keysrc;
- } else {
- tfm_ctx->keylen = keylen;
+ tfm_ctx->keysrc = keysrc;
+ tfm_ctx->keylen = sizeof(struct xilinx_hwkey_info);
+ return 0;
}
- } else {
+ return -EINVAL;
+ }
+
+ if (keylen == ZYNQMP_AES_KEY_SIZE && tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY) {
tfm_ctx->keylen = keylen;
- if (keylen == ZYNQMP_AES_KEY_SIZE) {
- tfm_ctx->keysrc = ZYNQMP_AES_KUP_KEY;
- memcpy(tfm_ctx->key, key, keylen);
- }
+ memcpy(tfm_ctx->key, key, keylen);
+ } else if (tfm_ctx->keysrc != ZYNQMP_AES_KUP_KEY) {
+ return -EINVAL;
}
tfm_ctx->fbk_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
tfm_ctx->fbk_cipher->base.crt_flags |= (aead->base.crt_flags &
CRYPTO_TFM_REQ_MASK);
- return crypto_aead_setkey(tfm_ctx->fbk_cipher, key, keylen);
+ err = crypto_aead_setkey(tfm_ctx->fbk_cipher, key, keylen);
+ if (!err)
+ tfm_ctx->keylen = keylen;
+
+ return err;
}
static int zynqmp_aes_aead_setauthsize(struct crypto_aead *aead,
@@ -267,9 +279,16 @@ static int zynqmp_aes_aead_encrypt(struct aead_request *req)
struct zynqmp_aead_drv_ctx *drv_ctx;
int err;
- rq_ctx->op = ZYNQMP_AES_ENCRYPT;
drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, aead.base);
+ if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY &&
+ tfm_ctx->keylen == sizeof(struct xilinx_hwkey_info))
+ return -EINVAL;
+
+ rq_ctx->op = ZYNQMP_AES_ENCRYPT;
err = zynqmp_fallback_check(tfm_ctx, req);
+ if (err && tfm_ctx->keysrc != ZYNQMP_AES_KUP_KEY)
+ return -EOPNOTSUPP;
+
if (err) {
aead_request_set_tfm(subreq, tfm_ctx->fbk_cipher);
aead_request_set_callback(subreq, req->base.flags,
@@ -297,7 +316,12 @@ static int zynqmp_aes_aead_decrypt(struct aead_request *req)
rq_ctx->op = ZYNQMP_AES_DECRYPT;
drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, aead.base);
+ if (tfm_ctx->keysrc == ZYNQMP_AES_KUP_KEY &&
+ tfm_ctx->keylen == sizeof(struct xilinx_hwkey_info))
+ return -EINVAL;
err = zynqmp_fallback_check(tfm_ctx, req);
+ if (err && tfm_ctx->keysrc != ZYNQMP_AES_KUP_KEY)
+ return -EOPNOTSUPP;
if (err) {
aead_request_set_tfm(subreq, tfm_ctx->fbk_cipher);
aead_request_set_callback(subreq, req->base.flags,
@@ -323,6 +347,8 @@ static int zynqmp_aes_aead_init(struct crypto_aead *aead)
drv_ctx = container_of(alg, struct zynqmp_aead_drv_ctx, aead.base);
tfm_ctx->dev = drv_ctx->dev;
+ tfm_ctx->keylen = 0;
+ tfm_ctx->keysrc = ZYNQMP_AES_KUP_KEY;
tfm_ctx->fbk_cipher = crypto_alloc_aead(drv_ctx->aead.base.base.cra_name,
0,
--
2.49.1
More information about the linux-arm-kernel
mailing list