drivers/crypto: update inline desc for sharing mode
[dpdk.git] / drivers / crypto / dpaa2_sec / hw / desc / algo.h
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2008-2016 Freescale Semiconductor Inc.
4  * Copyright 2016,2019 NXP
5  *
6  */
7
8 #ifndef __DESC_ALGO_H__
9 #define __DESC_ALGO_H__
10
11 #include "hw/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_snow_f8 - SNOW/f8 (UEA2) 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  * @count: UEA2 count value (32 bits)
28  * @bearer: UEA2 bearer ID (5 bits)
29  * @direction: UEA2 direction (1 bit)
30  *
31  * Return: size of descriptor written in words or negative number on error
32  */
33 static inline int
34 cnstr_shdsc_snow_f8(uint32_t *descbuf, bool ps, bool swap,
35                     struct alginfo *cipherdata, uint8_t dir,
36                     uint32_t count, uint8_t bearer, uint8_t direction)
37 {
38         struct program prg;
39         struct program *p = &prg;
40         uint32_t ct = count;
41         uint8_t br = bearer;
42         uint8_t dr = direction;
43         uint32_t context[2] = {ct, (br << 27) | (dr << 26)};
44
45         PROGRAM_CNTXT_INIT(p, descbuf, 0);
46         if (swap) {
47                 PROGRAM_SET_BSWAP(p);
48
49                 context[0] = swab32(context[0]);
50                 context[1] = swab32(context[1]);
51         }
52
53         if (ps)
54                 PROGRAM_SET_36BIT_ADDR(p);
55         SHR_HDR(p, SHR_ALWAYS, 1, 0);
56
57         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
58             cipherdata->keylen, INLINE_KEY(cipherdata));
59         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
60         MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
61         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8, OP_ALG_AAI_F8,
62                       OP_ALG_AS_INITFINAL, 0, dir);
63         LOAD(p, (uintptr_t)context, CONTEXT1, 0, 8, IMMED | COPY);
64         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
65         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
66
67         return PROGRAM_FINALIZE(p);
68 }
69
70 /**
71  * cnstr_shdsc_snow_f9 - SNOW/f9 (UIA2) as a shared descriptor
72  * @descbuf: pointer to descriptor-under-construction buffer
73  * @ps: if 36/40bit addressing is desired, this parameter must be true
74  * @swap: must be true when core endianness doesn't match SEC endianness
75  * @authdata: pointer to authentication transform definitions
76  * @dir: cipher direction (DIR_ENC/DIR_DEC)
77  * @count: UEA2 count value (32 bits)
78  * @fresh: UEA2 fresh value ID (32 bits)
79  * @direction: UEA2 direction (1 bit)
80  * @datalen: size of data
81  *
82  * Return: size of descriptor written in words or negative number on error
83  */
84 static inline int
85 cnstr_shdsc_snow_f9(uint32_t *descbuf, bool ps, bool swap,
86                     struct alginfo *authdata, uint8_t dir, uint32_t count,
87                     uint32_t fresh, uint8_t direction, uint32_t datalen)
88 {
89         struct program prg;
90         struct program *p = &prg;
91         uint64_t ct = count;
92         uint64_t fr = fresh;
93         uint64_t dr = direction;
94         uint64_t context[2];
95
96         context[0] = (ct << 32) | (dr << 26);
97         context[1] = fr << 32;
98
99         PROGRAM_CNTXT_INIT(p, descbuf, 0);
100         if (swap) {
101                 PROGRAM_SET_BSWAP(p);
102
103                 context[0] = swab64(context[0]);
104                 context[1] = swab64(context[1]);
105         }
106         if (ps)
107                 PROGRAM_SET_36BIT_ADDR(p);
108         SHR_HDR(p, SHR_ALWAYS, 1, 0);
109
110         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
111             INLINE_KEY(authdata));
112         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
113         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
114                       OP_ALG_AS_INITFINAL, 0, dir);
115         LOAD(p, (uintptr_t)context, CONTEXT2, 0, 16, IMMED | COPY);
116         SEQFIFOLOAD(p, BIT_DATA, datalen, CLASS2 | LAST2);
117         /* Save lower half of MAC out into a 32-bit sequence */
118         SEQSTORE(p, CONTEXT2, 0, 4, 0);
119
120         return PROGRAM_FINALIZE(p);
121 }
122
123 /**
124  * cnstr_shdsc_blkcipher - block cipher transformation
125  * @descbuf: pointer to descriptor-under-construction buffer
126  * @ps: if 36/40bit addressing is desired, this parameter must be true
127  * @swap: must be true when core endianness doesn't match SEC endianness
128  * @share: sharing type of shared descriptor
129  * @cipherdata: pointer to block cipher transform definitions
130  *              Valid algorithm values one of OP_ALG_ALGSEL_* {DES, 3DES, AES}
131  *              Valid modes for:
132  *                  AES: OP_ALG_AAI_* {CBC, CTR}
133  *                  DES, 3DES: OP_ALG_AAI_CBC
134  * @iv: IV data; if NULL, "ivlen" bytes from the input frame will be read as IV
135  * @ivlen: IV length
136  * @dir: DIR_ENC/DIR_DEC
137  *
138  * Return: size of descriptor written in words or negative number on error
139  */
140 static inline int
141 cnstr_shdsc_blkcipher(uint32_t *descbuf, bool ps, bool swap,
142                       enum rta_share_type share,
143                       struct alginfo *cipherdata, uint8_t *iv,
144                       uint32_t ivlen, uint8_t dir)
145 {
146         struct program prg;
147         struct program *p = &prg;
148         uint32_t iv_off = 0;
149         const bool need_dk = (dir == DIR_DEC) &&
150                              (cipherdata->algtype == OP_ALG_ALGSEL_AES) &&
151                              (cipherdata->algmode == OP_ALG_AAI_CBC);
152         LABEL(keyjmp);
153         LABEL(skipdk);
154         REFERENCE(pkeyjmp);
155         REFERENCE(pskipdk);
156
157         PROGRAM_CNTXT_INIT(p, descbuf, 0);
158         if (swap)
159                 PROGRAM_SET_BSWAP(p);
160         if (ps)
161                 PROGRAM_SET_36BIT_ADDR(p);
162         SHR_HDR(p, share, 1, SC);
163
164         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
165         /* Insert Key */
166         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
167             cipherdata->keylen, INLINE_KEY(cipherdata));
168
169         if (need_dk) {
170                 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
171                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
172
173                 pskipdk = JUMP(p, skipdk, LOCAL_JUMP, ALL_TRUE, 0);
174         }
175         SET_LABEL(p, keyjmp);
176
177         if (need_dk) {
178                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES, cipherdata->algmode |
179                               OP_ALG_AAI_DK, OP_ALG_AS_INITFINAL,
180                               ICV_CHECK_DISABLE, dir);
181                 SET_LABEL(p, skipdk);
182         } else {
183                 ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
184                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, dir);
185         }
186
187         if (cipherdata->algmode == OP_ALG_AAI_CTR)
188                 iv_off = 16;
189
190         if (iv)
191                 /* IV load, convert size */
192                 LOAD(p, (uintptr_t)iv, CONTEXT1, iv_off, ivlen, IMMED | COPY);
193         else
194                 /* IV is present first before the actual message */
195                 SEQLOAD(p, CONTEXT1, iv_off, ivlen, 0);
196
197         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
198         MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
199
200         /* Insert sequence load/store with VLF */
201         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
202         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
203
204         PATCH_JUMP(p, pkeyjmp, keyjmp);
205         if (need_dk)
206                 PATCH_JUMP(p, pskipdk, skipdk);
207
208         return PROGRAM_FINALIZE(p);
209 }
210
211 /**
212  * cnstr_shdsc_hmac - HMAC shared
213  * @descbuf: pointer to descriptor-under-construction buffer
214  * @ps: if 36/40bit addressing is desired, this parameter must be true
215  * @swap: must be true when core endianness doesn't match SEC endianness
216  * @share: sharing type of shared descriptor
217  * @authdata: pointer to authentication transform definitions;
218  *            message digest algorithm: OP_ALG_ALGSEL_MD5/ SHA1-512.
219  * @do_icv: 0 if ICV checking is not desired, any other value if ICV checking
220  *          is needed for all the packets processed by this shared descriptor
221  * @trunc_len: Length of the truncated ICV to be written in the output buffer, 0
222  *             if no truncation is needed
223  *
224  * Note: There's no support for keys longer than the block size of the
225  * underlying hash function, according to the selected algorithm.
226  *
227  * Return: size of descriptor written in words or negative number on error
228  */
229 static inline int
230 cnstr_shdsc_hmac(uint32_t *descbuf, bool ps, bool swap,
231                  enum rta_share_type share,
232                  struct alginfo *authdata, uint8_t do_icv,
233                  uint8_t trunc_len)
234 {
235         struct program prg;
236         struct program *p = &prg;
237         uint8_t storelen, opicv, dir;
238         LABEL(keyjmp);
239         LABEL(jmpprecomp);
240         REFERENCE(pkeyjmp);
241         REFERENCE(pjmpprecomp);
242
243         /* Compute fixed-size store based on alg selection */
244         switch (authdata->algtype) {
245         case OP_ALG_ALGSEL_MD5:
246                 storelen = 16;
247                 break;
248         case OP_ALG_ALGSEL_SHA1:
249                 storelen = 20;
250                 break;
251         case OP_ALG_ALGSEL_SHA224:
252                 storelen = 28;
253                 break;
254         case OP_ALG_ALGSEL_SHA256:
255                 storelen = 32;
256                 break;
257         case OP_ALG_ALGSEL_SHA384:
258                 storelen = 48;
259                 break;
260         case OP_ALG_ALGSEL_SHA512:
261                 storelen = 64;
262                 break;
263         default:
264                 return -EINVAL;
265         }
266
267         trunc_len = trunc_len && (trunc_len < storelen) ? trunc_len : storelen;
268
269         opicv = do_icv ? ICV_CHECK_ENABLE : ICV_CHECK_DISABLE;
270         dir = do_icv ? DIR_DEC : DIR_ENC;
271
272         PROGRAM_CNTXT_INIT(p, descbuf, 0);
273         if (swap)
274                 PROGRAM_SET_BSWAP(p);
275         if (ps)
276                 PROGRAM_SET_36BIT_ADDR(p);
277         SHR_HDR(p, share, 1, SC);
278
279         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SHRD);
280         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
281             INLINE_KEY(authdata));
282
283         /* Do operation */
284         ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC,
285                       OP_ALG_AS_INITFINAL, opicv, dir);
286
287         pjmpprecomp = JUMP(p, jmpprecomp, LOCAL_JUMP, ALL_TRUE, 0);
288         SET_LABEL(p, keyjmp);
289
290         ALG_OPERATION(p, authdata->algtype, OP_ALG_AAI_HMAC_PRECOMP,
291                       OP_ALG_AS_INITFINAL, opicv, dir);
292
293         SET_LABEL(p, jmpprecomp);
294
295         /* compute sequences */
296         if (opicv == ICV_CHECK_ENABLE)
297                 MATHB(p, SEQINSZ, SUB, trunc_len, VSEQINSZ, 4, IMMED2);
298         else
299                 MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
300
301         /* Do load (variable length) */
302         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
303
304         if (opicv == ICV_CHECK_ENABLE)
305                 SEQFIFOLOAD(p, ICV2, trunc_len, LAST2);
306         else
307                 SEQSTORE(p, CONTEXT2, 0, trunc_len, 0);
308
309         PATCH_JUMP(p, pkeyjmp, keyjmp);
310         PATCH_JUMP(p, pjmpprecomp, jmpprecomp);
311
312         return PROGRAM_FINALIZE(p);
313 }
314
315 /**
316  * cnstr_shdsc_kasumi_f8 - KASUMI F8 (Confidentiality) as a shared descriptor
317  *                         (ETSI "Document 1: f8 and f9 specification")
318  * @descbuf: pointer to descriptor-under-construction buffer
319  * @ps: if 36/40bit addressing is desired, this parameter must be true
320  * @swap: must be true when core endianness doesn't match SEC endianness
321  * @cipherdata: pointer to block cipher transform definitions
322  * @dir: cipher direction (DIR_ENC/DIR_DEC)
323  * @count: count value (32 bits)
324  * @bearer: bearer ID (5 bits)
325  * @direction: direction (1 bit)
326  *
327  * Return: size of descriptor written in words or negative number on error
328  */
329 static inline int
330 cnstr_shdsc_kasumi_f8(uint32_t *descbuf, bool ps, bool swap,
331                       struct alginfo *cipherdata, uint8_t dir,
332                       uint32_t count, uint8_t bearer, uint8_t direction)
333 {
334         struct program prg;
335         struct program *p = &prg;
336         uint64_t ct = count;
337         uint64_t br = bearer;
338         uint64_t dr = direction;
339         uint32_t context[2] = { ct, (br << 27) | (dr << 26) };
340
341         PROGRAM_CNTXT_INIT(p, descbuf, 0);
342         if (swap) {
343                 PROGRAM_SET_BSWAP(p);
344
345                 context[0] = swab32(context[0]);
346                 context[1] = swab32(context[1]);
347         }
348         if (ps)
349                 PROGRAM_SET_36BIT_ADDR(p);
350         SHR_HDR(p, SHR_ALWAYS, 1, 0);
351
352         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
353             cipherdata->keylen, INLINE_KEY(cipherdata));
354         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
355         MATHB(p, SEQINSZ, SUB, MATH2, VSEQOUTSZ, 4, 0);
356         ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F8,
357                       OP_ALG_AS_INITFINAL, 0, dir);
358         LOAD(p, (uintptr_t)context, CONTEXT1, 0, 8, IMMED | COPY);
359         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1);
360         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
361
362         return PROGRAM_FINALIZE(p);
363 }
364
365 /**
366  * cnstr_shdsc_kasumi_f9 -  KASUMI F9 (Integrity) as a shared descriptor
367  *                          (ETSI "Document 1: f8 and f9 specification")
368  * @descbuf: pointer to descriptor-under-construction buffer
369  * @ps: if 36/40bit addressing is desired, this parameter must be true
370  * @swap: must be true when core endianness doesn't match SEC endianness
371  * @authdata: pointer to authentication transform definitions
372  * @dir: cipher direction (DIR_ENC/DIR_DEC)
373  * @count: count value (32 bits)
374  * @fresh: fresh value ID (32 bits)
375  * @direction: direction (1 bit)
376  * @datalen: size of data
377  *
378  * Return: size of descriptor written in words or negative number on error
379  */
380 static inline int
381 cnstr_shdsc_kasumi_f9(uint32_t *descbuf, bool ps, bool swap,
382                       struct alginfo *authdata, uint8_t dir,
383                       uint32_t count, uint32_t fresh, uint8_t direction,
384                       uint32_t datalen)
385 {
386         struct program prg;
387         struct program *p = &prg;
388         uint16_t ctx_offset = 16;
389         uint32_t context[6] = {count, direction << 26, fresh, 0, 0, 0};
390
391         PROGRAM_CNTXT_INIT(p, descbuf, 0);
392         if (swap) {
393                 PROGRAM_SET_BSWAP(p);
394
395                 context[0] = swab32(context[0]);
396                 context[1] = swab32(context[1]);
397                 context[2] = swab32(context[2]);
398         }
399         if (ps)
400                 PROGRAM_SET_36BIT_ADDR(p);
401         SHR_HDR(p, SHR_ALWAYS, 1, 0);
402
403         KEY(p, KEY1, authdata->key_enc_flags, authdata->key, authdata->keylen,
404             INLINE_KEY(authdata));
405         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
406         ALG_OPERATION(p, OP_ALG_ALGSEL_KASUMI, OP_ALG_AAI_F9,
407                       OP_ALG_AS_INITFINAL, 0, dir);
408         LOAD(p, (uintptr_t)context, CONTEXT1, 0, 24, IMMED | COPY);
409         SEQFIFOLOAD(p, BIT_DATA, datalen, CLASS1 | LAST1);
410         /* Save output MAC of DWORD 2 into a 32-bit sequence */
411         SEQSTORE(p, CONTEXT1, ctx_offset, 4, 0);
412
413         return PROGRAM_FINALIZE(p);
414 }
415
416 /**
417  * cnstr_shdsc_crc - CRC32 Accelerator (IEEE 802 CRC32 protocol mode)
418  * @descbuf: pointer to descriptor-under-construction buffer
419  * @swap: must be true when core endianness doesn't match SEC endianness
420  *
421  * Return: size of descriptor written in words or negative number on error
422  */
423 static inline int
424 cnstr_shdsc_crc(uint32_t *descbuf, bool swap)
425 {
426         struct program prg;
427         struct program *p = &prg;
428
429         PROGRAM_CNTXT_INIT(p, descbuf, 0);
430         if (swap)
431                 PROGRAM_SET_BSWAP(p);
432
433         SHR_HDR(p, SHR_ALWAYS, 1, 0);
434
435         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
436         ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
437                       OP_ALG_AAI_802 | OP_ALG_AAI_DOC,
438                       OP_ALG_AS_FINALIZE, 0, DIR_ENC);
439         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
440         SEQSTORE(p, CONTEXT2, 0, 4, 0);
441
442         return PROGRAM_FINALIZE(p);
443 }
444
445 /**
446  * cnstr_shdsc_gcm_encap - AES-GCM encap as a shared descriptor
447  * @descbuf: pointer to descriptor-under-construction buffer
448  * @ps: if 36/40bit addressing is desired, this parameter must be true
449  * @swap: must be true when core endianness doesn't match SEC endianness
450  * @share: sharing type of shared descriptor
451  * @cipherdata: pointer to block cipher transform definitions
452  *              Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
453  *              OP_ALG_AAI_GCM.
454  * @ivlen: Initialization vector length
455  * @icvsize: integrity check value (ICV) size (truncated or full)
456  *
457  * Return: size of descriptor written in words or negative number on error
458  */
459 static inline int
460 cnstr_shdsc_gcm_encap(uint32_t *descbuf, bool ps, bool swap,
461                       enum rta_share_type share,
462                       struct alginfo *cipherdata,
463                       uint32_t ivlen, uint32_t icvsize)
464 {
465         struct program prg;
466         struct program *p = &prg;
467
468         LABEL(keyjmp);
469         LABEL(zeroassocjump2);
470         LABEL(zeroassocjump1);
471         LABEL(zeropayloadjump);
472         REFERENCE(pkeyjmp);
473         REFERENCE(pzeroassocjump2);
474         REFERENCE(pzeroassocjump1);
475         REFERENCE(pzeropayloadjump);
476
477         PROGRAM_CNTXT_INIT(p, descbuf, 0);
478
479         if (swap)
480                 PROGRAM_SET_BSWAP(p);
481         if (ps)
482                 PROGRAM_SET_36BIT_ADDR(p);
483
484         SHR_HDR(p, share, 1, SC);
485
486         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
487         /* Insert Key */
488         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
489             cipherdata->keylen, INLINE_KEY(cipherdata));
490
491         SET_LABEL(p, keyjmp);
492
493         /* class 1 operation */
494         ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
495                       OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
496
497         MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
498
499         /* if assoclen + cryptlen is ZERO, skip to ICV write */
500         MATHB(p, SEQINSZ, SUB, ivlen, VSEQOUTSZ, 4, IMMED2);
501         pzeroassocjump2 = JUMP(p, zeroassocjump2, LOCAL_JUMP, ALL_TRUE, MATH_Z);
502
503         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
504
505         /* if assoclen is ZERO, skip reading the assoc data */
506         MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
507         pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
508
509         MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, 4, 0);
510
511         /* skip assoc data */
512         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
513
514         /* cryptlen = seqinlen - assoclen */
515         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
516
517         /* if cryptlen is ZERO jump to zero-payload commands */
518         pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
519                                 MATH_Z);
520
521         /* read assoc data */
522         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
523         SET_LABEL(p, zeroassocjump1);
524
525         MATHB(p, SEQINSZ, SUB, MATH0, VSEQINSZ, 4, 0);
526
527         /* write encrypted data */
528         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
529
530         /* read payload data */
531         SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | LAST1);
532
533         /* jump the zero-payload commands */
534         JUMP(p, 4, LOCAL_JUMP, ALL_TRUE, 0);
535
536         /* zero-payload commands */
537         SET_LABEL(p, zeropayloadjump);
538
539         /* read assoc data */
540         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | LAST1);
541
542         JUMP(p, 2, LOCAL_JUMP, ALL_TRUE, 0);
543
544         /* There is no input data */
545         SET_LABEL(p, zeroassocjump2);
546
547         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1 | LAST1);
548
549         /* write ICV */
550         SEQSTORE(p, CONTEXT1, 0, icvsize, 0);
551
552         PATCH_JUMP(p, pkeyjmp, keyjmp);
553         PATCH_JUMP(p, pzeroassocjump2, zeroassocjump2);
554         PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
555         PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
556
557         return PROGRAM_FINALIZE(p);
558 }
559
560 /**
561  * cnstr_shdsc_gcm_decap - AES-GCM decap as a shared descriptor
562  * @descbuf: pointer to descriptor-under-construction buffer
563  * @ps: if 36/40bit addressing is desired, this parameter must be true
564  * @swap: must be true when core endianness doesn't match SEC endianness
565  * @share: sharing type of shared descriptor
566  * @cipherdata: pointer to block cipher transform definitions
567  *              Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
568  *              OP_ALG_AAI_GCM.
569  * @icvsize: integrity check value (ICV) size (truncated or full)
570  *
571  * Return: size of descriptor written in words or negative number on error
572  */
573 static inline int
574 cnstr_shdsc_gcm_decap(uint32_t *descbuf, bool ps, bool swap,
575                       enum rta_share_type share,
576                       struct alginfo *cipherdata,
577                       uint32_t ivlen, uint32_t icvsize)
578 {
579         struct program prg;
580         struct program *p = &prg;
581
582         LABEL(keyjmp);
583         LABEL(zeroassocjump1);
584         LABEL(zeropayloadjump);
585         REFERENCE(pkeyjmp);
586         REFERENCE(pzeroassocjump1);
587         REFERENCE(pzeropayloadjump);
588
589         PROGRAM_CNTXT_INIT(p, descbuf, 0);
590
591         if (swap)
592                 PROGRAM_SET_BSWAP(p);
593         if (ps)
594                 PROGRAM_SET_36BIT_ADDR(p);
595
596         SHR_HDR(p, share, 1, SC);
597
598         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
599         /* Insert Key */
600         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
601             cipherdata->keylen, INLINE_KEY(cipherdata));
602
603         SET_LABEL(p, keyjmp);
604
605         /* class 1 operation */
606         ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
607                       OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
608
609         MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
610         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
611
612         /* if assoclen is ZERO, skip reading the assoc data */
613         MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
614         pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
615
616         MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, 4, 0);
617
618         /* skip assoc data */
619         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
620
621         /* read assoc data */
622         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
623
624         SET_LABEL(p, zeroassocjump1);
625
626         /* cryptlen = seqoutlen - assoclen */
627         MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQINSZ, 4, 0);
628
629         /* jump to zero-payload command if cryptlen is zero */
630         pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
631                                 MATH_Z);
632
633         MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQOUTSZ, 4, 0);
634
635         /* store encrypted data */
636         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
637
638         /* read payload data */
639         SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | FLUSH1);
640
641         /* zero-payload command */
642         SET_LABEL(p, zeropayloadjump);
643
644         /* read ICV */
645         SEQFIFOLOAD(p, ICV1, icvsize, CLASS1 | LAST1);
646
647         PATCH_JUMP(p, pkeyjmp, keyjmp);
648         PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
649         PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
650
651         return PROGRAM_FINALIZE(p);
652 }
653
654 #endif /* __DESC_ALGO_H__ */