New upstream version 18.02
[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_gcm_encap - AES-GCM encap as a shared descriptor
414  * @descbuf: pointer to descriptor-under-construction buffer
415  * @ps: if 36/40bit addressing is desired, this parameter must be true
416  * @swap: must be true when core endianness doesn't match SEC endianness
417  * @cipherdata: pointer to block cipher transform definitions
418  *              Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
419  *              OP_ALG_AAI_GCM.
420  * @ivlen: Initialization vector length
421  * @icvsize: integrity check value (ICV) size (truncated or full)
422  *
423  * Return: size of descriptor written in words or negative number on error
424  */
425 static inline int
426 cnstr_shdsc_gcm_encap(uint32_t *descbuf, bool ps, bool swap,
427                       struct alginfo *cipherdata,
428                       uint32_t ivlen, uint32_t icvsize)
429 {
430         struct program prg;
431         struct program *p = &prg;
432
433         LABEL(keyjmp);
434         LABEL(zeroassocjump2);
435         LABEL(zeroassocjump1);
436         LABEL(zeropayloadjump);
437         REFERENCE(pkeyjmp);
438         REFERENCE(pzeroassocjump2);
439         REFERENCE(pzeroassocjump1);
440         REFERENCE(pzeropayloadjump);
441
442         PROGRAM_CNTXT_INIT(p, descbuf, 0);
443
444         if (swap)
445                 PROGRAM_SET_BSWAP(p);
446         if (ps)
447                 PROGRAM_SET_36BIT_ADDR(p);
448
449         SHR_HDR(p, SHR_SERIAL, 1, SC);
450
451         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
452         /* Insert Key */
453         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
454             cipherdata->keylen, INLINE_KEY(cipherdata));
455
456         SET_LABEL(p, keyjmp);
457
458         /* class 1 operation */
459         ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
460                       OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE, DIR_ENC);
461
462         MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
463
464         /* if assoclen + cryptlen is ZERO, skip to ICV write */
465         MATHB(p, SEQINSZ, SUB, ivlen, VSEQOUTSZ, 4, IMMED2);
466         pzeroassocjump2 = JUMP(p, zeroassocjump2, LOCAL_JUMP, ALL_TRUE, MATH_Z);
467
468         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
469
470         /* if assoclen is ZERO, skip reading the assoc data */
471         MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
472         pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
473
474         MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, 4, 0);
475
476         /* skip assoc data */
477         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
478
479         /* cryptlen = seqinlen - assoclen */
480         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
481
482         /* if cryptlen is ZERO jump to zero-payload commands */
483         pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
484                                 MATH_Z);
485
486         /* read assoc data */
487         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
488         SET_LABEL(p, zeroassocjump1);
489
490         MATHB(p, SEQINSZ, SUB, MATH0, VSEQINSZ, 4, 0);
491
492         /* write encrypted data */
493         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
494
495         /* read payload data */
496         SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | LAST1);
497
498         /* jump the zero-payload commands */
499         JUMP(p, 4, LOCAL_JUMP, ALL_TRUE, 0);
500
501         /* zero-payload commands */
502         SET_LABEL(p, zeropayloadjump);
503
504         /* read assoc data */
505         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | LAST1);
506
507         JUMP(p, 2, LOCAL_JUMP, ALL_TRUE, 0);
508
509         /* There is no input data */
510         SET_LABEL(p, zeroassocjump2);
511
512         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1 | LAST1);
513
514         /* write ICV */
515         SEQSTORE(p, CONTEXT1, 0, icvsize, 0);
516
517         PATCH_JUMP(p, pkeyjmp, keyjmp);
518         PATCH_JUMP(p, pzeroassocjump2, zeroassocjump2);
519         PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
520         PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
521
522         return PROGRAM_FINALIZE(p);
523 }
524
525 /**
526  * cnstr_shdsc_gcm_decap - AES-GCM decap as a shared descriptor
527  * @descbuf: pointer to descriptor-under-construction buffer
528  * @ps: if 36/40bit addressing is desired, this parameter must be true
529  * @swap: must be true when core endianness doesn't match SEC endianness
530  * @cipherdata: pointer to block cipher transform definitions
531  *              Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with
532  *              OP_ALG_AAI_GCM.
533  * @icvsize: integrity check value (ICV) size (truncated or full)
534  *
535  * Return: size of descriptor written in words or negative number on error
536  */
537 static inline int
538 cnstr_shdsc_gcm_decap(uint32_t *descbuf, bool ps, bool swap,
539                       struct alginfo *cipherdata,
540                       uint32_t ivlen, uint32_t icvsize)
541 {
542         struct program prg;
543         struct program *p = &prg;
544
545         LABEL(keyjmp);
546         LABEL(zeroassocjump1);
547         LABEL(zeropayloadjump);
548         REFERENCE(pkeyjmp);
549         REFERENCE(pzeroassocjump1);
550         REFERENCE(pzeropayloadjump);
551
552         PROGRAM_CNTXT_INIT(p, descbuf, 0);
553
554         if (swap)
555                 PROGRAM_SET_BSWAP(p);
556         if (ps)
557                 PROGRAM_SET_36BIT_ADDR(p);
558
559         SHR_HDR(p, SHR_SERIAL, 1, SC);
560
561         pkeyjmp = JUMP(p, keyjmp, LOCAL_JUMP, ALL_TRUE, SELF | SHRD);
562         /* Insert Key */
563         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
564             cipherdata->keylen, INLINE_KEY(cipherdata));
565
566         SET_LABEL(p, keyjmp);
567
568         /* class 1 operation */
569         ALG_OPERATION(p, cipherdata->algtype, cipherdata->algmode,
570                       OP_ALG_AS_INITFINAL, ICV_CHECK_ENABLE, DIR_DEC);
571
572         MATHB(p, DPOVRD, AND, 0x7fffffff, MATH3, 4, IMMED2);
573         SEQFIFOLOAD(p, IV1, ivlen, FLUSH1);
574
575         /* if assoclen is ZERO, skip reading the assoc data */
576         MATHB(p, ZERO, ADD, MATH3, VSEQINSZ, 4, 0);
577         pzeroassocjump1 = JUMP(p, zeroassocjump1, LOCAL_JUMP, ALL_TRUE, MATH_Z);
578
579         MATHB(p, ZERO, ADD, MATH3, VSEQOUTSZ, 4, 0);
580
581         /* skip assoc data */
582         SEQFIFOSTORE(p, SKIP, 0, 0, VLF);
583
584         /* read assoc data */
585         SEQFIFOLOAD(p, AAD1, 0, CLASS1 | VLF | FLUSH1);
586
587         SET_LABEL(p, zeroassocjump1);
588
589         /* cryptlen = seqoutlen - assoclen */
590         MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQINSZ, 4, 0);
591
592         /* jump to zero-payload command if cryptlen is zero */
593         pzeropayloadjump = JUMP(p, zeropayloadjump, LOCAL_JUMP, ALL_TRUE,
594                                 MATH_Z);
595
596         MATHB(p, SEQOUTSZ, SUB, MATH0, VSEQOUTSZ, 4, 0);
597
598         /* store encrypted data */
599         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
600
601         /* read payload data */
602         SEQFIFOLOAD(p, MSG1, 0, CLASS1 | VLF | FLUSH1);
603
604         /* zero-payload command */
605         SET_LABEL(p, zeropayloadjump);
606
607         /* read ICV */
608         SEQFIFOLOAD(p, ICV1, icvsize, CLASS1 | LAST1);
609
610         PATCH_JUMP(p, pkeyjmp, keyjmp);
611         PATCH_JUMP(p, pzeroassocjump1, zeroassocjump1);
612         PATCH_JUMP(p, pzeropayloadjump, zeropayloadjump);
613
614         return PROGRAM_FINALIZE(p);
615 }
616
617 /**
618  * cnstr_shdsc_crc - CRC32 Accelerator (IEEE 802 CRC32 protocol mode)
619  * @descbuf: pointer to descriptor-under-construction buffer
620  * @swap: must be true when core endianness doesn't match SEC endianness
621  *
622  * Return: size of descriptor written in words or negative number on error
623  */
624 static inline int
625 cnstr_shdsc_crc(uint32_t *descbuf, bool swap)
626 {
627         struct program prg;
628         struct program *p = &prg;
629
630         PROGRAM_CNTXT_INIT(p, descbuf, 0);
631         if (swap)
632                 PROGRAM_SET_BSWAP(p);
633
634         SHR_HDR(p, SHR_ALWAYS, 1, 0);
635
636         MATHB(p, SEQINSZ, SUB, MATH2, VSEQINSZ, 4, 0);
637         ALG_OPERATION(p, OP_ALG_ALGSEL_CRC,
638                       OP_ALG_AAI_802 | OP_ALG_AAI_DOC,
639                       OP_ALG_AS_FINALIZE, 0, DIR_ENC);
640         SEQFIFOLOAD(p, MSG2, 0, VLF | LAST2);
641         SEQSTORE(p, CONTEXT2, 0, 4, 0);
642
643         return PROGRAM_FINALIZE(p);
644 }
645
646 #endif /* __DESC_ALGO_H__ */