2 * Copyright 2008-2016 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
7 #ifndef __DESC_ALGO_H__
8 #define __DESC_ALGO_H__
14 * DOC: Algorithms - Shared Descriptor Constructors
16 * Shared descriptors for algorithms (i.e. not for protocols).
20 * cnstr_shdsc_snow_f8 - SNOW/f8 (UEA2) as a shared descriptor
21 * @descbuf: pointer to descriptor-under-construction buffer
22 * @ps: if 36/40bit addressing is desired, this parameter must be true
23 * @swap: must be true when core endianness doesn't match SEC endianness
24 * @cipherdata: pointer to block cipher transform definitions
25 * @dir: Cipher direction (DIR_ENC/DIR_DEC)
26 * @count: UEA2 count value (32 bits)
27 * @bearer: UEA2 bearer ID (5 bits)
28 * @direction: UEA2 direction (1 bit)
30 * Return: size of descriptor written in words or negative number on error
33 cnstr_shdsc_snow_f8(uint32_t *descbuf, bool ps, bool swap,
34 struct alginfo *cipherdata, uint8_t dir,
35 uint32_t count, uint8_t bearer, uint8_t direction)
38 struct program *p = &prg;
41 uint8_t dr = direction;
42 uint32_t context[2] = {ct, (br << 27) | (dr << 26)};
44 PROGRAM_CNTXT_INIT(p, descbuf, 0);
48 context[0] = swab32(context[0]);
49 context[1] = swab32(context[1]);
53 PROGRAM_SET_36BIT_ADDR(p);
54 SHR_HDR(p, SHR_ALWAYS, 1, 0);
56 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
57 cipherdata->keylen, INLINE_KEY(cipherdata));
58 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
59 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
60 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
61 OP_ALG_AS_INITFINAL, 0, dir);
62 LOAD(p, (uintptr_t)context, CONTEXT1, 0, 8, IMMED | COPY);
63 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
64 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
66 return PROGRAM_FINALIZE(p);
70 * cnstr_shdsc_snow_f9 - SNOW/f9 (UIA2) as a shared descriptor
71 * @descbuf: pointer to descriptor-under-construction buffer
72 * @ps: if 36/40bit addressing is desired, this parameter must be true
73 * @swap: must be true when core endianness doesn't match SEC endianness
74 * @authdata: pointer to authentication transform definitions
75 * @dir: cipher direction (DIR_ENC/DIR_DEC)
76 * @count: UEA2 count value (32 bits)
77 * @fresh: UEA2 fresh value ID (32 bits)
78 * @direction: UEA2 direction (1 bit)
79 * @datalen: size of data
81 * Return: size of descriptor written in words or negative number on error
84 cnstr_shdsc_snow_f9(uint32_t *descbuf, bool ps, bool swap,
85 struct alginfo *authdata, uint8_t dir, uint32_t count,
86 uint32_t fresh, uint8_t direction, uint32_t datalen)
89 struct program *p = &prg;
92 uint64_t dr = direction;
95 context[0] = (ct << 32) | (dr << 26);
96 context[1] = fr << 32;
98 PROGRAM_CNTXT_INIT(p, descbuf, 0);
100 PROGRAM_SET_BSWAP(p);
102 context[0] = swab64(context[0]);
103 context[1] = swab64(context[1]);
106 PROGRAM_SET_36BIT_ADDR(p);
107 SHR_HDR(p, SHR_ALWAYS, 1, 0);
109 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
110 INLINE_KEY(authdata));
111 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
112 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
113 OP_ALG_AS_INITFINAL, 0, dir);
114 LOAD(p, (uintptr_t)context, CONTEXT2, 0, 16, IMMED | COPY);
115 SEQFIFOLOAD(p, BIT_DATA, datalen, CLASS2 | LAST2);
116 /* Save lower half of MAC out into a 32-bit sequence */
117 SEQSTORE(p, CONTEXT2, 0, 4, 0);
119 return PROGRAM_FINALIZE(p);
123 * cnstr_shdsc_blkcipher - block cipher transformation
124 * @descbuf: pointer to descriptor-under-construction buffer
125 * @ps: if 36/40bit addressing is desired, this parameter must be true
126 * @swap: must be true when core endianness doesn't match SEC endianness
127 * @cipherdata: pointer to block cipher transform definitions
128 * @iv: IV data; if NULL, "ivlen" bytes from the input frame will be read as IV
130 * @dir: DIR_ENC/DIR_DEC
132 * Return: size of descriptor written in words or negative number on error
135 cnstr_shdsc_blkcipher(uint32_t *descbuf, bool ps, bool swap,
136 struct alginfo *cipherdata, uint8_t *iv,
137 uint32_t ivlen, uint8_t dir)
140 struct program *p = &prg;
141 const bool is_aes_dec = (dir == DIR_DEC) &&
142 (cipherdata->algtype == OP_ALG_ALGSEL_AES);
148 PROGRAM_CNTXT_INIT(p, descbuf, 0);
150 PROGRAM_SET_BSWAP(p);
152 PROGRAM_SET_36BIT_ADDR(p);
153 SHR_HDR(p, SHR_SERIAL, 1, SC);
155 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
157 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
158 cipherdata->keylen, INLINE_KEY(cipherdata));
161 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
162 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
164 pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0);
166 SET_LABEL(p, keyjmp);
169 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
170 OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
171 ICV_CHECK_DISABLE, dir);
172 SET_LABEL(p, skipdk);
174 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
175 OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
179 /* IV load, convert size */
180 LOAD(p, (uintptr_t)iv, CONTEXT1, 0, ivlen, IMMED | COPY);
182 /* IV is present first before the actual message */
183 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
185 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
186 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
188 /* Insert sequence load/store with VLF */
189 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
190 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
192 PATCH_JUMP(p, pkeyjmp, keyjmp);
194 PATCH_JUMP(p, pskipdk, skipdk);
196 return PROGRAM_FINALIZE(p);
200 * cnstr_shdsc_hmac - HMAC shared
201 * @descbuf: pointer to descriptor-under-construction buffer
202 * @ps: if 36/40bit addressing is desired, this parameter must be true
203 * @swap: must be true when core endianness doesn't match SEC endianness
204 * @authdata: pointer to authentication transform definitions;
205 * message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512.
206 * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking
207 * is needed for all the packets processed by this shared descriptor
208 * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0
209 * if no truncation is needed
211 * Note: There's no support for keys longer than the block size of the
212 * underlying hash function, according to the selected algorithm.
214 * Return: size of descriptor written in words or negative number on error
217 cnstr_shdsc_hmac(uint32_t *descbuf, bool ps, bool swap,
218 struct alginfo *authdata, uint8_t do_icv,
222 struct program *p = &prg;
223 uint8_t storelen, opicv, dir;
227 REFERENCE(pjmpprecomp);
229 /* Compute fixed-size store based on alg selection */
230 switch (authdata->algtype) {
231 case OP_ALG_ALGSEL_MD5:
234 case OP_ALG_ALGSEL_SHA1:
237 case OP_ALG_ALGSEL_SHA224:
240 case OP_ALG_ALGSEL_SHA256:
243 case OP_ALG_ALGSEL_SHA384:
246 case OP_ALG_ALGSEL_SHA512:
253 trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen;
255 opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
256 dir = do_icv ? DIR_DEC : DIR_ENC;
258 PROGRAM_CNTXT_INIT(p, descbuf, 0);
260 PROGRAM_SET_BSWAP(p);
262 PROGRAM_SET_36BIT_ADDR(p);
263 SHR_HDR(p, SHR_SERIAL, 1, SC);
265 pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
266 KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
267 INLINE_KEY(authdata));
270 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC,
271 OP_ALG_AS_INITFINAL, opicv, dir);
273 pjmpprecomp = JUMP(p, jmpprecomp, LOCAL_JUMP, ALL_TRUE, 0);
274 SET_LABEL(p, keyjmp);
276 ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
277 OP_ALG_AS_INITFINAL, opicv, dir);
279 SET_LABEL(p, jmpprecomp);
281 /* compute sequences */
282 if (opicv == ICV_CHECK_ENABLE)
283 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
285 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
287 /* Do load (variable length) */
288 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
290 if (opicv == ICV_CHECK_ENABLE)
291 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
293 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
295 PATCH_JUMP(p, pkeyjmp, keyjmp);
296 PATCH_JUMP(p, pjmpprecomp, jmpprecomp);
298 return PROGRAM_FINALIZE(p);
302 * cnstr_shdsc_kasumi_f8 - KASUMI F8 (Confidentiality) as a shared descriptor
303 * (ETSI "Document 1: f8 and f9 specification")
304 * @descbuf: pointer to descriptor-under-construction buffer
305 * @ps: if 36/40bit addressing is desired, this parameter must be true
306 * @swap: must be true when core endianness doesn't match SEC endianness
307 * @cipherdata: pointer to block cipher transform definitions
308 * @dir: cipher direction (DIR_ENC/DIR_DEC)
309 * @count: count value (32 bits)
310 * @bearer: bearer ID (5 bits)
311 * @direction: direction (1 bit)
313 * Return: size of descriptor written in words or negative number on error
316 cnstr_shdsc_kasumi_f8(uint32_t *descbuf, bool ps, bool swap,
317 struct alginfo *cipherdata, uint8_t dir,
318 uint32_t count, uint8_t bearer, uint8_t direction)
321 struct program *p = &prg;
323 uint64_t br = bearer;
324 uint64_t dr = direction;
325 uint32_t context[2] = { ct, (br << 27) | (dr << 26) };
327 PROGRAM_CNTXT_INIT(p, descbuf, 0);
329 PROGRAM_SET_BSWAP(p);
331 context[0] = swab32(context[0]);
332 context[1] = swab32(context[1]);
335 PROGRAM_SET_36BIT_ADDR(p);
336 SHR_HDR(p, SHR_ALWAYS, 1, 0);
338 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
339 cipherdata->keylen, INLINE_KEY(cipherdata));
340 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
341 MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
342 ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F8,
343 OP_ALG_AS_INITFINAL, 0, dir);
344 LOAD(p, (uintptr_t)context, CONTEXT1, 0, 8, IMMED | COPY);
345 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
346 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
348 return PROGRAM_FINALIZE(p);
352 * cnstr_shdsc_kasumi_f9 - KASUMI F9 (Integrity) as a shared descriptor
353 * (ETSI "Document 1: f8 and f9 specification")
354 * @descbuf: pointer to descriptor-under-construction buffer
355 * @ps: if 36/40bit addressing is desired, this parameter must be true
356 * @swap: must be true when core endianness doesn't match SEC endianness
357 * @authdata: pointer to authentication transform definitions
358 * @dir: cipher direction (DIR_ENC/DIR_DEC)
359 * @count: count value (32 bits)
360 * @fresh: fresh value ID (32 bits)
361 * @direction: direction (1 bit)
362 * @datalen: size of data
364 * Return: size of descriptor written in words or negative number on error
367 cnstr_shdsc_kasumi_f9(uint32_t *descbuf, bool ps, bool swap,
368 struct alginfo *authdata, uint8_t dir,
369 uint32_t count, uint32_t fresh, uint8_t direction,
373 struct program *p = &prg;
374 uint16_t ctx_offset = 16;
375 uint32_t context[6] = {count, direction << 26, fresh, 0, 0, 0};
377 PROGRAM_CNTXT_INIT(p, descbuf, 0);
379 PROGRAM_SET_BSWAP(p);
381 context[0] = swab32(context[0]);
382 context[1] = swab32(context[1]);
383 context[2] = swab32(context[2]);
386 PROGRAM_SET_36BIT_ADDR(p);
387 SHR_HDR(p, SHR_ALWAYS, 1, 0);
389 KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
390 INLINE_KEY(authdata));
391 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
392 ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F9,
393 OP_ALG_AS_INITFINAL, 0, dir);
394 LOAD(p, (uintptr_t)context, CONTEXT1, 0, 24, IMMED | COPY);
395 SEQFIFOLOAD(p, BIT_DATA, datalen, CLASS1 | LAST1);
396 /* Save output MAC of DWORD 2 into a 32-bit sequence */
397 SEQSTORE(p, CONTEXT1, ctx_offset, 4, 0);
399 return PROGRAM_FINALIZE(p);
403 * cnstr_shdsc_crc - CRC32 Accelerator (IEEE 802 CRC32 protocol mode)
404 * @descbuf: pointer to descriptor-under-construction buffer
405 * @swap: must be true when core endianness doesn't match SEC endianness
407 * Return: size of descriptor written in words or negative number on error
410 cnstr_shdsc_crc(uint32_t *descbuf, bool swap)
413 struct program *p = &prg;
415 PROGRAM_CNTXT_INIT(p, descbuf, 0);
417 PROGRAM_SET_BSWAP(p);
419 SHR_HDR(p, SHR_ALWAYS, 1, 0);
421 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
422 ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
423 OP_ALG_AAI_802 | OP_ALG_AAI_DOC,
424 OP_ALG_AS_FINALIZE, 0, DIR_ENC);
425 SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
426 SEQSTORE(p, CONTEXT2, 0, 4, 0);
428 return PROGRAM_FINALIZE(p);
431 #endif /* __DESC_ALGO_H__ */