1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
4 * Crypto driver file to manage keys of NVIDIA Security Engine.
7 #include <linux/bitops.h>
8 #include <linux/module.h>
9 #include <crypto/aes.h>
13 #define SE_KEY_FULL_MASK GENMASK(SE_MAX_KEYSLOT, 0)
15 /* Reserve keyslot 0, 14, 15 */
16 #define SE_KEY_RSVD_MASK (BIT(0) | BIT(14) | BIT(15))
17 #define SE_KEY_VALID_MASK (SE_KEY_FULL_MASK & ~SE_KEY_RSVD_MASK)
19 /* Mutex lock to guard keyslots */
20 static DEFINE_MUTEX(kslt_lock
);
22 /* Keyslot bitmask (0 = available, 1 = in use/not available) */
23 static u16 tegra_se_keyslots
= SE_KEY_RSVD_MASK
;
25 static u16
tegra_keyslot_alloc(void)
29 mutex_lock(&kslt_lock
);
30 /* Check if all key slots are full */
31 if (tegra_se_keyslots
== GENMASK(SE_MAX_KEYSLOT
, 0)) {
32 mutex_unlock(&kslt_lock
);
36 keyid
= ffz(tegra_se_keyslots
);
37 tegra_se_keyslots
|= BIT(keyid
);
39 mutex_unlock(&kslt_lock
);
44 static void tegra_keyslot_free(u16 slot
)
46 mutex_lock(&kslt_lock
);
47 tegra_se_keyslots
&= ~(BIT(slot
));
48 mutex_unlock(&kslt_lock
);
51 static unsigned int tegra_key_prep_ins_cmd(struct tegra_se
*se
, u32
*cpuvaddr
,
52 const u32
*key
, u32 keylen
, u16 slot
, u32 alg
)
56 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
57 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->op
);
58 cpuvaddr
[i
++] = SE_AES_OP_WRSTALL
| SE_AES_OP_DUMMY
;
60 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
61 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->manifest
);
62 cpuvaddr
[i
++] = se
->manifest(se
->owner
, alg
, keylen
);
63 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
64 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->key_dst
);
66 cpuvaddr
[i
++] = SE_AES_KEY_DST_INDEX(slot
);
68 for (j
= 0; j
< keylen
/ 4; j
++) {
70 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
71 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->key_addr
);
75 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
76 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->key_data
);
77 cpuvaddr
[i
++] = key
[j
];
80 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
81 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->config
);
82 cpuvaddr
[i
++] = SE_CFG_INS
;
84 cpuvaddr
[i
++] = host1x_opcode_setpayload(1);
85 cpuvaddr
[i
++] = se_host1x_opcode_incr_w(se
->hw
->regs
->op
);
86 cpuvaddr
[i
++] = SE_AES_OP_WRSTALL
| SE_AES_OP_START
|
89 cpuvaddr
[i
++] = se_host1x_opcode_nonincr(host1x_uclass_incr_syncpt_r(), 1);
90 cpuvaddr
[i
++] = host1x_uclass_incr_syncpt_cond_f(1) |
91 host1x_uclass_incr_syncpt_indx_f(se
->syncpt_id
);
93 dev_dbg(se
->dev
, "key-slot %u key-manifest %#x\n",
94 slot
, se
->manifest(se
->owner
, alg
, keylen
));
99 static bool tegra_key_in_kslt(u32 keyid
)
103 if (keyid
> SE_MAX_KEYSLOT
)
106 mutex_lock(&kslt_lock
);
107 ret
= ((BIT(keyid
) & SE_KEY_VALID_MASK
) &&
108 (BIT(keyid
) & tegra_se_keyslots
));
109 mutex_unlock(&kslt_lock
);
114 static int tegra_key_insert(struct tegra_se
*se
, const u8
*key
,
115 u32 keylen
, u16 slot
, u32 alg
)
117 const u32
*keyval
= (u32
*)key
;
118 u32
*addr
= se
->cmdbuf
->addr
, size
;
120 size
= tegra_key_prep_ins_cmd(se
, addr
, keyval
, keylen
, slot
, alg
);
122 return tegra_se_host1x_submit(se
, size
);
125 void tegra_key_invalidate(struct tegra_se
*se
, u32 keyid
, u32 alg
)
127 u8 zkey
[AES_MAX_KEY_SIZE
] = {0};
132 /* Overwrite the key with 0s */
133 tegra_key_insert(se
, zkey
, AES_MAX_KEY_SIZE
, keyid
, alg
);
135 tegra_keyslot_free(keyid
);
138 int tegra_key_submit(struct tegra_se
*se
, const u8
*key
, u32 keylen
, u32 alg
, u32
*keyid
)
142 /* Use the existing slot if it is already allocated */
143 if (!tegra_key_in_kslt(*keyid
)) {
144 *keyid
= tegra_keyslot_alloc();
146 dev_err(se
->dev
, "failed to allocate key slot\n");
151 ret
= tegra_key_insert(se
, key
, keylen
, *keyid
, alg
);