1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <linux/platform_device.h>
18#include <crypto/ctr.h>
19#include "ssi_config.h"
20#include "ssi_driver.h"
21#include "ssi_ivgen.h"
22#include "ssi_request_mgr.h"
23#include "ssi_sram_mgr.h"
24#include "ssi_buffer_mgr.h"
25
26
27#define SSI_IVPOOL_SIZE 1024
28
29
30
31#define SSI_IVPOOL_META_SIZE (CC_AES_IV_SIZE + AES_KEYSIZE_128)
32#define SSI_IVPOOL_GEN_SEQ_LEN 4
33
34
35
36
37
38
39
40
41
42
43struct ssi_ivgen_ctx {
44 ssi_sram_addr_t pool;
45 ssi_sram_addr_t ctr_key;
46 ssi_sram_addr_t ctr_iv;
47 u32 next_iv_ofs;
48 u8 *pool_meta;
49 dma_addr_t pool_meta_dma;
50};
51
52
53
54
55
56
57
58
59
60static int ssi_ivgen_generate_pool(
61 struct ssi_ivgen_ctx *ivgen_ctx,
62 struct cc_hw_desc iv_seq[],
63 unsigned int *iv_seq_len)
64{
65 unsigned int idx = *iv_seq_len;
66
67 if ((*iv_seq_len + SSI_IVPOOL_GEN_SEQ_LEN) > SSI_IVPOOL_SEQ_LEN) {
68
69 return -EINVAL;
70 }
71
72 hw_desc_init(&iv_seq[idx]);
73 set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_key, AES_KEYSIZE_128);
74 set_setup_mode(&iv_seq[idx], SETUP_LOAD_KEY0);
75 set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
76 set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
77 set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
78 set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
79 idx++;
80
81
82 hw_desc_init(&iv_seq[idx]);
83 set_din_sram(&iv_seq[idx], ivgen_ctx->ctr_iv, CC_AES_IV_SIZE);
84 set_cipher_config0(&iv_seq[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
85 set_flow_mode(&iv_seq[idx], S_DIN_to_AES);
86 set_setup_mode(&iv_seq[idx], SETUP_LOAD_STATE1);
87 set_key_size_aes(&iv_seq[idx], CC_AES_128_BIT_KEY_SIZE);
88 set_cipher_mode(&iv_seq[idx], DRV_CIPHER_CTR);
89 idx++;
90
91
92 hw_desc_init(&iv_seq[idx]);
93 set_din_const(&iv_seq[idx], 0, CC_AES_IV_SIZE);
94 set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, CC_AES_IV_SIZE);
95 set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
96 idx++;
97
98
99 hw_desc_init(&iv_seq[idx]);
100 set_din_const(&iv_seq[idx], 0, SSI_IVPOOL_SIZE);
101 set_dout_sram(&iv_seq[idx], ivgen_ctx->pool, SSI_IVPOOL_SIZE);
102 set_flow_mode(&iv_seq[idx], DIN_AES_DOUT);
103 idx++;
104
105 *iv_seq_len = idx;
106
107
108 ivgen_ctx->next_iv_ofs = SSI_IVPOOL_META_SIZE;
109
110 return 0;
111}
112
113
114
115
116
117
118
119
120
121int ssi_ivgen_init_sram_pool(struct ssi_drvdata *drvdata)
122{
123 struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
124 struct cc_hw_desc iv_seq[SSI_IVPOOL_SEQ_LEN];
125 unsigned int iv_seq_len = 0;
126 int rc;
127
128
129 get_random_bytes(ivgen_ctx->pool_meta, SSI_IVPOOL_META_SIZE);
130
131
132 ivgen_ctx->ctr_key = ivgen_ctx->pool;
133 ivgen_ctx->ctr_iv = ivgen_ctx->pool + AES_KEYSIZE_128;
134
135
136 hw_desc_init(&iv_seq[iv_seq_len]);
137 set_din_type(&iv_seq[iv_seq_len], DMA_DLLI, ivgen_ctx->pool_meta_dma,
138 SSI_IVPOOL_META_SIZE, NS_BIT);
139 set_dout_sram(&iv_seq[iv_seq_len], ivgen_ctx->pool,
140 SSI_IVPOOL_META_SIZE);
141 set_flow_mode(&iv_seq[iv_seq_len], BYPASS);
142 iv_seq_len++;
143
144
145 rc = ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, &iv_seq_len);
146 if (unlikely(rc != 0))
147 return rc;
148
149
150 return send_request_init(drvdata, iv_seq, iv_seq_len);
151}
152
153
154
155
156
157
158void ssi_ivgen_fini(struct ssi_drvdata *drvdata)
159{
160 struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
161 struct device *device = &(drvdata->plat_dev->dev);
162
163 if (!ivgen_ctx)
164 return;
165
166 if (ivgen_ctx->pool_meta) {
167 memset(ivgen_ctx->pool_meta, 0, SSI_IVPOOL_META_SIZE);
168 dma_free_coherent(device, SSI_IVPOOL_META_SIZE,
169 ivgen_ctx->pool_meta, ivgen_ctx->pool_meta_dma);
170 }
171
172 ivgen_ctx->pool = NULL_SRAM_ADDR;
173
174
175 kfree(ivgen_ctx);
176}
177
178
179
180
181
182
183
184
185
186int ssi_ivgen_init(struct ssi_drvdata *drvdata)
187{
188 struct ssi_ivgen_ctx *ivgen_ctx;
189 struct device *device = &drvdata->plat_dev->dev;
190 int rc;
191
192
193 drvdata->ivgen_handle = kzalloc(sizeof(struct ssi_ivgen_ctx), GFP_KERNEL);
194 if (!drvdata->ivgen_handle) {
195 SSI_LOG_ERR("Not enough memory to allocate IVGEN context "
196 "(%zu B)\n", sizeof(struct ssi_ivgen_ctx));
197 rc = -ENOMEM;
198 goto out;
199 }
200 ivgen_ctx = drvdata->ivgen_handle;
201
202
203 ivgen_ctx->pool_meta = dma_alloc_coherent(device, SSI_IVPOOL_META_SIZE,
204 &ivgen_ctx->pool_meta_dma, GFP_KERNEL);
205 if (!ivgen_ctx->pool_meta) {
206 SSI_LOG_ERR("Not enough memory to allocate DMA of pool_meta "
207 "(%u B)\n", SSI_IVPOOL_META_SIZE);
208 rc = -ENOMEM;
209 goto out;
210 }
211
212 ivgen_ctx->pool = ssi_sram_mgr_alloc(drvdata, SSI_IVPOOL_SIZE);
213 if (ivgen_ctx->pool == NULL_SRAM_ADDR) {
214 SSI_LOG_ERR("SRAM pool exhausted\n");
215 rc = -ENOMEM;
216 goto out;
217 }
218
219 return ssi_ivgen_init_sram_pool(drvdata);
220
221out:
222 ssi_ivgen_fini(drvdata);
223 return rc;
224}
225
226
227
228
229
230
231
232
233
234
235
236
237
238int ssi_ivgen_getiv(
239 struct ssi_drvdata *drvdata,
240 dma_addr_t iv_out_dma[],
241 unsigned int iv_out_dma_len,
242 unsigned int iv_out_size,
243 struct cc_hw_desc iv_seq[],
244 unsigned int *iv_seq_len)
245{
246 struct ssi_ivgen_ctx *ivgen_ctx = drvdata->ivgen_handle;
247 unsigned int idx = *iv_seq_len;
248 unsigned int t;
249
250 if ((iv_out_size != CC_AES_IV_SIZE) &&
251 (iv_out_size != CTR_RFC3686_IV_SIZE)) {
252 return -EINVAL;
253 }
254 if ((iv_out_dma_len + 1) > SSI_IVPOOL_SEQ_LEN) {
255
256 return -EINVAL;
257 }
258
259
260 if (iv_out_dma_len > SSI_MAX_IVGEN_DMA_ADDRESSES) {
261
262 return -EINVAL;
263 }
264
265 for (t = 0; t < iv_out_dma_len; t++) {
266
267 hw_desc_init(&iv_seq[idx]);
268 set_din_sram(&iv_seq[idx], (ivgen_ctx->pool +
269 ivgen_ctx->next_iv_ofs),
270 iv_out_size);
271 set_dout_dlli(&iv_seq[idx], iv_out_dma[t], iv_out_size,
272 NS_BIT, 0);
273 set_flow_mode(&iv_seq[idx], BYPASS);
274 idx++;
275 }
276
277
278
279
280 hw_desc_init(&iv_seq[idx]);
281 set_din_no_dma(&iv_seq[idx], 0, 0xfffff0);
282 set_dout_no_dma(&iv_seq[idx], 0, 0, 1);
283 idx++;
284
285 *iv_seq_len = idx;
286
287
288 ivgen_ctx->next_iv_ofs += iv_out_size;
289
290 if ((SSI_IVPOOL_SIZE - ivgen_ctx->next_iv_ofs) < CC_AES_IV_SIZE) {
291 SSI_LOG_DEBUG("Pool exhausted, regenerating iv-pool\n");
292
293 return ssi_ivgen_generate_pool(ivgen_ctx, iv_seq, iv_seq_len);
294 }
295
296 return 0;
297}
298
299