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