bac6b05624b00534aafd8ab85773e075b08bc150
[dpdk.git] / drivers / crypto / dpaa2_sec / hw / desc / algo.h
1 /*
2  * Copyright 2008-2016 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
5  */
6
7 #ifndef __DESC_ALGO_H__
8 #define __DESC_ALGO_H__
9
10 #include "hw/rta.h"
11 #include "common.h"
12
13 /**
14  * DOC: Algorithms - Shared Descriptor Constructors
15  *
16  * Shared descriptors for algorithms (i.e. not for protocols).
17  */
18
19 /**
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)
29  *
30  * Return: size of descriptor written in words or negative number on error
31  */
32 static inline int
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)
36 {
37         struct program prg;
38         struct program *p = &prg;
39         uint32_t ct = count;
40         uint8_t br = bearer;
41         uint8_t dr = direction;
42         uint32_t context[2] = {ct, (br << 27) | (dr << 26)};
43
44         PROGRAM_CNTXT_INIT(p, descbuf, 0);
45         if (swap) {
46                 PROGRAM_SET_BSWAP(p);
47
48                 context[0] = swab32(context[0]);
49                 context[1] = swab32(context[1]);
50         }
51
52         if (ps)
53                 PROGRAM_SET_36BIT_ADDR(p);
54         SHR_HDR(p, SHR_ALWAYS, 1, 0);
55
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);
65
66         return PROGRAM_FINALIZE(p);
67 }
68
69 /**
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
80  *
81  * Return: size of descriptor written in words or negative number on error
82  */
83 static inline int
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)
87 {
88         struct program prg;
89         struct program *p = &prg;
90         uint64_t ct = count;
91         uint64_t fr = fresh;
92         uint64_t dr = direction;
93         uint64_t context[2];
94
95         context[0] = (ct << 32) | (dr << 26);
96         context[1] = fr << 32;
97
98         PROGRAM_CNTXT_INIT(p, descbuf, 0);
99         if (swap) {
100                 PROGRAM_SET_BSWAP(p);
101
102                 context[0] = swab64(context[0]);
103                 context[1] = swab64(context[1]);
104         }
105         if (ps)
106                 PROGRAM_SET_36BIT_ADDR(p);
107         SHR_HDR(p, SHR_ALWAYS, 1, 0);
108
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);
118
119         return PROGRAM_FINALIZE(p);
120 }
121
122 /**
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
129  * @ivlen: IV length
130  * @dir: DIR_ENC/DIR_DEC
131  *
132  * Return: size of descriptor written in words or negative number on error
133  */
134 static inline int
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)
138 {
139         struct program prg;
140         struct program *p = &prg;
141         const bool is_aes_dec = (dir == DIR_DEC) &&
142                                 (cipherdata->algtype == OP_ALG_ALGSEL_AES);
143         LABEL(keyjmp);
144         LABEL(skipdk);
145         REFERENCE(pkeyjmp);
146         REFERENCE(pskipdk);
147
148         PROGRAM_CNTXT_INIT(p, descbuf, 0);
149         if (swap)
150                 PROGRAM_SET_BSWAP(p);
151         if (ps)
152                 PROGRAM_SET_36BIT_ADDR(p);
153         SHR_HDR(p, SHR_SERIAL, 1, SC);
154
155         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
156         /* Insert Key */
157         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
158             cipherdata->keylen, INLINE_KEY(cipherdata));
159
160         if (is_aes_dec) {
161                 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
162                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
163
164                 pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0);
165         }
166         SET_LABEL(p, keyjmp);
167
168         if (is_aes_dec) {
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);
173         } else {
174                 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
175                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
176         }
177
178         if (iv)
179                 /* IV load, convert size */
180                 LOAD(p, (uintptr_t)iv, CONTEXT1, 0, ivlen, IMMED | COPY);
181         else
182                 /* IV is present first before the actual message */
183                 SEQLOAD(p, CONTEXT1, 0, ivlen, 0);
184
185         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
186         MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
187
188         /* Insert sequence load/store with VLF */
189         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
190         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
191
192         PATCH_JUMP(p, pkeyjmp, keyjmp);
193         if (is_aes_dec)
194                 PATCH_JUMP(p, pskipdk, skipdk);
195
196         return PROGRAM_FINALIZE(p);
197 }
198
199 /**
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
210  *
211  * Note: There's no support for keys longer than the block size of the
212  * underlying hash function, according to the selected algorithm.
213  *
214  * Return: size of descriptor written in words or negative number on error
215  */
216 static inline int
217 cnstr_shdsc_hmac(uint32_t *descbuf, bool ps, bool swap,
218                  struct alginfo *authdata, uint8_t do_icv,
219                  uint8_t trunc_len)
220 {
221         struct program prg;
222         struct program *p = &prg;
223         uint8_t storelen, opicv, dir;
224         LABEL(keyjmp);
225         LABEL(jmpprecomp);
226         REFERENCE(pkeyjmp);
227         REFERENCE(pjmpprecomp);
228
229         /* Compute fixed-size store based on alg selection */
230         switch (authdata->algtype) {
231         case OP_ALG_ALGSEL_MD5:
232                 storelen = 16;
233                 break;
234         case OP_ALG_ALGSEL_SHA1:
235                 storelen = 20;
236                 break;
237         case OP_ALG_ALGSEL_SHA224:
238                 storelen = 28;
239                 break;
240         case OP_ALG_ALGSEL_SHA256:
241                 storelen = 32;
242                 break;
243         case OP_ALG_ALGSEL_SHA384:
244                 storelen = 48;
245                 break;
246         case OP_ALG_ALGSEL_SHA512:
247                 storelen = 64;
248                 break;
249         default:
250                 return -EINVAL;
251         }
252
253         trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen;
254
255         opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
256         dir = do_icv ? DIR_DEC : DIR_ENC;
257
258         PROGRAM_CNTXT_INIT(p, descbuf, 0);
259         if (swap)
260                 PROGRAM_SET_BSWAP(p);
261         if (ps)
262                 PROGRAM_SET_36BIT_ADDR(p);
263         SHR_HDR(p, SHR_SERIAL, 1, SC);
264
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));
268
269         /* Do operation */
270         ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC,
271                       OP_ALG_AS_INITFINAL, opicv, dir);
272
273         pjmpprecomp = JUMP(p, jmpprecomp, LOCAL_JUMP, ALL_TRUE, 0);
274         SET_LABEL(p, keyjmp);
275
276         ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
277                       OP_ALG_AS_INITFINAL, opicv, dir);
278
279         SET_LABEL(p, jmpprecomp);
280
281         /* compute sequences */
282         if (opicv == ICV_CHECK_ENABLE)
283                 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
284         else
285                 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
286
287         /* Do load (variable length) */
288         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
289
290         if (opicv == ICV_CHECK_ENABLE)
291                 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
292         else
293                 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
294
295         PATCH_JUMP(p, pkeyjmp, keyjmp);
296         PATCH_JUMP(p, pjmpprecomp, jmpprecomp);
297
298         return PROGRAM_FINALIZE(p);
299 }
300
301 /**
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)
312  *
313  * Return: size of descriptor written in words or negative number on error
314  */
315 static inline int
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)
319 {
320         struct program prg;
321         struct program *p = &prg;
322         uint64_t ct = count;
323         uint64_t br = bearer;
324         uint64_t dr = direction;
325         uint32_t context[2] = { ct, (br << 27) | (dr << 26) };
326
327         PROGRAM_CNTXT_INIT(p, descbuf, 0);
328         if (swap) {
329                 PROGRAM_SET_BSWAP(p);
330
331                 context[0] = swab32(context[0]);
332                 context[1] = swab32(context[1]);
333         }
334         if (ps)
335                 PROGRAM_SET_36BIT_ADDR(p);
336         SHR_HDR(p, SHR_ALWAYS, 1, 0);
337
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);
347
348         return PROGRAM_FINALIZE(p);
349 }
350
351 /**
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
363  *
364  * Return: size of descriptor written in words or negative number on error
365  */
366 static inline int
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,
370                       uint32_t datalen)
371 {
372         struct program prg;
373         struct program *p = &prg;
374         uint16_t ctx_offset = 16;
375         uint32_t context[6] = {count, direction << 26, fresh, 0, 0, 0};
376
377         PROGRAM_CNTXT_INIT(p, descbuf, 0);
378         if (swap) {
379                 PROGRAM_SET_BSWAP(p);
380
381                 context[0] = swab32(context[0]);
382                 context[1] = swab32(context[1]);
383                 context[2] = swab32(context[2]);
384         }
385         if (ps)
386                 PROGRAM_SET_36BIT_ADDR(p);
387         SHR_HDR(p, SHR_ALWAYS, 1, 0);
388
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);
398
399         return PROGRAM_FINALIZE(p);
400 }
401
402 /**
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
406  *
407  * Return: size of descriptor written in words or negative number on error
408  */
409 static inline int
410 cnstr_shdsc_crc(uint32_t *descbuf, bool swap)
411 {
412         struct program prg;
413         struct program *p = &prg;
414
415         PROGRAM_CNTXT_INIT(p, descbuf, 0);
416         if (swap)
417                 PROGRAM_SET_BSWAP(p);
418
419         SHR_HDR(p, SHR_ALWAYS, 1, 0);
420
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);
427
428         return PROGRAM_FINALIZE(p);
429 }
430
431 #endif /* __DESC_ALGO_H__ */