Branch data Line data Source code
1 : : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 : : *
3 : : * Copyright 2008-2016 Freescale Semiconductor Inc.
4 : : * Copyright 2016,2019-2021 NXP
5 : : *
6 : : */
7 : :
8 : : #ifndef __DESC_ALGO_H__
9 : : #define __DESC_ALGO_H__
10 : :
11 : : #include "rta.h"
12 : : #include "common.h"
13 : :
14 : : /**
15 : : * DOC: Algorithms - Shared Descriptor Constructors
16 : : *
17 : : * Shared descriptors for algorithms (i.e. not for protocols).
18 : : */
19 : :
20 : : /**
21 : : * cnstr_shdsc_zuce - ZUC Enc (EEA2) as a shared descriptor
22 : : * @descbuf: pointer to descriptor-under-construction buffer
23 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
24 : : * @swap: must be true when core endianness doesn't match SEC endianness
25 : : * @cipherdata: pointer to block cipher transform definitions
26 : : * @dir: Cipher direction (DIR_ENC/DIR_DEC)
27 : : *
28 : : * Return: size of descriptor written in words or negative number on error
29 : : */
30 : : static inline int
31 [ # # ]: 0 : cnstr_shdsc_zuce(uint32_t *descbuf, bool ps, bool swap,
32 : : struct alginfo *cipherdata, uint8_t dir)
33 : : {
34 : : struct program prg;
35 : : struct program *p = &prg;
36 : :
37 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
38 [ # # ]: 0 : if (swap)
39 : : PROGRAM_SET_BSWAP(p);
40 : :
41 [ # # ]: 0 : if (ps)
42 : : PROGRAM_SET_36BIT_ADDR(p);
43 : 0 : SHR_HDR(p, SHR_ALWAYS, 1, 0);
44 : :
45 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
46 : : cipherdata->keylen, INLINE_KEY(cipherdata));
47 : :
48 : 0 : SEQLOAD(p, CONTEXT1, 0, 16, 0);
49 : :
50 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
51 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
52 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE, OP_ALG_AAI_F8,
53 : : OP_ALG_AS_INITFINAL, 0, dir);
54 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
55 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
56 : :
57 : 0 : return PROGRAM_FINALIZE(p);
58 : : }
59 : :
60 : : /**
61 : : * cnstr_shdsc_zuca - ZUC Auth (EIA2) as a shared descriptor
62 : : * @descbuf: pointer to descriptor-under-construction buffer
63 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
64 : : * @swap: must be true when core endianness doesn't match SEC endianness
65 : : * @authdata: pointer to authentication transform definitions
66 : : * @chk_icv: Whether to compare and verify ICV (true/false)
67 : : * @authlen: size of digest
68 : : *
69 : : * The IV prepended before hmac payload must be 8 bytes consisting
70 : : * of COUNT||BEARER||DIR. The COUNT is of 32-bits, bearer is of 5 bits and
71 : : * direction is of 1 bit - totalling to 38 bits.
72 : : *
73 : : * Return: size of descriptor written in words or negative number on error
74 : : */
75 : : static inline int
76 : 0 : cnstr_shdsc_zuca(uint32_t *descbuf, bool ps, bool swap,
77 : : struct alginfo *authdata, uint8_t chk_icv,
78 : : uint32_t authlen)
79 : : {
80 : : struct program prg;
81 : : struct program *p = &prg;
82 [ # # ]: 0 : int dir = chk_icv ? DIR_DEC : DIR_ENC;
83 : :
84 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
85 [ # # ]: 0 : if (swap)
86 : : PROGRAM_SET_BSWAP(p);
87 : :
88 [ # # ]: 0 : if (ps)
89 : : PROGRAM_SET_36BIT_ADDR(p);
90 : 0 : SHR_HDR(p, SHR_ALWAYS, 1, 0);
91 : :
92 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
93 : : authdata->keylen, INLINE_KEY(authdata));
94 : :
95 : 0 : SEQLOAD(p, CONTEXT2, 0, 8, 0);
96 : :
97 [ # # ]: 0 : if (chk_icv == ICV_CHECK_ENABLE)
98 : 0 : MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2);
99 : : else
100 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
101 : :
102 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA, OP_ALG_AAI_F9,
103 : : OP_ALG_AS_INITFINAL, chk_icv, dir);
104 : :
105 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2);
106 : :
107 [ # # ]: 0 : if (chk_icv == ICV_CHECK_ENABLE)
108 : 0 : SEQFIFOLOAD(p, ICV2, authlen, LAST2);
109 : : else
110 : : /* Save lower half of MAC out into a 32-bit sequence */
111 : 0 : SEQSTORE(p, CONTEXT2, 0, authlen, 0);
112 : :
113 : 0 : return PROGRAM_FINALIZE(p);
114 : : }
115 : :
116 : :
117 : : /**
118 : : * cnstr_shdsc_snow_f8 - SNOW/f8 (UEA2) as a shared descriptor
119 : : * @descbuf: pointer to descriptor-under-construction buffer
120 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
121 : : * @swap: must be true when core endianness doesn't match SEC endianness
122 : : * @cipherdata: pointer to block cipher transform definitions
123 : : * @dir: Cipher direction (DIR_ENC/DIR_DEC)
124 : : *
125 : : * Return: size of descriptor written in words or negative number on error
126 : : */
127 : : static inline int
128 [ # # ]: 0 : cnstr_shdsc_snow_f8(uint32_t *descbuf, bool ps, bool swap,
129 : : struct alginfo *cipherdata, uint8_t dir)
130 : : {
131 : : struct program prg;
132 : : struct program *p = &prg;
133 : :
134 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
135 [ # # ]: 0 : if (swap)
136 : : PROGRAM_SET_BSWAP(p);
137 : :
138 [ # # ]: 0 : if (ps)
139 : : PROGRAM_SET_36BIT_ADDR(p);
140 : 0 : SHR_HDR(p, SHR_ALWAYS, 1, 0);
141 : :
142 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
143 : : cipherdata->keylen, INLINE_KEY(cipherdata));
144 : :
145 : 0 : SEQLOAD(p, CONTEXT1, 0, 16, 0);
146 : :
147 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
148 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
149 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
150 : : OP_ALG_AS_INITFINAL, 0, dir);
151 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
152 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
153 : :
154 : 0 : return PROGRAM_FINALIZE(p);
155 : : }
156 : :
157 : : /**
158 : : * conv_to_zuc_eia_iv - ZUCA IV 16-byte to 8-byte convert
159 : : * function for 3G.
160 : : * @iv: 16 bytes of original IV data.
161 : : *
162 : : * From the original IV, we extract 32-bits of COUNT,
163 : : * 5-bits of bearer and 1-bit of direction.
164 : : * Refer to CAAM refman for ZUCA IV format. Then these values are
165 : : * appended as COUNT||BEARER||DIR continuously to make a 38-bit block.
166 : : * This 38-bit block is copied left justified into 8-byte array used as
167 : : * converted IV.
168 : : *
169 : : * Return: 8-bytes of IV data as understood by SEC HW
170 : : */
171 : :
172 : : static inline uint8_t *conv_to_zuc_eia_iv(uint8_t *iv)
173 : : {
174 : 0 : uint8_t dir = (iv[14] & 0x80) ? 4 : 0;
175 : :
176 : 0 : iv[12] = iv[4] | dir;
177 : 0 : iv[13] = 0;
178 : 0 : iv[14] = 0;
179 : 0 : iv[15] = 0;
180 : :
181 : 0 : iv[8] = iv[0];
182 : 0 : iv[9] = iv[1];
183 : 0 : iv[10] = iv[2];
184 : 0 : iv[11] = iv[3];
185 : :
186 : 0 : return (iv + 8);
187 : : }
188 : :
189 : : /**
190 : : * conv_to_snow_f9_iv - SNOW/f9 (UIA2) IV 16 byte to 12 byte convert
191 : : * function for 3G.
192 : : * @iv: 16 byte original IV data
193 : : *
194 : : * Return: 12 byte IV data as understood by SEC HW
195 : : */
196 : :
197 : : static inline uint8_t *conv_to_snow_f9_iv(uint8_t *iv)
198 : : {
199 [ # # # # ]: 0 : uint8_t temp = (iv[8] == iv[0]) ? 0 : 4;
200 : :
201 : 0 : iv[12] = iv[4];
202 : 0 : iv[13] = iv[5];
203 : 0 : iv[14] = iv[6];
204 : 0 : iv[15] = iv[7];
205 : :
206 : 0 : iv[8] = temp;
207 : 0 : iv[9] = 0x00;
208 : 0 : iv[10] = 0x00;
209 : 0 : iv[11] = 0x00;
210 : :
211 : 0 : iv[4] = iv[0];
212 : 0 : iv[5] = iv[1];
213 : 0 : iv[6] = iv[2];
214 : 0 : iv[7] = iv[3];
215 : :
216 : 0 : return (iv + 4);
217 : : }
218 : :
219 : : /**
220 : : * cnstr_shdsc_snow_f9 - SNOW/f9 (UIA2) as a shared descriptor
221 : : * @descbuf: pointer to descriptor-under-construction buffer
222 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
223 : : * @swap: must be true when core endianness doesn't match SEC endianness
224 : : * @authdata: pointer to authentication transform definitions
225 : : * @chk_icv: check or generate ICV value
226 : : * @authlen: size of digest
227 : : *
228 : : * Return: size of descriptor written in words or negative number on error
229 : : */
230 : : static inline int
231 : 0 : cnstr_shdsc_snow_f9(uint32_t *descbuf, bool ps, bool swap,
232 : : struct alginfo *authdata, uint8_t chk_icv,
233 : : uint32_t authlen)
234 : : {
235 : : struct program prg;
236 : : struct program *p = &prg;
237 [ # # ]: 0 : int dir = chk_icv ? DIR_DEC : DIR_ENC;
238 : :
239 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
240 [ # # ]: 0 : if (swap)
241 : : PROGRAM_SET_BSWAP(p);
242 : :
243 [ # # ]: 0 : if (ps)
244 : : PROGRAM_SET_36BIT_ADDR(p);
245 : :
246 : 0 : SHR_HDR(p, SHR_ALWAYS, 1, 0);
247 : :
248 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
249 : : authdata->keylen, INLINE_KEY(authdata));
250 : :
251 : 0 : SEQLOAD(p, CONTEXT2, 0, 12, 0);
252 : :
253 [ # # ]: 0 : if (chk_icv == ICV_CHECK_ENABLE)
254 : 0 : MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2);
255 : : else
256 : 0 : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
257 : :
258 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
259 : : OP_ALG_AS_INITFINAL, chk_icv, dir);
260 : :
261 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2);
262 : :
263 [ # # ]: 0 : if (chk_icv == ICV_CHECK_ENABLE)
264 : 0 : SEQFIFOLOAD(p, ICV2, authlen, LAST2);
265 : : else
266 : : /* Save lower half of MAC out into a 32-bit sequence */
267 : 0 : SEQSTORE(p, CONTEXT2, 0, authlen, 0);
268 : :
269 : 0 : return PROGRAM_FINALIZE(p);
270 : : }
271 : :
272 : : /**
273 : : * cnstr_shdsc_blkcipher - block cipher transformation
274 : : * @descbuf: pointer to descriptor-under-construction buffer
275 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
276 : : * @swap: must be true when core endianness doesn't match SEC endianness
277 : : * @share: sharing type of shared descriptor
278 : : * @cipherdata: pointer to block cipher transform definitions
279 : : * Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
280 : : * Valid modes for:
281 : : * AES: OP_ALG_AAI_* {CBC, CTR}
282 : : * DES, 3DES: OP_ALG_AAI_CBC
283 : : * @iv: IV data; if NULL, "ivlen" bytes from the input frame will be read as IV
284 : : * @ivlen: IV length
285 : : * @dir: DIR_ENC/DIR_DEC
286 : : *
287 : : * Return: size of descriptor written in words or negative number on error
288 : : */
289 : : static inline int
290 : 0 : cnstr_shdsc_blkcipher(uint32_t *descbuf, bool ps, bool swap,
291 : : enum rta_share_type share,
292 : : struct alginfo *cipherdata,
293 : : uint32_t ivlen, uint8_t dir)
294 : : {
295 : : struct program prg;
296 : : struct program *p = &prg;
297 : : uint32_t iv_off = 0, counter;
298 [ # # ]: 0 : const bool need_dk = (dir == DIR_DEC) &&
299 [ # # # # ]: 0 : (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
300 [ # # ]: 0 : (cipherdata->algmode == OP_ALG_AAI_CBC);
301 : : LABEL(keyjmp);
302 : : LABEL(skipdk);
303 : : REFERENCE(pkeyjmp);
304 : : REFERENCE(pskipdk);
305 : :
306 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
307 [ # # ]: 0 : if (swap)
308 : : PROGRAM_SET_BSWAP(p);
309 [ # # ]: 0 : if (ps)
310 : : PROGRAM_SET_36BIT_ADDR(p);
311 : 0 : SHR_HDR(p, share, 1, SC);
312 : :
313 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
314 : : /* Insert Key */
315 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
316 : : cipherdata->keylen, INLINE_KEY(cipherdata));
317 : :
318 [ # # ]: 0 : if (need_dk) {
319 : 0 : ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
320 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
321 : :
322 : 0 : pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0);
323 : : }
324 : : SET_LABEL(p, keyjmp);
325 : :
326 [ # # ]: 0 : if (need_dk) {
327 : 0 : ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
328 : : OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
329 : : ICV_CHECK_DISABLE, dir);
330 : : SET_LABEL(p, skipdk);
331 : : } else {
332 : 0 : ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
333 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
334 : : }
335 : :
336 [ # # ]: 0 : if (cipherdata->algmode == OP_ALG_AAI_CTR)
337 : : iv_off = 16;
338 : :
339 : : /* IV is present first before the actual message */
340 : 0 : SEQLOAD(p, CONTEXT1, iv_off, ivlen, 0);
341 : :
342 : : /* If IV len is less than 16 bytes, set 'counter' as 1 */
343 [ # # # # ]: 0 : if (cipherdata->algmode == OP_ALG_AAI_CTR && ivlen < 16) {
344 : : counter = 1;
345 [ # # ]: 0 : if (!swap)
346 : : counter = swab32(1);
347 : :
348 : 0 : LOAD(p, counter, CONTEXT1, (iv_off + ivlen), 16 - ivlen, IMMED);
349 : : }
350 : :
351 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
352 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
353 : :
354 : : /* Insert sequence load/store with VLF */
355 : 0 : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
356 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
357 : :
358 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
359 [ # # ]: 0 : if (need_dk)
360 : 0 : PATCH_JUMP(p, pskipdk, skipdk);
361 : :
362 : 0 : return PROGRAM_FINALIZE(p);
363 : : }
364 : :
365 : : /**
366 : : * cnstr_shdsc_hmac - HMAC shared
367 : : * @descbuf: pointer to descriptor-under-construction buffer
368 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
369 : : * @swap: must be true when core endianness doesn't match SEC endianness
370 : : * @share: sharing type of shared descriptor
371 : : * @authdata: pointer to authentication transform definitions;
372 : : * message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512.
373 : : * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking
374 : : * is needed for all the packets processed by this shared descriptor
375 : : * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0
376 : : * if no truncation is needed
377 : : *
378 : : * Note: There's no support for keys longer than the block size of the
379 : : * underlying hash function, according to the selected algorithm.
380 : : *
381 : : * Return: size of descriptor written in words or negative number on error
382 : : */
383 : : static inline int
384 : 0 : cnstr_shdsc_hmac(uint32_t *descbuf, bool ps, bool swap,
385 : : enum rta_share_type share,
386 : : struct alginfo *authdata, uint8_t do_icv,
387 : : uint8_t trunc_len)
388 : : {
389 : : struct program prg;
390 : : struct program *p = &prg;
391 : : uint8_t storelen, opicv, dir;
392 : : LABEL(keyjmp);
393 : : LABEL(jmpprecomp);
394 : : REFERENCE(pkeyjmp);
395 : : REFERENCE(pjmpprecomp);
396 : :
397 : : /* Compute fixed-size store based on alg selection */
398 [ # # # # : 0 : switch (authdata->algtype) {
# # # ]
399 : : case OP_ALG_ALGSEL_MD5:
400 : : storelen = 16;
401 : : break;
402 : 0 : case OP_ALG_ALGSEL_SHA1:
403 : : storelen = 20;
404 : 0 : break;
405 : 0 : case OP_ALG_ALGSEL_SHA224:
406 : : storelen = 28;
407 : 0 : break;
408 : 0 : case OP_ALG_ALGSEL_SHA256:
409 : : storelen = 32;
410 : 0 : break;
411 : 0 : case OP_ALG_ALGSEL_SHA384:
412 : : storelen = 48;
413 : 0 : break;
414 : 0 : case OP_ALG_ALGSEL_SHA512:
415 : : storelen = 64;
416 : 0 : break;
417 : : default:
418 : : return -EINVAL;
419 : : }
420 : :
421 [ # # ]: 0 : trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen;
422 : :
423 : 0 : opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
424 [ # # ]: 0 : dir = do_icv ? DIR_DEC : DIR_ENC;
425 : :
426 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
427 [ # # ]: 0 : if (swap)
428 : : PROGRAM_SET_BSWAP(p);
429 [ # # ]: 0 : if (ps)
430 : : PROGRAM_SET_36BIT_ADDR(p);
431 : 0 : SHR_HDR(p, share, 1, SC);
432 : :
433 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
434 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
435 : : INLINE_KEY(authdata));
436 : :
437 : : /* Do operation */
438 : 0 : ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC,
439 : : OP_ALG_AS_INITFINAL, opicv, dir);
440 : :
441 : 0 : pjmpprecomp = JUMP(p, jmpprecomp, LOCAL_JUMP, ALL_TRUE, 0);
442 : : SET_LABEL(p, keyjmp);
443 : :
444 : 0 : ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
445 : : OP_ALG_AS_INITFINAL, opicv, dir);
446 : :
447 : : SET_LABEL(p, jmpprecomp);
448 : :
449 : : /* compute sequences */
450 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE)
451 : 0 : MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
452 : : else
453 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
454 : :
455 : : /* Do load (variable length) */
456 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
457 : :
458 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE)
459 : 0 : SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
460 : : else
461 : 0 : SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
462 : :
463 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
464 : 0 : PATCH_JUMP(p, pjmpprecomp, jmpprecomp);
465 : :
466 : 0 : return PROGRAM_FINALIZE(p);
467 : : }
468 : :
469 : : /**
470 : : * cnstr_shdsc_hash - HASH shared
471 : : * @descbuf: pointer to descriptor-under-construction buffer
472 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
473 : : * @swap: must be true when core endianness doesn't match SEC endianness
474 : : * @share: sharing type of shared descriptor
475 : : * @authdata: pointer to authentication transform definitions;
476 : : * message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512.
477 : : * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking
478 : : * is needed for all the packets processed by this shared descriptor
479 : : * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0
480 : : * if no truncation is needed
481 : : *
482 : : * Note: There's no support for keys longer than the block size of the
483 : : * underlying hash function, according to the selected algorithm.
484 : : *
485 : : * Return: size of descriptor written in words or negative number on error
486 : : */
487 : : static inline int
488 : 0 : cnstr_shdsc_hash(uint32_t *descbuf, bool ps, bool swap,
489 : : enum rta_share_type share,
490 : : struct alginfo *authdata, uint8_t do_icv,
491 : : uint8_t trunc_len)
492 : : {
493 : : struct program prg;
494 : : struct program *p = &prg;
495 : : uint8_t storelen, opicv, dir;
496 : :
497 : : /* Compute fixed-size store based on alg selection */
498 [ # # # # : 0 : switch (authdata->algtype) {
# # # ]
499 : : case OP_ALG_ALGSEL_MD5:
500 : : storelen = 16;
501 : : break;
502 : 0 : case OP_ALG_ALGSEL_SHA1:
503 : : storelen = 20;
504 : 0 : break;
505 : 0 : case OP_ALG_ALGSEL_SHA224:
506 : : storelen = 28;
507 : 0 : break;
508 : 0 : case OP_ALG_ALGSEL_SHA256:
509 : : storelen = 32;
510 : 0 : break;
511 : 0 : case OP_ALG_ALGSEL_SHA384:
512 : : storelen = 48;
513 : 0 : break;
514 : 0 : case OP_ALG_ALGSEL_SHA512:
515 : : storelen = 64;
516 : 0 : break;
517 : : default:
518 : : return -EINVAL;
519 : : }
520 : :
521 [ # # ]: 0 : trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen;
522 : :
523 : 0 : opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
524 [ # # ]: 0 : dir = do_icv ? DIR_DEC : DIR_ENC;
525 : :
526 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
527 [ # # ]: 0 : if (swap)
528 : : PROGRAM_SET_BSWAP(p);
529 [ # # ]: 0 : if (ps)
530 : : PROGRAM_SET_36BIT_ADDR(p);
531 : 0 : SHR_HDR(p, share, 1, SC);
532 : :
533 : : /* Do operation */
534 : : /* compute sequences */
535 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE)
536 : 0 : MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
537 : : else
538 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
539 : :
540 : 0 : ALG_OPERATION(p, authdata->algtype,
541 : : OP_ALG_AAI_HASH,
542 : : OP_ALG_AS_INITFINAL, opicv, dir);
543 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
544 : :
545 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE)
546 : 0 : SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
547 : : else
548 : 0 : SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
549 : :
550 : 0 : return PROGRAM_FINALIZE(p);
551 : : }
552 : :
553 : : /**
554 : : * cnstr_shdsc_kasumi_f8 - KASUMI F8 (Confidentiality) as a shared descriptor
555 : : * (ETSI "Document 1: f8 and f9 specification")
556 : : * @descbuf: pointer to descriptor-under-construction buffer
557 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
558 : : * @swap: must be true when core endianness doesn't match SEC endianness
559 : : * @cipherdata: pointer to block cipher transform definitions
560 : : * @dir: cipher direction (DIR_ENC/DIR_DEC)
561 : : * @count: count value (32 bits)
562 : : * @bearer: bearer ID (5 bits)
563 : : * @direction: direction (1 bit)
564 : : *
565 : : * Return: size of descriptor written in words or negative number on error
566 : : */
567 : : static inline int
568 : : cnstr_shdsc_kasumi_f8(uint32_t *descbuf, bool ps, bool swap,
569 : : struct alginfo *cipherdata, uint8_t dir)
570 : : {
571 : : struct program prg;
572 : : struct program *p = &prg;
573 : :
574 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
575 : : if (swap)
576 : : PROGRAM_SET_BSWAP(p);
577 : : if (ps)
578 : : PROGRAM_SET_36BIT_ADDR(p);
579 : : SHR_HDR(p, SHR_ALWAYS, 1, 0);
580 : :
581 : : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
582 : : cipherdata->keylen, INLINE_KEY(cipherdata));
583 : : SEQLOAD(p, CONTEXT1, 0, 8, 0);
584 : : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
585 : : MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
586 : : ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F8,
587 : : OP_ALG_AS_INITFINAL, 0, dir);
588 : : SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
589 : : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
590 : :
591 : : return PROGRAM_FINALIZE(p);
592 : : }
593 : :
594 : : /**
595 : : * cnstr_shdsc_kasumi_f9 - KASUMI F9 (Integrity) as a shared descriptor
596 : : * (ETSI "Document 1: f8 and f9 specification")
597 : : * @descbuf: pointer to descriptor-under-construction buffer
598 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
599 : : * @swap: must be true when core endianness doesn't match SEC endianness
600 : : * @authdata: pointer to authentication transform definitions
601 : : * @chk_icv: check or generate ICV value
602 : : * @authlen: size of digest
603 : : *
604 : : * Return: size of descriptor written in words or negative number on error
605 : : */
606 : : static inline int
607 : : cnstr_shdsc_kasumi_f9(uint32_t *descbuf, bool ps, bool swap,
608 : : struct alginfo *authdata, uint8_t chk_icv,
609 : : uint32_t authlen)
610 : : {
611 : : struct program prg;
612 : : struct program *p = &prg;
613 : : int dir = chk_icv ? DIR_DEC : DIR_ENC;
614 : :
615 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
616 : : if (swap)
617 : : PROGRAM_SET_BSWAP(p);
618 : :
619 : : if (ps)
620 : : PROGRAM_SET_36BIT_ADDR(p);
621 : :
622 : : SHR_HDR(p, SHR_ALWAYS, 1, 0);
623 : :
624 : : KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
625 : : authdata->keylen, INLINE_KEY(authdata));
626 : :
627 : : SEQLOAD(p, CONTEXT2, 0, 12, 0);
628 : :
629 : : if (chk_icv == ICV_CHECK_ENABLE)
630 : : MATHB(p, SEQINSZ, SUB, authlen, VSEQINSZ, 4, IMMED2);
631 : : else
632 : : MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
633 : :
634 : : ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F9,
635 : : OP_ALG_AS_INITFINAL, chk_icv, dir);
636 : :
637 : : SEQFIFOLOAD(p, MSG2, 0, VLF | CLASS2 | LAST2);
638 : :
639 : : if (chk_icv == ICV_CHECK_ENABLE)
640 : : SEQFIFOLOAD(p, ICV2, authlen, LAST2);
641 : : else
642 : : /* Save lower half of MAC out into a 32-bit sequence */
643 : : SEQSTORE(p, CONTEXT2, 0, authlen, 0);
644 : :
645 : : return PROGRAM_FINALIZE(p);
646 : : }
647 : :
648 : : /**
649 : : * cnstr_shdsc_crc - CRC32 Accelerator (IEEE 802 CRC32 protocol mode)
650 : : * @descbuf: pointer to descriptor-under-construction buffer
651 : : * @swap: must be true when core endianness doesn't match SEC endianness
652 : : *
653 : : * Return: size of descriptor written in words or negative number on error
654 : : */
655 : : static inline int
656 : : cnstr_shdsc_crc(uint32_t *descbuf, bool swap)
657 : : {
658 : : struct program prg;
659 : : struct program *p = &prg;
660 : :
661 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
662 : : if (swap)
663 : : PROGRAM_SET_BSWAP(p);
664 : :
665 : : SHR_HDR(p, SHR_ALWAYS, 1, 0);
666 : :
667 : : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
668 : : ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
669 : : OP_ALG_AAI_802 | OP_ALG_AAI_DOC,
670 : : OP_ALG_AS_FINALIZE, 0, DIR_ENC);
671 : : SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
672 : : SEQSTORE(p, CONTEXT2, 0, 4, 0);
673 : :
674 : : return PROGRAM_FINALIZE(p);
675 : : }
676 : :
677 : : /**
678 : : * cnstr_shdsc_gcm_encap - AES-GCM encap as a shared descriptor
679 : : * @descbuf: pointer to descriptor-under-construction buffer
680 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
681 : : * @swap: must be true when core endianness doesn't match SEC endianness
682 : : * @share: sharing type of shared descriptor
683 : : * @cipherdata: pointer to block cipher transform definitions
684 : : * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
685 : : * OP_ALG_AAI_GCM.
686 : : * @ivlen: Initialization vector length
687 : : * @icvsize: integrity check value (ICV) size (truncated or full)
688 : : *
689 : : * Return: size of descriptor written in words or negative number on error
690 : : */
691 : : static inline int
692 [ # # ]: 0 : cnstr_shdsc_gcm_encap(uint32_t *descbuf, bool ps, bool swap,
693 : : enum rta_share_type share,
694 : : struct alginfo *cipherdata,
695 : : uint32_t ivlen, uint32_t icvsize)
696 : : {
697 : : struct program prg;
698 : : struct program *p = &prg;
699 : :
700 : : LABEL(keyjmp);
701 : : LABEL(zeroassocjump2);
702 : : LABEL(zeroassocjump1);
703 : : LABEL(zeropayloadjump);
704 : : REFERENCE(pkeyjmp);
705 : : REFERENCE(pzeroassocjump2);
706 : : REFERENCE(pzeroassocjump1);
707 : : REFERENCE(pzeropayloadjump);
708 : :
709 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
710 : :
711 [ # # ]: 0 : if (swap)
712 : : PROGRAM_SET_BSWAP(p);
713 [ # # ]: 0 : if (ps)
714 : : PROGRAM_SET_36BIT_ADDR(p);
715 : :
716 : 0 : SHR_HDR(p, share, 1, SC);
717 : :
718 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
719 : : /* Insert Key */
720 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
721 : : cipherdata->keylen, INLINE_KEY(cipherdata));
722 : :
723 : : SET_LABEL(p, keyjmp);
724 : :
725 : : /* class 1 operation */
726 : 0 : ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
727 : : OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
728 : :
729 : 0 : MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
730 : :
731 : : /* if assoclen + cryptlen is ZERO, skip to ICV write */
732 : 0 : MATHB(p, SEQINSZ, SUB, ivlen, VSEQOUTSZ, 4, IMMED2);
733 : 0 : pzeroassocjump2 = JUMP(p, zeroassocjump2, LOCAL_JUMP, ALL_TRUE, MATH_Z);
734 : :
735 : 0 : SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
736 : :
737 : : /* if assoclen is ZERO, skip reading the assoc data */
738 : 0 : MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
739 : 0 : pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
740 : :
741 : : /* cryptlen = seqinlen - assoclen */
742 : 0 : MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
743 : :
744 : : /* if cryptlen is ZERO jump to zero-payload commands */
745 : 0 : pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
746 : : MATH_Z);
747 : :
748 : : /* read assoc data */
749 : 0 : SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
750 : : SET_LABEL(p, zeroassocjump1);
751 : :
752 : 0 : MATHB(p, SEQINSZ, SUB, MATH0, VSEQINSZ, 4, 0);
753 : :
754 : : /* write encrypted data */
755 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
756 : :
757 : : /* read payload data */
758 : 0 : SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | LAST1);
759 : :
760 : : /* jump the zero-payload commands */
761 : 0 : JUMP(p, 4, LOCAL_JUMP, ALL_TRUE, 0);
762 : :
763 : : /* zero-payload commands */
764 : : SET_LABEL(p, zeropayloadjump);
765 : :
766 : : /* read assoc data */
767 : 0 : SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | LAST1);
768 : :
769 : 0 : JUMP(p, 2, LOCAL_JUMP, ALL_TRUE, 0);
770 : :
771 : : /* There is no input data */
772 : : SET_LABEL(p, zeroassocjump2);
773 : :
774 : 0 : SEQFIFOLOAD(p, IV1, ivlen, FLUSH1 | LAST1);
775 : :
776 : : /* write ICV */
777 : 0 : SEQSTORE(p, CONTEXT1, 0, icvsize, 0);
778 : :
779 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
780 : 0 : PATCH_JUMP(p, pzeroassocjump2, zeroassocjump2);
781 : 0 : PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
782 : 0 : PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
783 : :
784 : 0 : return PROGRAM_FINALIZE(p);
785 : : }
786 : :
787 : : /**
788 : : * cnstr_shdsc_gcm_decap - AES-GCM decap as a shared descriptor
789 : : * @descbuf: pointer to descriptor-under-construction buffer
790 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
791 : : * @swap: must be true when core endianness doesn't match SEC endianness
792 : : * @share: sharing type of shared descriptor
793 : : * @cipherdata: pointer to block cipher transform definitions
794 : : * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
795 : : * OP_ALG_AAI_GCM.
796 : : * @icvsize: integrity check value (ICV) size (truncated or full)
797 : : *
798 : : * Return: size of descriptor written in words or negative number on error
799 : : */
800 : : static inline int
801 [ # # ]: 0 : cnstr_shdsc_gcm_decap(uint32_t *descbuf, bool ps, bool swap,
802 : : enum rta_share_type share,
803 : : struct alginfo *cipherdata,
804 : : uint32_t ivlen, uint32_t icvsize)
805 : : {
806 : : struct program prg;
807 : : struct program *p = &prg;
808 : :
809 : : LABEL(keyjmp);
810 : : LABEL(zeroassocjump1);
811 : : LABEL(zeropayloadjump);
812 : : REFERENCE(pkeyjmp);
813 : : REFERENCE(pzeroassocjump1);
814 : : REFERENCE(pzeropayloadjump);
815 : :
816 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
817 : :
818 [ # # ]: 0 : if (swap)
819 : : PROGRAM_SET_BSWAP(p);
820 [ # # ]: 0 : if (ps)
821 : : PROGRAM_SET_36BIT_ADDR(p);
822 : :
823 : 0 : SHR_HDR(p, share, 1, SC);
824 : :
825 : 0 : pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
826 : : /* Insert Key */
827 : 0 : KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
828 : : cipherdata->keylen, INLINE_KEY(cipherdata));
829 : :
830 : : SET_LABEL(p, keyjmp);
831 : :
832 : : /* class 1 operation */
833 : 0 : ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
834 : : OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
835 : :
836 : 0 : MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
837 : 0 : SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
838 : :
839 : : /* if assoclen is ZERO, skip reading the assoc data */
840 : 0 : MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
841 : 0 : pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
842 : :
843 : : /* read assoc data */
844 : 0 : SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
845 : :
846 : : SET_LABEL(p, zeroassocjump1);
847 : :
848 : : /* cryptlen = seqoutlen - assoclen */
849 : 0 : MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQINSZ, 4, 0);
850 : :
851 : : /* jump to zero-payload command if cryptlen is zero */
852 : 0 : pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
853 : : MATH_Z);
854 : :
855 : 0 : MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQOUTSZ, 4, 0);
856 : :
857 : : /* store encrypted data */
858 : 0 : SEQFIFOSTORE(p, MSG, 0, 0, VLF);
859 : :
860 : : /* read payload data */
861 : 0 : SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | FLUSH1);
862 : :
863 : : /* zero-payload command */
864 : : SET_LABEL(p, zeropayloadjump);
865 : :
866 : : /* read ICV */
867 : 0 : SEQFIFOLOAD(p, ICV1, icvsize, CLASS1 | LAST1);
868 : :
869 : 0 : PATCH_JUMP(p, pkeyjmp, keyjmp);
870 : 0 : PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
871 : 0 : PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
872 : :
873 : 0 : return PROGRAM_FINALIZE(p);
874 : : }
875 : :
876 : : /**
877 : : * cnstr_shdsc_aes_mac - AES_XCBC_MAC, CMAC cases
878 : : * @descbuf: pointer to descriptor-under-construction buffer
879 : : * @ps: if 36/40bit addressing is desired, this parameter must be true
880 : : * @swap: must be true when core endianness doesn't match SEC endianness
881 : : * @share: sharing type of shared descriptor
882 : : * @authdata: pointer to authentication transform definitions;
883 : : * message digest algorithm: OP_ALG_ALGSEL_AES.
884 : : * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking
885 : : * is needed for all the packets processed by this shared descriptor
886 : : * @trunc_len: Length of the truncated ICV to be written in the output buffer,
887 : : * 0 if no truncation is needed
888 : : *
889 : : * Note: There's no support for keys longer than the block size of the
890 : : * underlying hash function, according to the selected algorithm.
891 : : *
892 : : * Return: size of descriptor written in words or negative number on error
893 : : */
894 : : static inline int
895 : 0 : cnstr_shdsc_aes_mac(uint32_t *descbuf, bool ps, bool swap,
896 : : enum rta_share_type share,
897 : : struct alginfo *authdata, uint8_t do_icv,
898 : : uint8_t trunc_len)
899 : : {
900 : : struct program prg;
901 : : struct program *p = &prg;
902 : : uint8_t opicv, dir;
903 : :
904 : 0 : opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
905 [ # # ]: 0 : dir = do_icv ? DIR_DEC : DIR_ENC;
906 : :
907 : : PROGRAM_CNTXT_INIT(p, descbuf, 0);
908 [ # # ]: 0 : if (swap)
909 : : PROGRAM_SET_BSWAP(p);
910 [ # # ]: 0 : if (ps)
911 : : PROGRAM_SET_36BIT_ADDR(p);
912 : 0 : SHR_HDR(p, share, 1, SC);
913 : :
914 : 0 : KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
915 : : INLINE_KEY(authdata));
916 : :
917 : : /* compute sequences */
918 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE)
919 : 0 : MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
920 : : else
921 : 0 : MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
922 : :
923 : : /* Do operation */
924 : 0 : ALG_OPERATION_NP(p, authdata->algtype, authdata->algmode,
925 : : OP_ALG_AS_INITFINAL, opicv, dir);
926 : :
927 : : /* Do load (variable length) */
928 : 0 : SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
929 : :
930 [ # # ]: 0 : if (opicv == ICV_CHECK_ENABLE) {
931 : 0 : LOAD(p, trunc_len, ICV2SZ, 0, 4, IMMED);
932 : 0 : SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
933 : : } else
934 : 0 : SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
935 : :
936 : 0 : return PROGRAM_FINALIZE(p);
937 : : }
938 : :
939 : : #endif /* __DESC_ALGO_H__ */
|