1 // SPDX-License-Identifier: GPL-2.0-only
2 // SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 /*
4  * Crypto driver file to manage keys of NVIDIA Security Engine.
5  */
6 
7 #include <linux/bitops.h>
8 #include <linux/module.h>
9 #include <crypto/aes.h>
10 
11 #include "tegra-se.h"
12 
13 #define SE_KEY_FULL_MASK		GENMASK(SE_MAX_KEYSLOT, 0)
14 
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)
18 
19 /* Mutex lock to guard keyslots */
20 static DEFINE_MUTEX(kslt_lock);
21 
22 /* Keyslot bitmask (0 = available, 1 = in use/not available) */
23 static u16 tegra_se_keyslots = SE_KEY_RSVD_MASK;
24 
tegra_keyslot_alloc(void)25 static u16 tegra_keyslot_alloc(void)
26 {
27 	u16 keyid;
28 
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);
33 		return 0;
34 	}
35 
36 	keyid = ffz(tegra_se_keyslots);
37 	tegra_se_keyslots |= BIT(keyid);
38 
39 	mutex_unlock(&kslt_lock);
40 
41 	return keyid;
42 }
43 
tegra_keyslot_free(u16 slot)44 static void tegra_keyslot_free(u16 slot)
45 {
46 	mutex_lock(&kslt_lock);
47 	tegra_se_keyslots &= ~(BIT(slot));
48 	mutex_unlock(&kslt_lock);
49 }
50 
tegra_key_prep_ins_cmd(struct tegra_se * se,u32 * cpuvaddr,const u32 * key,u32 keylen,u16 slot,u32 alg)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)
53 {
54 	int i = 0, j;
55 
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;
59 
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);
65 
66 	cpuvaddr[i++] = SE_AES_KEY_DST_INDEX(slot);
67 
68 	for (j = 0; j < keylen / 4; j++) {
69 		/* Set key address */
70 		cpuvaddr[i++] = host1x_opcode_setpayload(1);
71 		cpuvaddr[i++] = se_host1x_opcode_incr_w(se->hw->regs->key_addr);
72 		cpuvaddr[i++] = j;
73 
74 		/* Set key data */
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];
78 	}
79 
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;
83 
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 |
87 			SE_AES_OP_LASTBUF;
88 
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);
92 
93 	dev_dbg(se->dev, "key-slot %u key-manifest %#x\n",
94 		slot, se->manifest(se->owner, alg, keylen));
95 
96 	return i;
97 }
98 
tegra_key_in_kslt(u32 keyid)99 static bool tegra_key_in_kslt(u32 keyid)
100 {
101 	bool ret;
102 
103 	if (keyid > SE_MAX_KEYSLOT)
104 		return false;
105 
106 	mutex_lock(&kslt_lock);
107 	ret = ((BIT(keyid) & SE_KEY_VALID_MASK) &&
108 		(BIT(keyid) & tegra_se_keyslots));
109 	mutex_unlock(&kslt_lock);
110 
111 	return ret;
112 }
113 
tegra_key_insert(struct tegra_se * se,const u8 * key,u32 keylen,u16 slot,u32 alg)114 static int tegra_key_insert(struct tegra_se *se, const u8 *key,
115 			    u32 keylen, u16 slot, u32 alg)
116 {
117 	const u32 *keyval = (u32 *)key;
118 	u32 *addr = se->keybuf->addr, size;
119 	int ret;
120 
121 	mutex_lock(&kslt_lock);
122 
123 	size = tegra_key_prep_ins_cmd(se, addr, keyval, keylen, slot, alg);
124 	ret = tegra_se_host1x_submit(se, se->keybuf, size);
125 
126 	mutex_unlock(&kslt_lock);
127 
128 	return ret;
129 }
130 
tegra_key_invalidate(struct tegra_se * se,u32 keyid,u32 alg)131 void tegra_key_invalidate(struct tegra_se *se, u32 keyid, u32 alg)
132 {
133 	u8 zkey[AES_MAX_KEY_SIZE] = {0};
134 
135 	if (!keyid)
136 		return;
137 
138 	/* Overwrite the key with 0s */
139 	tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
140 
141 	tegra_keyslot_free(keyid);
142 }
143 
tegra_key_invalidate_reserved(struct tegra_se * se,u32 keyid,u32 alg)144 void tegra_key_invalidate_reserved(struct tegra_se *se, u32 keyid, u32 alg)
145 {
146 	u8 zkey[AES_MAX_KEY_SIZE] = {0};
147 
148 	if (!keyid)
149 		return;
150 
151 	/* Overwrite the key with 0s */
152 	tegra_key_insert(se, zkey, AES_MAX_KEY_SIZE, keyid, alg);
153 }
154 
tegra_key_submit_reserved(struct tegra_se * se,const u8 * key,u32 keylen,u32 alg,u32 * keyid)155 inline int tegra_key_submit_reserved(struct tegra_se *se, const u8 *key,
156 				     u32 keylen, u32 alg, u32 *keyid)
157 {
158 	return tegra_key_insert(se, key, keylen, *keyid, alg);
159 }
160 
tegra_key_submit(struct tegra_se * se,const u8 * key,u32 keylen,u32 alg,u32 * keyid)161 int tegra_key_submit(struct tegra_se *se, const u8 *key, u32 keylen, u32 alg, u32 *keyid)
162 {
163 	int ret;
164 
165 	/* Use the existing slot if it is already allocated */
166 	if (!tegra_key_in_kslt(*keyid)) {
167 		*keyid = tegra_keyslot_alloc();
168 		if (!(*keyid)) {
169 			dev_dbg(se->dev, "failed to allocate key slot\n");
170 			return -ENOMEM;
171 		}
172 	}
173 
174 	ret = tegra_key_insert(se, key, keylen, *keyid, alg);
175 	if (ret)
176 		return ret;
177 
178 	return 0;
179 }
180