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