crypto/dpaa2_sec: update desc for PDCP 18-bit enc-auth
[dpdk.git] / drivers / crypto / dpaa2_sec / hw / desc / pdcp.h
1 /* SPDX-License-Identifier: BSD-3-Clause or GPL-2.0+
2  * Copyright 2008-2013 Freescale Semiconductor, Inc.
3  * Copyright 2019 NXP
4  */
5
6 #ifndef __DESC_PDCP_H__
7 #define __DESC_PDCP_H__
8
9 #include "hw/rta.h"
10 #include "common.h"
11
12 /**
13  * DOC: PDCP Shared Descriptor Constructors
14  *
15  * Shared descriptors for PDCP protocol.
16  */
17
18 /**
19  * PDCP_NULL_MAX_FRAME_LEN - The maximum frame frame length that is supported by
20  *                           PDCP NULL protocol.
21  */
22 #define PDCP_NULL_MAX_FRAME_LEN         0x00002FFF
23
24 /**
25  * PDCP_MAC_I_LEN - The length of the MAC-I for PDCP protocol operation
26  */
27 #define PDCP_MAC_I_LEN                  0x00000004
28
29 /**
30  * PDCP_MAX_FRAME_LEN_STATUS - The status returned in FD status/command field in
31  *                             case the input frame is larger than
32  *                             PDCP_NULL_MAX_FRAME_LEN.
33  */
34 #define PDCP_MAX_FRAME_LEN_STATUS       0xF1
35
36 /**
37  * PDCP_C_PLANE_SN_MASK - This mask is used in the PDCP descriptors for
38  *                        extracting the sequence number (SN) from the PDCP
39  *                        Control Plane header. For PDCP Control Plane, the SN
40  *                        is constant (5 bits) as opposed to PDCP Data Plane
41  *                        (7/12/15 bits).
42  */
43 #define PDCP_C_PLANE_SN_MASK            0x1F000000
44 #define PDCP_C_PLANE_SN_MASK_BE         0x0000001F
45
46 /**
47  * PDCP_U_PLANE_15BIT_SN_MASK - This mask is used in the PDCP descriptors for
48  *                              extracting the sequence number (SN) from the
49  *                              PDCP User Plane header. For PDCP Control Plane,
50  *                              the SN is constant (5 bits) as opposed to PDCP
51  *                              Data Plane (7/12/15 bits).
52  */
53 #define PDCP_U_PLANE_15BIT_SN_MASK      0xFF7F0000
54 #define PDCP_U_PLANE_15BIT_SN_MASK_BE   0x00007FFF
55
56 /**
57  * PDCP_U_PLANE_18BIT_SN_MASK - This mask is used in the PDCP descriptors for
58  *                              extracting the sequence number (SN) from the
59  *                              PDCP User Plane header.
60  */
61 #define PDCP_U_PLANE_18BIT_SN_MASK      0xFFFF0300
62 #define PDCP_U_PLANE_18BIT_SN_MASK_BE   0x0003FFFF
63
64 /**
65  * PDCP_BEARER_MASK - This mask is used masking out the bearer for PDCP
66  *                    processing with SNOW f9 in LTE.
67  *
68  * The value on which this mask is applied is formatted as below:
69  *     Count-C (32 bit) | Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
70  *
71  * Applying this mask is done for creating the upper 64 bits of the IV needed
72  * for SNOW f9.
73  *
74  * The lower 32 bits of the mask are used for masking the direction for AES
75  * CMAC IV.
76  */
77 #define PDCP_BEARER_MASK                0x00000004FFFFFFFFull
78 #define PDCP_BEARER_MASK_BE             0xFFFFFFFF04000000ull
79
80 /**
81  * PDCP_DIR_MASK - This mask is used masking out the direction for PDCP
82  *                 processing with SNOW f9 in LTE.
83  *
84  * The value on which this mask is applied is formatted as below:
85  *     Bearer (5 bit) | Direction (1 bit) | 0 (26 bits)
86  *
87  * Applying this mask is done for creating the lower 32 bits of the IV needed
88  * for SNOW f9.
89  *
90  * The upper 32 bits of the mask are used for masking the direction for AES
91  * CMAC IV.
92  */
93 #define PDCP_DIR_MASK                   0x00000000000000F8ull
94 #define PDCP_DIR_MASK_BE                        0xF800000000000000ull
95
96 /**
97  * PDCP_NULL_INT_MAC_I_VAL - The value of the PDCP PDU MAC-I in case NULL
98  *                           integrity is used.
99  */
100
101 #define PDCP_NULL_INT_MAC_I_VAL         0x00000000
102
103 /**
104  * PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS - The status used to report ICV check
105  *                                         failed in case of NULL integrity
106  *                                         Control Plane processing.
107  */
108 #define PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS   0x0A
109 /**
110  * PDCP_DPOVRD_HFN_OV_EN - Value to be used in the FD status/cmd field to
111  *                         indicate the HFN override mechanism is active for the
112  *                         frame.
113  */
114 #define PDCP_DPOVRD_HFN_OV_EN           0x80000000
115
116 /**
117  * PDCP_P4080REV2_HFN_OV_BUFLEN - The length in bytes of the supplementary space
118  *                                that must be provided by the user at the
119  *                                beginning of the input frame buffer for
120  *                                P4080 REV 2.
121  *
122  * The format of the frame buffer is the following:
123  *
124  *  |<---PDCP_P4080REV2_HFN_OV_BUFLEN-->|
125  * //===================================||============||==============\\
126  * || PDCP_DPOVRD_HFN_OV_EN | HFN value || PDCP Header|| PDCP Payload ||
127  * \\===================================||============||==============//
128  *
129  * If HFN override mechanism is not desired, then the MSB of the first 4 bytes
130  * must be set to 0b.
131  */
132 #define PDCP_P4080REV2_HFN_OV_BUFLEN    4
133
134 /**
135  * enum cipher_type_pdcp - Type selectors for cipher types in PDCP protocol OP
136  *                         instructions.
137  * @PDCP_CIPHER_TYPE_NULL: NULL
138  * @PDCP_CIPHER_TYPE_SNOW: SNOW F8
139  * @PDCP_CIPHER_TYPE_AES: AES
140  * @PDCP_CIPHER_TYPE_ZUC: ZUCE
141  * @PDCP_CIPHER_TYPE_INVALID: invalid option
142  */
143 enum cipher_type_pdcp {
144         PDCP_CIPHER_TYPE_NULL,
145         PDCP_CIPHER_TYPE_SNOW,
146         PDCP_CIPHER_TYPE_AES,
147         PDCP_CIPHER_TYPE_ZUC,
148         PDCP_CIPHER_TYPE_INVALID
149 };
150
151 /**
152  * enum auth_type_pdcp - Type selectors for integrity types in PDCP protocol OP
153  *                       instructions.
154  * @PDCP_AUTH_TYPE_NULL: NULL
155  * @PDCP_AUTH_TYPE_SNOW: SNOW F9
156  * @PDCP_AUTH_TYPE_AES: AES CMAC
157  * @PDCP_AUTH_TYPE_ZUC: ZUCA
158  * @PDCP_AUTH_TYPE_INVALID: invalid option
159  */
160 enum auth_type_pdcp {
161         PDCP_AUTH_TYPE_NULL,
162         PDCP_AUTH_TYPE_SNOW,
163         PDCP_AUTH_TYPE_AES,
164         PDCP_AUTH_TYPE_ZUC,
165         PDCP_AUTH_TYPE_INVALID
166 };
167
168 /**
169  * enum pdcp_dir - Type selectors for direction for PDCP protocol
170  * @PDCP_DIR_UPLINK: uplink direction
171  * @PDCP_DIR_DOWNLINK: downlink direction
172  * @PDCP_DIR_INVALID: invalid option
173  */
174 enum pdcp_dir {
175         PDCP_DIR_UPLINK = 0,
176         PDCP_DIR_DOWNLINK = 1,
177         PDCP_DIR_INVALID
178 };
179
180 /**
181  * enum pdcp_plane - PDCP domain selectors
182  * @PDCP_CONTROL_PLANE: Control Plane
183  * @PDCP_DATA_PLANE: Data Plane
184  * @PDCP_SHORT_MAC: Short MAC
185  */
186 enum pdcp_plane {
187         PDCP_CONTROL_PLANE,
188         PDCP_DATA_PLANE,
189         PDCP_SHORT_MAC
190 };
191
192 /**
193  * enum pdcp_sn_size - Sequence Number Size selectors for PDCP protocol
194  * @PDCP_SN_SIZE_5: 5bit sequence number
195  * @PDCP_SN_SIZE_7: 7bit sequence number
196  * @PDCP_SN_SIZE_12: 12bit sequence number
197  * @PDCP_SN_SIZE_15: 15bit sequence number
198  * @PDCP_SN_SIZE_18: 18bit sequence number
199  */
200 enum pdcp_sn_size {
201         PDCP_SN_SIZE_5 = 5,
202         PDCP_SN_SIZE_7 = 7,
203         PDCP_SN_SIZE_12 = 12,
204         PDCP_SN_SIZE_15 = 15,
205         PDCP_SN_SIZE_18 = 18
206 };
207
208 /*
209  * PDCP Control Plane Protocol Data Blocks
210  */
211 #define PDCP_C_PLANE_PDB_HFN_SHIFT              5
212 #define PDCP_C_PLANE_PDB_BEARER_SHIFT           27
213 #define PDCP_C_PLANE_PDB_DIR_SHIFT              26
214 #define PDCP_C_PLANE_PDB_HFN_THR_SHIFT          5
215
216 #define PDCP_U_PLANE_PDB_OPT_SHORT_SN           0x2
217 #define PDCP_U_PLANE_PDB_OPT_15B_SN             0x4
218 #define PDCP_U_PLANE_PDB_OPT_18B_SN             0x6
219 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT     7
220 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT      12
221 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT     15
222 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT     18
223 #define PDCP_U_PLANE_PDB_BEARER_SHIFT           27
224 #define PDCP_U_PLANE_PDB_DIR_SHIFT              26
225 #define PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT 7
226 #define PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT  12
227 #define PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT 15
228 #define PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT 18
229
230 struct pdcp_pdb {
231         union {
232                 uint32_t opt;
233                 uint32_t rsvd;
234         } opt_res;
235         uint32_t hfn_res;       /* HyperFrame number,(27, 25 or 21 bits),
236                                  * left aligned & right-padded with zeros.
237                                  */
238         uint32_t bearer_dir_res;/* Bearer(5 bits), packet direction (1 bit),
239                                  * left aligned & right-padded with zeros.
240                                  */
241         uint32_t hfn_thr_res;   /* HyperFrame number threshold (27, 25 or 21
242                                  * bits), left aligned & right-padded with
243                                  * zeros.
244                                  */
245 };
246
247 /*
248  * PDCP internal PDB types
249  */
250 enum pdb_type_e {
251         PDCP_PDB_TYPE_NO_PDB,
252         PDCP_PDB_TYPE_FULL_PDB,
253         PDCP_PDB_TYPE_REDUCED_PDB,
254         PDCP_PDB_TYPE_INVALID
255 };
256
257 /*
258  * Function for appending the portion of a PDCP Control Plane shared descriptor
259  * which performs NULL encryption and integrity (i.e. copies the input frame
260  * to the output frame, appending 32 bits of zeros at the end (MAC-I for
261  * NULL integrity).
262  */
263 static inline int
264 pdcp_insert_cplane_null_op(struct program *p,
265                            bool swap __maybe_unused,
266                            struct alginfo *cipherdata __maybe_unused,
267                            struct alginfo *authdata __maybe_unused,
268                            unsigned int dir,
269                            enum pdcp_sn_size sn_size __maybe_unused,
270                            unsigned char era_2_sw_hfn_ovrd __maybe_unused)
271 {
272         LABEL(local_offset);
273         REFERENCE(move_cmd_read_descbuf);
274         REFERENCE(move_cmd_write_descbuf);
275
276         if (rta_sec_era > RTA_SEC_ERA_2) {
277                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ, 4, 0);
278                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
279                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
280                               IMMED2);
281                 else
282                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
283                               IMMED2);
284         } else {
285                 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ, 4, 0);
286                 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
287
288                 if (dir == OP_TYPE_ENCAP_PROTOCOL) {
289                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
290                               IMMED2);
291                         MATHB(p, VSEQINSZ, SUB, ONE, MATH0, 4, 0);
292                 } else {
293                         MATHB(p, VSEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQINSZ, 4,
294                               IMMED2);
295                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
296                               IMMED2);
297                         MATHB(p, VSEQOUTSZ, SUB, ONE, MATH0, 4, 0);
298                 }
299
300                 MATHB(p, MATH0, ADD, ONE, MATH0, 4, 0);
301
302                 /*
303                  * Since MOVELEN is available only starting with
304                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
305                  * command dynamically by writing the length from M1 by
306                  * OR-ing the command in the M1 register and MOVE the
307                  * result into the descriptor buffer. Care must be taken
308                  * wrt. the location of the command because of SEC
309                  * pipelining. The actual MOVEs are written at the end
310                  * of the descriptor due to calculations needed on the
311                  * offset in the descriptor for the MOVE command.
312                  */
313                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
314                                              IMMED);
315                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
316                                               WAITCOMP | IMMED);
317         }
318         MATHB(p, VSEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE, 4,
319               IMMED2);
320         JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
321
322         if (rta_sec_era > RTA_SEC_ERA_2) {
323                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
324                         MATHB(p, VSEQINSZ, ADD, ZERO, MATH0, 4, 0);
325                 else
326                         MATHB(p, VSEQOUTSZ, ADD, ZERO, MATH0, 4, 0);
327         }
328         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
329         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
330
331         if (rta_sec_era > RTA_SEC_ERA_2) {
332                 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
333         } else {
334                 SET_LABEL(p, local_offset);
335
336                 /* Shut off automatic Info FIFO entries */
337                 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
338                 /* Placeholder for MOVE command with length from M1 register */
339                 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
340                 /* Enable automatic Info FIFO entries */
341                 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
342         }
343
344         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
345                 MATHB(p, MATH1, XOR, MATH1, MATH0, 8, 0);
346                 MOVE(p, MATH0, 0, OFIFO, 0, 4, IMMED);
347         }
348
349         if (rta_sec_era < RTA_SEC_ERA_3) {
350                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
351                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
352         }
353
354         return 0;
355 }
356
357 static inline int
358 insert_copy_frame_op(struct program *p,
359                      struct alginfo *cipherdata __maybe_unused,
360                      unsigned int dir __maybe_unused)
361 {
362         LABEL(local_offset);
363         REFERENCE(move_cmd_read_descbuf);
364         REFERENCE(move_cmd_write_descbuf);
365
366         if (rta_sec_era > RTA_SEC_ERA_2) {
367                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQINSZ,  4, 0);
368                 MATHB(p, SEQINSZ, ADD, ZERO, VSEQOUTSZ,  4, 0);
369         } else {
370                 MATHB(p, SEQINSZ, ADD, ONE, VSEQINSZ,  4, 0);
371                 MATHB(p, VSEQINSZ, SUB, ONE, VSEQINSZ,  4, 0);
372                 MATHB(p, SEQINSZ, ADD, ONE, VSEQOUTSZ,  4, 0);
373                 MATHB(p, VSEQOUTSZ, SUB, ONE, VSEQOUTSZ,  4, 0);
374                 MATHB(p, VSEQINSZ, SUB, ONE, MATH0,  4, 0);
375                 MATHB(p, MATH0, ADD, ONE, MATH0,  4, 0);
376
377                 /*
378                  * Since MOVELEN is available only starting with
379                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
380                  * command dynamically by writing the length from M1 by
381                  * OR-ing the command in the M1 register and MOVE the
382                  * result into the descriptor buffer. Care must be taken
383                  * wrt. the location of the command because of SEC
384                  * pipelining. The actual MOVEs are written at the end
385                  * of the descriptor due to calculations needed on the
386                  * offset in the descriptor for the MOVE command.
387                  */
388                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
389                                              IMMED);
390                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
391                                               WAITCOMP | IMMED);
392         }
393         MATHB(p, SEQINSZ, SUB, PDCP_NULL_MAX_FRAME_LEN, NONE,  4,
394               IFB | IMMED2);
395         JUMP(p, PDCP_MAX_FRAME_LEN_STATUS, HALT_STATUS, ALL_FALSE, MATH_N);
396
397         if (rta_sec_era > RTA_SEC_ERA_2)
398                 MATHB(p, VSEQINSZ, ADD, ZERO, MATH0,  4, 0);
399
400         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
401         if (rta_sec_era > RTA_SEC_ERA_2) {
402                 MOVE(p, AB1, 0, OFIFO, 0, MATH0, 0);
403         } else {
404                 SET_LABEL(p, local_offset);
405
406                 /* Shut off automatic Info FIFO entries */
407                 LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
408
409                 /* Placeholder for MOVE command with length from M0 register */
410                 MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
411
412                 /* Enable automatic Info FIFO entries */
413                 LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
414         }
415
416         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
417
418         if (rta_sec_era < RTA_SEC_ERA_3) {
419                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
420                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
421         }
422         return 0;
423 }
424
425 static inline int
426 pdcp_insert_cplane_int_only_op(struct program *p,
427                                bool swap __maybe_unused,
428                                struct alginfo *cipherdata __maybe_unused,
429                                struct alginfo *authdata, unsigned int dir,
430                                enum pdcp_sn_size sn_size,
431                                unsigned char era_2_sw_hfn_ovrd)
432 {
433         uint32_t offset = 0, length = 0, sn_mask = 0;
434
435         /* 12 bit SN is only supported for protocol offload case */
436         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_12) {
437                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
438                     authdata->keylen, INLINE_KEY(authdata));
439
440                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
441                          (uint16_t)authdata->algtype);
442                 return 0;
443         }
444
445         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
446         switch (sn_size) {
447         case PDCP_SN_SIZE_5:
448                 offset = 7;
449                 length = 1;
450                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
451                                         PDCP_C_PLANE_SN_MASK_BE;
452                 break;
453         case PDCP_SN_SIZE_18:
454                 offset = 5;
455                 length = 3;
456                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
457                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
458                 break;
459         case PDCP_SN_SIZE_7:
460         case PDCP_SN_SIZE_12:
461         case PDCP_SN_SIZE_15:
462                 pr_err("Invalid sn_size for %s\n", __func__);
463                 return -ENOTSUP;
464
465         }
466         LABEL(local_offset);
467         REFERENCE(move_cmd_read_descbuf);
468         REFERENCE(move_cmd_write_descbuf);
469
470         switch (authdata->algtype) {
471         case PDCP_AUTH_TYPE_SNOW:
472                 /* Insert Auth Key */
473                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
474                     authdata->keylen, INLINE_KEY(authdata));
475                 SEQLOAD(p, MATH0, offset, length, 0);
476                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
477
478                 if (rta_sec_era > RTA_SEC_ERA_2 ||
479                     (rta_sec_era == RTA_SEC_ERA_2 &&
480                                    era_2_sw_hfn_ovrd == 0)) {
481                         SEQINPTR(p, 0, length, RTO);
482                 } else {
483                         SEQINPTR(p, 0, 5, RTO);
484                         SEQFIFOLOAD(p, SKIP, 4, 0);
485                 }
486
487                 if (swap == false) {
488                         MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
489                               IFB | IMMED2);
490                         MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
491
492                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
493
494                         MATHB(p, MATH2, AND, PDCP_BEARER_MASK, MATH2, 8,
495                               IMMED2);
496                         MOVEB(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
497                         MATHB(p, MATH3, AND, PDCP_DIR_MASK, MATH3, 8, IMMED2);
498                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
499                         MOVEB(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
500                 } else {
501                         MATHB(p, MATH0, AND, sn_mask, MATH1,  8,
502                               IFB | IMMED2);
503                         MATHB(p, MATH1, SHLD, MATH1, MATH1,  8, 0);
504
505                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
506                         MATHB(p, MATH2, AND, PDCP_BEARER_MASK_BE, MATH2, 8,
507                               IMMED2);
508
509                         MOVE(p, DESCBUF, 0x0C, MATH3, 0, 4, WAITCOMP | IMMED);
510                         MATHB(p, MATH3, AND, PDCP_DIR_MASK_BE, MATH3, 8,
511                               IMMED2);
512                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
513                         MOVE(p, MATH2, 0, CONTEXT2, 0, 0x0C, WAITCOMP | IMMED);
514                 }
515
516                 if (dir == OP_TYPE_DECAP_PROTOCOL) {
517                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
518                               IMMED2);
519                 } else {
520                         if (rta_sec_era > RTA_SEC_ERA_2) {
521                                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
522                                       0);
523                         } else {
524                                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
525                                       0);
526                                 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
527                                       0);
528                         }
529                 }
530
531                 if (rta_sec_era > RTA_SEC_ERA_2) {
532                         MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
533                         MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
534                 } else {
535                         MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
536                         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
537
538                         /*
539                          * Since MOVELEN is available only starting with
540                          * SEC ERA 3, use poor man's MOVELEN: create a MOVE
541                          * command dynamically by writing the length from M1 by
542                          * OR-ing the command in the M1 register and MOVE the
543                          * result into the descriptor buffer. Care must be taken
544                          * wrt. the location of the command because of SEC
545                          * pipelining. The actual MOVEs are written at the end
546                          * of the descriptor due to calculations needed on the
547                          * offset in the descriptor for the MOVE command.
548                          */
549                         move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
550                                                      IMMED);
551                         move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
552                                                       8, WAITCOMP | IMMED);
553                 }
554
555                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
556                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9, OP_ALG_AAI_F9,
557                               OP_ALG_AS_INITFINAL,
558                               dir == OP_TYPE_ENCAP_PROTOCOL ?
559                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
560                               DIR_ENC);
561
562                 if (rta_sec_era > RTA_SEC_ERA_2) {
563                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
564                                     VLF | LAST1 | LAST2 | FLUSH1);
565                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
566                 } else {
567                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
568                                     VLF | LAST1 | LAST2 | FLUSH1);
569                         SET_LABEL(p, local_offset);
570
571                         /* Shut off automatic Info FIFO entries */
572                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
573                         /*
574                          * Placeholder for MOVE command with length from M1
575                          * register
576                          */
577                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
578                         /* Enable automatic Info FIFO entries */
579                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
580                 }
581
582                 if (dir == OP_TYPE_DECAP_PROTOCOL)
583                         SEQFIFOLOAD(p, ICV2, 4, LAST2);
584                 else
585                         SEQSTORE(p, CONTEXT2, 0, 4, 0);
586
587                 break;
588
589         case PDCP_AUTH_TYPE_AES:
590                 /* Insert Auth Key */
591                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
592                     authdata->keylen, INLINE_KEY(authdata));
593                 SEQLOAD(p, MATH0, offset, length, 0);
594                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
595                 if (rta_sec_era > RTA_SEC_ERA_2 ||
596                     (rta_sec_era == RTA_SEC_ERA_2 &&
597                      era_2_sw_hfn_ovrd == 0)) {
598                         SEQINPTR(p, 0, length, RTO);
599                 } else {
600                         SEQINPTR(p, 0, 5, RTO);
601                         SEQFIFOLOAD(p, SKIP, 4, 0);
602                 }
603
604                 if (swap == false) {
605                         MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
606                               IFB | IMMED2);
607                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
608
609                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
610                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
611                         MOVEB(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
612                 } else {
613                         MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
614                               IFB | IMMED2);
615                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
616
617                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
618                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
619                         MOVE(p, MATH2, 0, IFIFOAB1, 0, 8, IMMED);
620                 }
621
622                 if (dir == OP_TYPE_DECAP_PROTOCOL) {
623                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
624                               IMMED2);
625                 } else {
626                         if (rta_sec_era > RTA_SEC_ERA_2) {
627                                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4,
628                                       0);
629                         } else {
630                                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4,
631                                       0);
632                                 MATHB(p, MATH1, SUB, ONE, MATH1, 4,
633                                       0);
634                         }
635                 }
636
637                 if (rta_sec_era > RTA_SEC_ERA_2) {
638                         MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
639                         MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
640                 } else {
641                         MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
642                         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
643
644                         /*
645                          * Since MOVELEN is available only starting with
646                          * SEC ERA 3, use poor man's MOVELEN: create a MOVE
647                          * command dynamically by writing the length from M1 by
648                          * OR-ing the command in the M1 register and MOVE the
649                          * result into the descriptor buffer. Care must be taken
650                          * wrt. the location of the command because of SEC
651                          * pipelining. The actual MOVEs are written at the end
652                          * of the descriptor due to calculations needed on the
653                          * offset in the descriptor for the MOVE command.
654                          */
655                         move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH1, 0, 6,
656                                                      IMMED);
657                         move_cmd_write_descbuf = MOVE(p, MATH1, 0, DESCBUF, 0,
658                                                       8, WAITCOMP | IMMED);
659                 }
660                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
661                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
662                               OP_ALG_AAI_CMAC,
663                               OP_ALG_AS_INITFINAL,
664                               dir == OP_TYPE_ENCAP_PROTOCOL ?
665                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
666                               DIR_ENC);
667
668                 if (rta_sec_era > RTA_SEC_ERA_2) {
669                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
670                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
671                                     VLF | LAST1 | LAST2 | FLUSH1);
672                 } else {
673                         SEQFIFOLOAD(p, MSGINSNOOP, 0,
674                                     VLF | LAST1 | LAST2 | FLUSH1);
675                         SET_LABEL(p, local_offset);
676
677                         /* Shut off automatic Info FIFO entries */
678                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
679
680                         /*
681                          * Placeholder for MOVE command with length from
682                          * M1 register
683                          */
684                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
685
686                         /* Enable automatic Info FIFO entries */
687                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
688                 }
689
690                 if (dir == OP_TYPE_DECAP_PROTOCOL)
691                         SEQFIFOLOAD(p, ICV1, 4, LAST1 | FLUSH1);
692                 else
693                         SEQSTORE(p, CONTEXT1, 0, 4, 0);
694
695                 break;
696
697         case PDCP_AUTH_TYPE_ZUC:
698                 if (rta_sec_era < RTA_SEC_ERA_5) {
699                         pr_err("Invalid era for selected algorithm\n");
700                         return -ENOTSUP;
701                 }
702                 /* Insert Auth Key */
703                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
704                     authdata->keylen, INLINE_KEY(authdata));
705                 SEQLOAD(p, MATH0, offset, length, 0);
706                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
707                 SEQINPTR(p, 0, length, RTO);
708                 if (swap == false) {
709                         MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
710                               IFB | IMMED2);
711                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
712
713                         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
714                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
715                         MOVEB(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
716
717                 } else {
718                         MATHB(p, MATH0, AND, sn_mask, MATH1, 8,
719                               IFB | IMMED2);
720                         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
721
722                         MOVE(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
723                         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
724                         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, IMMED);
725                 }
726                 if (dir == OP_TYPE_DECAP_PROTOCOL)
727                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4,
728                               IMMED2);
729                 else
730                         MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
731
732                 MATHB(p, MATH1, SUB, ZERO, VSEQINSZ, 4, 0);
733                 MATHB(p, MATH1, SUB, ZERO, VSEQOUTSZ, 4, 0);
734                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
735                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
736                               OP_ALG_AAI_F9,
737                               OP_ALG_AS_INITFINAL,
738                               dir == OP_TYPE_ENCAP_PROTOCOL ?
739                                      ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
740                               DIR_ENC);
741                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
742                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
743
744                 if (dir == OP_TYPE_DECAP_PROTOCOL)
745                         SEQFIFOLOAD(p, ICV2, 4, LAST2);
746                 else
747                         SEQSTORE(p, CONTEXT2, 0, 4, 0);
748
749                 break;
750
751         default:
752                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
753                        "pdcp_insert_cplane_int_only_op", authdata->algtype);
754                 return -EINVAL;
755         }
756
757         if (rta_sec_era < RTA_SEC_ERA_3) {
758                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
759                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
760         }
761
762         return 0;
763 }
764
765 static inline int
766 pdcp_insert_cplane_enc_only_op(struct program *p,
767                                bool swap __maybe_unused,
768                                struct alginfo *cipherdata,
769                                struct alginfo *authdata __maybe_unused,
770                                unsigned int dir,
771                                enum pdcp_sn_size sn_size,
772                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
773 {
774         uint32_t offset = 0, length = 0, sn_mask = 0;
775         /* Insert Cipher Key */
776         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
777             cipherdata->keylen, INLINE_KEY(cipherdata));
778
779         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
780                 if (sn_size == PDCP_SN_SIZE_5)
781                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
782                                  (uint16_t)cipherdata->algtype << 8);
783                 else
784                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
785                                  (uint16_t)cipherdata->algtype << 8);
786                 return 0;
787         }
788         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
789         switch (sn_size) {
790         case PDCP_SN_SIZE_5:
791                 offset = 7;
792                 length = 1;
793                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
794                                         PDCP_C_PLANE_SN_MASK_BE;
795                 break;
796         case PDCP_SN_SIZE_18:
797                 offset = 5;
798                 length = 3;
799                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
800                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
801                 break;
802         case PDCP_SN_SIZE_7:
803         case PDCP_SN_SIZE_12:
804         case PDCP_SN_SIZE_15:
805                 pr_err("Invalid sn_size for %s\n", __func__);
806                 return -ENOTSUP;
807
808         }
809
810         SEQLOAD(p, MATH0, offset, length, 0);
811         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
812         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
813         SEQSTORE(p, MATH0, offset, length, 0);
814         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
815         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
816         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
817
818         switch (cipherdata->algtype) {
819         case PDCP_CIPHER_TYPE_SNOW:
820                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
821
822                 if (rta_sec_era > RTA_SEC_ERA_2) {
823                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
824                 } else {
825                         MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
826                         MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
827                 }
828
829                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
830                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
831                               IMMED2);
832                 else
833                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
834                               IMMED2);
835                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
836                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
837                               OP_ALG_AAI_F8,
838                               OP_ALG_AS_INITFINAL, ICV_CHECK_DISABLE,
839                               dir == OP_TYPE_ENCAP_PROTOCOL ?
840                                         DIR_ENC : DIR_DEC);
841                 break;
842
843         case PDCP_CIPHER_TYPE_AES:
844                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
845
846                 if (rta_sec_era > RTA_SEC_ERA_2) {
847                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
848                 } else {
849                         MATHB(p, SEQINSZ, SUB, ONE, MATH1, 4, 0);
850                         MATHB(p, MATH1, ADD, ONE, VSEQINSZ, 4, 0);
851                 }
852
853                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
854                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
855                               IMMED2);
856                 else
857                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
858                               IMMED2);
859
860                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
861                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
862                               OP_ALG_AAI_CTR,
863                               OP_ALG_AS_INITFINAL,
864                               ICV_CHECK_DISABLE,
865                               dir == OP_TYPE_ENCAP_PROTOCOL ?
866                                         DIR_ENC : DIR_DEC);
867                 break;
868
869         case PDCP_CIPHER_TYPE_ZUC:
870                 if (rta_sec_era < RTA_SEC_ERA_5) {
871                         pr_err("Invalid era for selected algorithm\n");
872                         return -ENOTSUP;
873                 }
874
875                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
876                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
877                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
878                 if (dir == OP_TYPE_ENCAP_PROTOCOL)
879                         MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
880                               IMMED2);
881                 else
882                         MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4,
883                               IMMED2);
884
885                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
886                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
887                               OP_ALG_AAI_F8,
888                               OP_ALG_AS_INITFINAL,
889                               ICV_CHECK_DISABLE,
890                               dir == OP_TYPE_ENCAP_PROTOCOL ?
891                                         DIR_ENC : DIR_DEC);
892                 break;
893
894         default:
895                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
896                        "pdcp_insert_cplane_enc_only_op", cipherdata->algtype);
897                 return -EINVAL;
898         }
899
900         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
901                 SEQFIFOLOAD(p, MSG1, 0, VLF);
902                 FIFOLOAD(p, MSG1, PDCP_NULL_INT_MAC_I_VAL, 4,
903                          LAST1 | FLUSH1 | IMMED);
904         } else {
905                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
906                 MOVE(p, OFIFO, 0, MATH1, 4, PDCP_MAC_I_LEN, WAITCOMP | IMMED);
907                 MATHB(p, MATH1, XOR, PDCP_NULL_INT_MAC_I_VAL, NONE, 4, IMMED2);
908                 JUMP(p, PDCP_NULL_INT_ICV_CHECK_FAILED_STATUS,
909                      HALT_STATUS, ALL_FALSE, MATH_Z);
910         }
911
912         return 0;
913 }
914
915 static inline int
916 pdcp_insert_cplane_acc_op(struct program *p,
917                           bool swap __maybe_unused,
918                           struct alginfo *cipherdata,
919                           struct alginfo *authdata,
920                           unsigned int dir,
921                           enum pdcp_sn_size sn_size,
922                           unsigned char era_2_hfn_ovrd __maybe_unused)
923 {
924         /* Insert Auth Key */
925         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
926             INLINE_KEY(authdata));
927
928         /* Insert Cipher Key */
929         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
930             cipherdata->keylen, INLINE_KEY(cipherdata));
931
932         if (sn_size == PDCP_SN_SIZE_5)
933                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL,
934                          (uint16_t)cipherdata->algtype);
935         else
936                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
937                          ((uint16_t)cipherdata->algtype << 8) |
938                           (uint16_t)authdata->algtype);
939
940         return 0;
941 }
942
943 static inline int
944 pdcp_insert_cplane_snow_aes_op(struct program *p,
945                                bool swap __maybe_unused,
946                                struct alginfo *cipherdata,
947                                struct alginfo *authdata,
948                                unsigned int dir,
949                                enum pdcp_sn_size sn_size,
950                                unsigned char era_2_sw_hfn_ovrd)
951 {
952         uint32_t offset = 0, length = 0, sn_mask = 0;
953
954         LABEL(back_to_sd_offset);
955         LABEL(end_desc);
956         LABEL(local_offset);
957         LABEL(jump_to_beginning);
958         LABEL(fifo_load_mac_i_offset);
959         REFERENCE(seqin_ptr_read);
960         REFERENCE(seqin_ptr_write);
961         REFERENCE(seq_out_read);
962         REFERENCE(jump_back_to_sd_cmd);
963         REFERENCE(move_mac_i_to_desc_buf);
964
965         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
966                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
967                                 cipherdata->keylen, INLINE_KEY(cipherdata));
968                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
969                                 authdata->keylen, INLINE_KEY(authdata));
970
971                 if (sn_size == PDCP_SN_SIZE_5)
972                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_CTRL_MIXED,
973                                  ((uint16_t)cipherdata->algtype << 8) |
974                                  (uint16_t)authdata->algtype);
975                 else
976                         PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER_RN,
977                                  ((uint16_t)cipherdata->algtype << 8) |
978                                  (uint16_t)authdata->algtype);
979
980                 return 0;
981         }
982         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
983         switch (sn_size) {
984         case PDCP_SN_SIZE_5:
985                 offset = 7;
986                 length = 1;
987                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
988                                         PDCP_C_PLANE_SN_MASK_BE;
989                 break;
990         case PDCP_SN_SIZE_18:
991                 offset = 5;
992                 length = 3;
993                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
994                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
995                 break;
996         case PDCP_SN_SIZE_7:
997         case PDCP_SN_SIZE_12:
998         case PDCP_SN_SIZE_15:
999                 pr_err("Invalid sn_size for %s\n", __func__);
1000                 return -ENOTSUP;
1001
1002         }
1003
1004         SEQLOAD(p, MATH0, offset, length, 0);
1005         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1006         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1007         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1008         MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1009         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1010         SEQSTORE(p, MATH0, offset, length, 0);
1011         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1012                 if (rta_sec_era > RTA_SEC_ERA_2 ||
1013                     (rta_sec_era == RTA_SEC_ERA_2 &&
1014                                    era_2_sw_hfn_ovrd == 0)) {
1015                         SEQINPTR(p, 0, 1, RTO);
1016                 } else {
1017                         SEQINPTR(p, 0, 5, RTO);
1018                         SEQFIFOLOAD(p, SKIP, 4, 0);
1019                 }
1020                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1021                     authdata->keylen, INLINE_KEY(authdata));
1022                 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1023
1024                 if (rta_sec_era > RTA_SEC_ERA_2) {
1025                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1026                         MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
1027                         MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1028                               4, IMMED2);
1029                 } else {
1030                         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1031                         MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN - 1, VSEQOUTSZ,
1032                               4, IMMED2);
1033                         /*
1034                          * Note: Although the calculations below might seem a
1035                          * little off, the logic is the following:
1036                          *
1037                          * - SEQ IN PTR RTO below needs the full length of the
1038                          *   frame; in case of P4080_REV_2_HFN_OV_WORKAROUND,
1039                          *   this means the length of the frame to be processed
1040                          *   + 4 bytes (the HFN override flag and value).
1041                          *   The length of the frame to be processed minus 1
1042                          *   byte is in the VSIL register (because
1043                          *   VSIL = SIL + 3, due to 1 byte, the header being
1044                          *   already written by the SEQ STORE above). So for
1045                          *   calculating the length to use in RTO, I add one
1046                          *   to the VSIL value in order to obtain the total
1047                          *   frame length. This helps in case of P4080 which
1048                          *   can have the value 0 as an operand in a MATH
1049                          *   command only as SRC1 When the HFN override
1050                          *   workaround is not enabled, the length of the
1051                          *   frame is given by the SIL register; the
1052                          *   calculation is similar to the one in the SEC 4.2
1053                          *   and SEC 5.3 cases.
1054                          */
1055                         if (era_2_sw_hfn_ovrd)
1056                                 MATHB(p, VSEQOUTSZ, ADD, ONE, MATH1, 4,
1057                                       0);
1058                         else
1059                                 MATHB(p, SEQINSZ, ADD, MATH3, MATH1, 4,
1060                                       0);
1061                 }
1062                 /*
1063                  * Placeholder for filling the length in
1064                  * SEQIN PTR RTO below
1065                  */
1066                 seqin_ptr_read = MOVE(p, DESCBUF, 0, MATH1, 0, 6, IMMED);
1067                 seqin_ptr_write = MOVE(p, MATH1, 0, DESCBUF, 0, 8,
1068                                        WAITCOMP | IMMED);
1069                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1070                               OP_ALG_AAI_CMAC,
1071                               OP_ALG_AS_INITFINAL,
1072                               ICV_CHECK_DISABLE,
1073                               DIR_DEC);
1074                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1075                 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1076                 if (rta_sec_era <= RTA_SEC_ERA_3)
1077                         LOAD(p, CLRW_CLR_C1KEY |
1078                              CLRW_CLR_C1CTX |
1079                              CLRW_CLR_C1ICV |
1080                              CLRW_CLR_C1DATAS |
1081                              CLRW_CLR_C1MODE,
1082                              CLRW, 0, 4, IMMED);
1083                 else
1084                         LOAD(p, CLRW_RESET_CLS1_CHA |
1085                              CLRW_CLR_C1KEY |
1086                              CLRW_CLR_C1CTX |
1087                              CLRW_CLR_C1ICV |
1088                              CLRW_CLR_C1DATAS |
1089                              CLRW_CLR_C1MODE,
1090                              CLRW, 0, 4, IMMED);
1091
1092                 if (rta_sec_era <= RTA_SEC_ERA_3)
1093                         LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1094
1095                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1096                     cipherdata->keylen, INLINE_KEY(cipherdata));
1097                 SET_LABEL(p, local_offset);
1098                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1099                 SEQINPTR(p, 0, 0, RTO);
1100
1101                 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
1102                         SEQFIFOLOAD(p, SKIP, 5, 0);
1103                         MATHB(p, SEQINSZ, ADD, ONE, SEQINSZ, 4, 0);
1104                 }
1105
1106                 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1107                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1108                               OP_ALG_AAI_F8,
1109                               OP_ALG_AS_INITFINAL,
1110                               ICV_CHECK_DISABLE,
1111                               DIR_ENC);
1112                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1113
1114                 if (rta_sec_era > RTA_SEC_ERA_2 ||
1115                     (rta_sec_era == RTA_SEC_ERA_2 &&
1116                                    era_2_sw_hfn_ovrd == 0))
1117                         SEQFIFOLOAD(p, SKIP, 1, 0);
1118
1119                 SEQFIFOLOAD(p, MSG1, 0, VLF);
1120                 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1121                 PATCH_MOVE(p, seqin_ptr_read, local_offset);
1122                 PATCH_MOVE(p, seqin_ptr_write, local_offset);
1123         } else {
1124                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1125
1126                 if (rta_sec_era >= RTA_SEC_ERA_5)
1127                         MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1128
1129                 if (rta_sec_era > RTA_SEC_ERA_2)
1130                         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1131                 else
1132                         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
1133
1134                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1135 /*
1136  * TODO: To be changed when proper support is added in RTA (can't load a
1137  * command that is also written by RTA (or patch it for that matter).
1138  * Change when proper RTA support is added.
1139  */
1140                 if (p->ps)
1141                         WORD(p, 0x168B0004);
1142                 else
1143                         WORD(p, 0x16880404);
1144
1145                 jump_back_to_sd_cmd = JUMP(p, 0, LOCAL_JUMP, ALL_TRUE, 0);
1146                 /*
1147                  * Placeholder for command reading  the SEQ OUT command in
1148                  * JD. Done for rereading the decrypted data and performing
1149                  * the integrity check
1150                  */
1151 /*
1152  * TODO: RTA currently doesn't support patching of length of a MOVE command
1153  * Thus, it is inserted as a raw word, as per PS setting.
1154  */
1155                 if (p->ps)
1156                         seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 20,
1157                                             WAITCOMP | IMMED);
1158                 else
1159                         seq_out_read = MOVE(p, DESCBUF, 0, MATH1, 0, 16,
1160                                             WAITCOMP | IMMED);
1161
1162                 MATHB(p, MATH1, XOR, CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR, MATH1, 4,
1163                       IMMED2);
1164                 /* Placeholder for overwriting the SEQ IN  with SEQ OUT */
1165 /*
1166  * TODO: RTA currently doesn't support patching of length of a MOVE command
1167  * Thus, it is inserted as a raw word, as per PS setting.
1168  */
1169                 if (p->ps)
1170                         MOVE(p, MATH1, 0, DESCBUF, 0, 24, IMMED);
1171                 else
1172                         MOVE(p, MATH1, 0, DESCBUF, 0, 20, IMMED);
1173
1174                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1175                     cipherdata->keylen, INLINE_KEY(cipherdata));
1176
1177                 if (rta_sec_era >= RTA_SEC_ERA_4)
1178                         MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1179                 else
1180                         MOVE(p, CONTEXT1, 0, MATH3, 0, 8, IMMED);
1181
1182                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1183                               OP_ALG_AAI_F8,
1184                               OP_ALG_AS_INITFINAL,
1185                               ICV_CHECK_DISABLE,
1186                               DIR_DEC);
1187                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1188                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1189
1190                 if (rta_sec_era <= RTA_SEC_ERA_3)
1191                         move_mac_i_to_desc_buf = MOVE(p, OFIFO, 0, DESCBUF, 0,
1192                                                       4, WAITCOMP | IMMED);
1193                 else
1194                         MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1195
1196                 if (rta_sec_era <= RTA_SEC_ERA_3)
1197                         LOAD(p, CCTRL_RESET_CHA_ALL, CCTRL, 0, 4, IMMED);
1198                 else
1199                         LOAD(p, CLRW_RESET_CLS1_CHA |
1200                              CLRW_CLR_C1KEY |
1201                              CLRW_CLR_C1CTX |
1202                              CLRW_CLR_C1ICV |
1203                              CLRW_CLR_C1DATAS |
1204                              CLRW_CLR_C1MODE,
1205                              CLRW, 0, 4, IMMED);
1206
1207                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1208                     authdata->keylen, INLINE_KEY(authdata));
1209                 /*
1210                  * Placeholder for jump in SD for executing the new SEQ IN PTR
1211                  * command (which is actually the old SEQ OUT PTR command
1212                  * copied over from JD.
1213                  */
1214                 SET_LABEL(p, jump_to_beginning);
1215                 JUMP(p, 1 - jump_to_beginning, LOCAL_JUMP, ALL_TRUE, 0);
1216                 SET_LABEL(p, back_to_sd_offset);
1217                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1218                               OP_ALG_AAI_CMAC,
1219                               OP_ALG_AS_INITFINAL,
1220                               ICV_CHECK_ENABLE,
1221                               DIR_DEC);
1222
1223                 /* Read the # of bytes written in the output buffer + 1 (HDR) */
1224                 MATHB(p, VSEQOUTSZ, ADD, ONE, VSEQINSZ, 4, 0);
1225
1226                 if (rta_sec_era <= RTA_SEC_ERA_3)
1227                         MOVE(p, MATH3, 0, IFIFOAB1, 0, 8, IMMED);
1228                 else
1229                         MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1230
1231                 if (rta_sec_era == RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd)
1232                         SEQFIFOLOAD(p, SKIP, 4, 0);
1233
1234                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1235
1236                 if (rta_sec_era >= RTA_SEC_ERA_4) {
1237                         LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1238                              NFIFOENTRY_DEST_CLASS1 |
1239                              NFIFOENTRY_DTYPE_ICV |
1240                              NFIFOENTRY_LC1 |
1241                              NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1242                         MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1243                 } else {
1244                         SET_LABEL(p, fifo_load_mac_i_offset);
1245                         FIFOLOAD(p, ICV1, fifo_load_mac_i_offset, 4,
1246                                  LAST1 | FLUSH1 | IMMED);
1247                 }
1248
1249                 SET_LABEL(p, end_desc);
1250
1251                 if (!p->ps) {
1252                         PATCH_MOVE(p, seq_out_read, end_desc + 1);
1253                         PATCH_JUMP(p, jump_back_to_sd_cmd,
1254                                    back_to_sd_offset + jump_back_to_sd_cmd - 5);
1255
1256                         if (rta_sec_era <= RTA_SEC_ERA_3)
1257                                 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1258                                            fifo_load_mac_i_offset + 1);
1259                 } else {
1260                         PATCH_MOVE(p, seq_out_read, end_desc + 2);
1261                         PATCH_JUMP(p, jump_back_to_sd_cmd,
1262                                    back_to_sd_offset + jump_back_to_sd_cmd - 5);
1263
1264                         if (rta_sec_era <= RTA_SEC_ERA_3)
1265                                 PATCH_MOVE(p, move_mac_i_to_desc_buf,
1266                                            fifo_load_mac_i_offset + 1);
1267                 }
1268         }
1269
1270         return 0;
1271 }
1272
1273 static inline int
1274 pdcp_insert_cplane_aes_snow_op(struct program *p,
1275                                bool swap __maybe_unused,
1276                                struct alginfo *cipherdata,
1277                                struct alginfo *authdata,
1278                                unsigned int dir,
1279                                enum pdcp_sn_size sn_size,
1280                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1281 {
1282         uint32_t offset = 0, length = 0, sn_mask = 0;
1283
1284         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1285             cipherdata->keylen, INLINE_KEY(cipherdata));
1286         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1287             INLINE_KEY(authdata));
1288
1289         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1290                 int pclid;
1291
1292                 if (sn_size == PDCP_SN_SIZE_5)
1293                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1294                 else
1295                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1296
1297                 PROTOCOL(p, dir, pclid,
1298                          ((uint16_t)cipherdata->algtype << 8) |
1299                          (uint16_t)authdata->algtype);
1300
1301                 return 0;
1302         }
1303         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1304         switch (sn_size) {
1305         case PDCP_SN_SIZE_5:
1306                 offset = 7;
1307                 length = 1;
1308                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1309                                         PDCP_C_PLANE_SN_MASK_BE;
1310                 break;
1311         case PDCP_SN_SIZE_18:
1312                 offset = 5;
1313                 length = 3;
1314                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1315                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1316                 break;
1317         case PDCP_SN_SIZE_7:
1318         case PDCP_SN_SIZE_12:
1319         case PDCP_SN_SIZE_15:
1320                 pr_err("Invalid sn_size for %s\n", __func__);
1321                 return -ENOTSUP;
1322
1323         }
1324
1325         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1326                 MATHB(p, SEQINSZ, SUB, ONE, VSEQINSZ, 4, 0);
1327
1328         SEQLOAD(p, MATH0, offset, length, 0);
1329         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1330         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1331         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1332
1333         SEQSTORE(p, MATH0, offset, length, 0);
1334         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1335         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1336         MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1337         MOVE(p, MATH1, 0, CONTEXT1, 16, 8, IMMED);
1338         MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1339         if (swap == false) {
1340                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2, 4,
1341                         IMMED2);
1342                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3, 4,
1343                         IMMED2);
1344         } else {
1345                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1346                         4, IMMED2);
1347                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1348                         4, IMMED2);
1349         }
1350         MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1351         MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1352         MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1353         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1354                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1355         } else {
1356                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, MATH1, 4, IMMED2);
1357
1358                 MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
1359                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
1360         }
1361
1362         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1363                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1364         else
1365                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1366
1367         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1368                       OP_ALG_AAI_F9,
1369                       OP_ALG_AS_INITFINAL,
1370                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1371                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1372                       DIR_DEC);
1373         ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1374                       OP_ALG_AAI_CTR,
1375                       OP_ALG_AS_INITFINAL,
1376                       ICV_CHECK_DISABLE,
1377                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1378
1379         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1380                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1381                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1382         } else {
1383                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1384                 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1385                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1386
1387                 if (rta_sec_era >= RTA_SEC_ERA_6)
1388                         LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1389
1390                 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1391
1392                 NFIFOADD(p, IFIFO, ICV2, 4, LAST2);
1393
1394                 if (rta_sec_era <= RTA_SEC_ERA_2) {
1395                         /* Shut off automatic Info FIFO entries */
1396                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
1397                         MOVE(p, MATH0, 0, IFIFOAB2, 0, 4, WAITCOMP | IMMED);
1398                 } else {
1399                         MOVE(p, MATH0, 0, IFIFO, 0, 4, WAITCOMP | IMMED);
1400                 }
1401         }
1402
1403         return 0;
1404 }
1405
1406 static inline int
1407 pdcp_insert_cplane_snow_zuc_op(struct program *p,
1408                                bool swap __maybe_unused,
1409                                struct alginfo *cipherdata,
1410                                struct alginfo *authdata,
1411                                unsigned int dir,
1412                                enum pdcp_sn_size sn_size,
1413                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1414 {
1415         uint32_t offset = 0, length = 0, sn_mask = 0;
1416
1417         LABEL(keyjump);
1418         REFERENCE(pkeyjump);
1419
1420         if (rta_sec_era < RTA_SEC_ERA_5) {
1421                 pr_err("Invalid era for selected algorithm\n");
1422                 return -ENOTSUP;
1423         }
1424
1425         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1426         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1427             cipherdata->keylen, INLINE_KEY(cipherdata));
1428         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1429             INLINE_KEY(authdata));
1430
1431         SET_LABEL(p, keyjump);
1432
1433         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1434                 int pclid;
1435
1436                 if (sn_size == PDCP_SN_SIZE_5)
1437                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1438                 else
1439                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1440
1441                 PROTOCOL(p, dir, pclid,
1442                          ((uint16_t)cipherdata->algtype << 8) |
1443                          (uint16_t)authdata->algtype);
1444                 return 0;
1445         }
1446         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1447         switch (sn_size) {
1448         case PDCP_SN_SIZE_5:
1449                 offset = 7;
1450                 length = 1;
1451                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1452                                         PDCP_C_PLANE_SN_MASK_BE;
1453                 break;
1454         case PDCP_SN_SIZE_18:
1455                 offset = 5;
1456                 length = 3;
1457                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1458                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1459                 break;
1460         case PDCP_SN_SIZE_7:
1461         case PDCP_SN_SIZE_12:
1462         case PDCP_SN_SIZE_15:
1463                 pr_err("Invalid sn_size for %s\n", __func__);
1464                 return -ENOTSUP;
1465
1466         }
1467
1468         SEQLOAD(p, MATH0, offset, length, 0);
1469         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1470         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1471         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1472
1473         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1474         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1475         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1476         MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1477         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1478
1479         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1480                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1481         else
1482                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1483
1484         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1485         SEQSTORE(p, MATH0, offset, length, 0);
1486
1487         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1488                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1489                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1490         } else {
1491                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1492                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1493         }
1494
1495         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1496                       OP_ALG_AAI_F9,
1497                       OP_ALG_AS_INITFINAL,
1498                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1499                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1500                       DIR_ENC);
1501
1502         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
1503                       OP_ALG_AAI_F8,
1504                       OP_ALG_AS_INITFINAL,
1505                       ICV_CHECK_DISABLE,
1506                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1507         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1508                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1509         } else {
1510                 /* Save ICV */
1511                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1512                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1513                      NFIFOENTRY_DEST_CLASS2 |
1514                      NFIFOENTRY_DTYPE_ICV |
1515                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1516                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1517         }
1518
1519         /* Reset ZUCA mode and done interrupt */
1520         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1521         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1522
1523         PATCH_JUMP(p, pkeyjump, keyjump);
1524         return 0;
1525 }
1526
1527 static inline int
1528 pdcp_insert_cplane_aes_zuc_op(struct program *p,
1529                               bool swap __maybe_unused,
1530                               struct alginfo *cipherdata,
1531                               struct alginfo *authdata,
1532                               unsigned int dir,
1533                               enum pdcp_sn_size sn_size,
1534                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1535 {
1536         uint32_t offset = 0, length = 0, sn_mask = 0;
1537         LABEL(keyjump);
1538         REFERENCE(pkeyjump);
1539
1540         if (rta_sec_era < RTA_SEC_ERA_5) {
1541                 pr_err("Invalid era for selected algorithm\n");
1542                 return -ENOTSUP;
1543         }
1544
1545         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1546         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1547             cipherdata->keylen, INLINE_KEY(cipherdata));
1548         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1549             INLINE_KEY(authdata));
1550
1551         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1552                 int pclid;
1553
1554                 if (sn_size == PDCP_SN_SIZE_5)
1555                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1556                 else
1557                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1558
1559                 PROTOCOL(p, dir, pclid,
1560                          ((uint16_t)cipherdata->algtype << 8) |
1561                          (uint16_t)authdata->algtype);
1562
1563                 return 0;
1564         }
1565         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1566         switch (sn_size) {
1567         case PDCP_SN_SIZE_5:
1568                 offset = 7;
1569                 length = 1;
1570                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1571                                         PDCP_C_PLANE_SN_MASK_BE;
1572                 break;
1573         case PDCP_SN_SIZE_18:
1574                 offset = 5;
1575                 length = 3;
1576                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1577                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1578                 break;
1579         case PDCP_SN_SIZE_7:
1580         case PDCP_SN_SIZE_12:
1581         case PDCP_SN_SIZE_15:
1582                 pr_err("Invalid sn_size for %s\n", __func__);
1583                 return -ENOTSUP;
1584
1585         }
1586
1587         SET_LABEL(p, keyjump);
1588         SEQLOAD(p, MATH0, offset, length, 0);
1589         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1590         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1591         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1592
1593         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1594         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1595         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1596         MOVE(p, MATH2, 0, CONTEXT1, 16, 8, IMMED);
1597         MOVE(p, MATH2, 0, CONTEXT2, 0, 8, WAITCOMP | IMMED);
1598
1599         if (dir == OP_TYPE_ENCAP_PROTOCOL)
1600                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1601         else
1602                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1603
1604         MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1605         SEQSTORE(p, MATH0, offset, length, 0);
1606
1607         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1608                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1609                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1610         } else {
1611                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1612                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST1 | FLUSH1);
1613         }
1614
1615         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
1616                       OP_ALG_AAI_F9,
1617                       OP_ALG_AS_INITFINAL,
1618                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1619                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1620                       DIR_ENC);
1621
1622         ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1623                       OP_ALG_AAI_CTR,
1624                       OP_ALG_AS_INITFINAL,
1625                       ICV_CHECK_DISABLE,
1626                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1627
1628         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1629                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1630         } else {
1631                 /* Save ICV */
1632                 MOVE(p, OFIFO, 0, MATH0, 0, 4, IMMED);
1633
1634                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1635                      NFIFOENTRY_DEST_CLASS2 |
1636                      NFIFOENTRY_DTYPE_ICV |
1637                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1638                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, WAITCOMP | IMMED);
1639         }
1640
1641         /* Reset ZUCA mode and done interrupt */
1642         LOAD(p, CLRW_CLR_C2MODE, CLRW, 0, 4, IMMED);
1643         LOAD(p, CIRQ_ZADI, ICTRL, 0, 4, IMMED);
1644
1645         PATCH_JUMP(p, pkeyjump, keyjump);
1646
1647         return 0;
1648 }
1649
1650 static inline int
1651 pdcp_insert_cplane_zuc_snow_op(struct program *p,
1652                                bool swap __maybe_unused,
1653                                struct alginfo *cipherdata,
1654                                struct alginfo *authdata,
1655                                unsigned int dir,
1656                                enum pdcp_sn_size sn_size,
1657                                unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1658 {
1659         uint32_t offset = 0, length = 0, sn_mask = 0;
1660         LABEL(keyjump);
1661         REFERENCE(pkeyjump);
1662
1663         if (rta_sec_era < RTA_SEC_ERA_5) {
1664                 pr_err("Invalid era for selected algorithm\n");
1665                 return -ENOTSUP;
1666         }
1667
1668         pkeyjump = JUMP(p, keyjump, LOCAL_JUMP, ALL_TRUE, SHRD | SELF | BOTH);
1669         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1670             cipherdata->keylen, INLINE_KEY(cipherdata));
1671         KEY(p, KEY2, authdata->key_enc_flags, authdata->key, authdata->keylen,
1672             INLINE_KEY(authdata));
1673
1674         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1675                 int pclid;
1676
1677                 if (sn_size == PDCP_SN_SIZE_5)
1678                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1679                 else
1680                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1681
1682                 PROTOCOL(p, dir, pclid,
1683                          ((uint16_t)cipherdata->algtype << 8) |
1684                          (uint16_t)authdata->algtype);
1685
1686                 return 0;
1687         }
1688         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1689         switch (sn_size) {
1690         case PDCP_SN_SIZE_5:
1691                 offset = 7;
1692                 length = 1;
1693                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1694                                         PDCP_C_PLANE_SN_MASK_BE;
1695                 break;
1696         case PDCP_SN_SIZE_18:
1697                 offset = 5;
1698                 length = 3;
1699                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1700                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1701                 break;
1702         case PDCP_SN_SIZE_7:
1703         case PDCP_SN_SIZE_12:
1704         case PDCP_SN_SIZE_15:
1705                 pr_err("Invalid sn_size for %s\n", __func__);
1706                 return -ENOTSUP;
1707
1708         }
1709         SET_LABEL(p, keyjump);
1710         SEQLOAD(p, MATH0, offset, length, 0);
1711         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1712         MOVE(p, MATH0, 7, IFIFOAB2, 0, 1, IMMED);
1713         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1714
1715         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1716         MOVE(p, DESCBUF, 4, MATH2, 0, 8, WAITCOMP | IMMED);
1717         MATHB(p, MATH1, OR, MATH2, MATH1, 8, 0);
1718         MOVE(p, MATH1, 0, CONTEXT1, 0, 8, IMMED);
1719         MOVE(p, MATH1, 0, CONTEXT2, 0, 4, IMMED);
1720         if (swap == false) {
1721                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK), MATH2,
1722                         4, IMMED2);
1723                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK), MATH3,
1724                         4, IMMED2);
1725         } else {
1726                 MATHB(p, MATH1, AND, lower_32_bits(PDCP_BEARER_MASK_BE), MATH2,
1727                         4, IMMED2);
1728                 MATHB(p, MATH1, AND, upper_32_bits(PDCP_DIR_MASK_BE), MATH3,
1729                         4, IMMED2);
1730         }
1731         MATHB(p, MATH3, SHLD, MATH3, MATH3, 8, 0);
1732         MOVE(p, MATH2, 4, OFIFO, 0, 12, IMMED);
1733         MOVE(p, OFIFO, 0, CONTEXT2, 4, 12, IMMED);
1734
1735         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1736                 MATHB(p, SEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1737                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1738         } else {
1739                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1740                 MATHB(p, VSEQOUTSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1741         }
1742
1743         SEQSTORE(p, MATH0, offset, length, 0);
1744
1745         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1746                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1747                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST2);
1748         } else {
1749                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1750                 SEQFIFOLOAD(p, MSGOUTSNOOP, 0, VLF | LAST2);
1751         }
1752
1753         ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
1754                       OP_ALG_AAI_F9,
1755                       OP_ALG_AS_INITFINAL,
1756                       dir == OP_TYPE_ENCAP_PROTOCOL ?
1757                              ICV_CHECK_DISABLE : ICV_CHECK_ENABLE,
1758                       DIR_DEC);
1759
1760         ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1761                       OP_ALG_AAI_F8,
1762                       OP_ALG_AS_INITFINAL,
1763                       ICV_CHECK_DISABLE,
1764                       dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC);
1765
1766         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1767                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1768         } else {
1769                 SEQFIFOLOAD(p, MSG1, 4, LAST1 | FLUSH1);
1770                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CLASS1 | NOP | NIFP);
1771
1772                 if (rta_sec_era >= RTA_SEC_ERA_6)
1773                         /*
1774                          * For SEC ERA 6, there's a problem with the OFIFO
1775                          * pointer, and thus it needs to be reset here before
1776                          * moving to M0.
1777                          */
1778                         LOAD(p, 0, DCTRL, 0, LDLEN_RST_CHA_OFIFO_PTR, IMMED);
1779
1780                 /* Put ICV to M0 before sending it to C2 for comparison. */
1781                 MOVE(p, OFIFO, 0, MATH0, 0, 4, WAITCOMP | IMMED);
1782
1783                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1784                      NFIFOENTRY_DEST_CLASS2 |
1785                      NFIFOENTRY_DTYPE_ICV |
1786                      NFIFOENTRY_LC2 | 4, NFIFO_SZL, 0, 4, IMMED);
1787                 MOVE(p, MATH0, 0, ALTSOURCE, 0, 4, IMMED);
1788         }
1789
1790         PATCH_JUMP(p, pkeyjump, keyjump);
1791         return 0;
1792 }
1793
1794 static inline int
1795 pdcp_insert_cplane_zuc_aes_op(struct program *p,
1796                               bool swap __maybe_unused,
1797                               struct alginfo *cipherdata,
1798                               struct alginfo *authdata,
1799                               unsigned int dir,
1800                               enum pdcp_sn_size sn_size,
1801                               unsigned char era_2_sw_hfn_ovrd __maybe_unused)
1802 {
1803         uint32_t offset = 0, length = 0, sn_mask = 0;
1804         if (rta_sec_era < RTA_SEC_ERA_5) {
1805                 pr_err("Invalid era for selected algorithm\n");
1806                 return -ENOTSUP;
1807         }
1808
1809         if (rta_sec_era >= RTA_SEC_ERA_8 && sn_size != PDCP_SN_SIZE_18) {
1810                 int pclid;
1811
1812                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1813                                 cipherdata->keylen, INLINE_KEY(cipherdata));
1814                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
1815                                 authdata->keylen, INLINE_KEY(authdata));
1816
1817                 if (sn_size == PDCP_SN_SIZE_5)
1818                         pclid = OP_PCLID_LTE_PDCP_CTRL_MIXED;
1819                 else
1820                         pclid = OP_PCLID_LTE_PDCP_USER_RN;
1821
1822                 PROTOCOL(p, dir, pclid,
1823                          ((uint16_t)cipherdata->algtype << 8) |
1824                          (uint16_t)authdata->algtype);
1825                 return 0;
1826         }
1827         /* Non-proto is supported only for 5bit cplane and 18bit uplane */
1828         switch (sn_size) {
1829         case PDCP_SN_SIZE_5:
1830                 offset = 7;
1831                 length = 1;
1832                 sn_mask = (swap == false) ? PDCP_C_PLANE_SN_MASK :
1833                                         PDCP_C_PLANE_SN_MASK_BE;
1834                 break;
1835         case PDCP_SN_SIZE_18:
1836                 offset = 5;
1837                 length = 3;
1838                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1839                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1840                 break;
1841         case PDCP_SN_SIZE_7:
1842         case PDCP_SN_SIZE_12:
1843         case PDCP_SN_SIZE_15:
1844                 pr_err("Invalid sn_size for %s\n", __func__);
1845                 return -ENOTSUP;
1846         }
1847
1848         SEQLOAD(p, MATH0, offset, length, 0);
1849         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1850         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1851
1852         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1853         MOVE(p, DESCBUF, 4, MATH2, 0, 0x08, WAITCOMP | IMMED);
1854         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1855         SEQSTORE(p, MATH0, offset, length, 0);
1856         if (dir == OP_TYPE_ENCAP_PROTOCOL) {
1857                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1858                     authdata->keylen, INLINE_KEY(authdata));
1859                 MOVE(p, MATH2, 0, IFIFOAB1, 0, 0x08, IMMED);
1860                 MOVE(p, MATH0, 7, IFIFOAB1, 0, 1, IMMED);
1861
1862                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1863                 MATHB(p, VSEQINSZ, ADD, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1864
1865                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1866                               OP_ALG_AAI_CMAC,
1867                               OP_ALG_AS_INITFINAL,
1868                               ICV_CHECK_DISABLE,
1869                               DIR_DEC);
1870                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1871                 MOVE(p, CONTEXT1, 0, MATH3, 0, 4, WAITCOMP | IMMED);
1872                 LOAD(p, CLRW_RESET_CLS1_CHA |
1873                      CLRW_CLR_C1KEY |
1874                      CLRW_CLR_C1CTX |
1875                      CLRW_CLR_C1ICV |
1876                      CLRW_CLR_C1DATAS |
1877                      CLRW_CLR_C1MODE,
1878                      CLRW, 0, 4, IMMED);
1879
1880                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1881                     cipherdata->keylen, INLINE_KEY(cipherdata));
1882
1883                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1884                 SEQINPTR(p, 0, PDCP_NULL_MAX_FRAME_LEN, RTO);
1885
1886                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1887                               OP_ALG_AAI_F8,
1888                               OP_ALG_AS_INITFINAL,
1889                               ICV_CHECK_DISABLE,
1890                               DIR_ENC);
1891                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
1892
1893                 SEQFIFOLOAD(p, SKIP, 1, 0);
1894
1895                 SEQFIFOLOAD(p, MSG1, 0, VLF);
1896                 MOVE(p, MATH3, 0, IFIFOAB1, 0, 4, LAST1 | FLUSH1 | IMMED);
1897         } else {
1898                 MOVE(p, MATH2, 0, CONTEXT1, 0, 8, IMMED);
1899
1900                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1901
1902                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1903
1904                 MATHB(p, SEQINSZ, SUB, PDCP_MAC_I_LEN, VSEQOUTSZ, 4, IMMED2);
1905
1906                 KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1907                     cipherdata->keylen, INLINE_KEY(cipherdata));
1908
1909                 MOVE(p, CONTEXT1, 0, CONTEXT2, 0, 8, IMMED);
1910
1911                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
1912                               OP_ALG_AAI_F8,
1913                               OP_ALG_AS_INITFINAL,
1914                               ICV_CHECK_DISABLE,
1915                               DIR_DEC);
1916                 SEQFIFOSTORE(p, MSG, 0, 0, VLF | CONT);
1917                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1918
1919                 MOVE(p, OFIFO, 0, MATH3, 0, 4, IMMED);
1920
1921                 LOAD(p, CLRW_RESET_CLS1_CHA |
1922                      CLRW_CLR_C1KEY |
1923                      CLRW_CLR_C1CTX |
1924                      CLRW_CLR_C1ICV |
1925                      CLRW_CLR_C1DATAS |
1926                      CLRW_CLR_C1MODE,
1927                      CLRW, 0, 4, IMMED);
1928
1929                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
1930                     authdata->keylen, INLINE_KEY(authdata));
1931
1932                 SEQINPTR(p, 0, 0, SOP);
1933
1934                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
1935                               OP_ALG_AAI_CMAC,
1936                               OP_ALG_AS_INITFINAL,
1937                               ICV_CHECK_ENABLE,
1938                               DIR_DEC);
1939
1940                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
1941
1942                 MOVE(p, CONTEXT2, 0, IFIFOAB1, 0, 8, IMMED);
1943
1944                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
1945
1946                 LOAD(p, NFIFOENTRY_STYPE_ALTSOURCE |
1947                      NFIFOENTRY_DEST_CLASS1 |
1948                      NFIFOENTRY_DTYPE_ICV |
1949                      NFIFOENTRY_LC1 |
1950                      NFIFOENTRY_FC1 | 4, NFIFO_SZL, 0, 4, IMMED);
1951                 MOVE(p, MATH3, 0, ALTSOURCE, 0, 4, IMMED);
1952         }
1953
1954         return 0;
1955 }
1956
1957 static inline int
1958 pdcp_insert_uplane_no_int_op(struct program *p,
1959                             bool swap __maybe_unused,
1960                             struct alginfo *cipherdata,
1961                             unsigned int dir,
1962                             enum pdcp_sn_size sn_size)
1963 {
1964         int op;
1965         uint32_t sn_mask;
1966
1967         /* Insert Cipher Key */
1968         KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
1969             cipherdata->keylen, INLINE_KEY(cipherdata));
1970
1971         if ((rta_sec_era >= RTA_SEC_ERA_8 && sn_size == PDCP_SN_SIZE_15) ||
1972                         (rta_sec_era >= RTA_SEC_ERA_10)) {
1973                 PROTOCOL(p, dir, OP_PCLID_LTE_PDCP_USER,
1974                          (uint16_t)cipherdata->algtype);
1975                 return 0;
1976         }
1977
1978         if (sn_size == PDCP_SN_SIZE_15) {
1979                 SEQLOAD(p, MATH0, 6, 2, 0);
1980                 sn_mask = (swap == false) ? PDCP_U_PLANE_15BIT_SN_MASK :
1981                                         PDCP_U_PLANE_15BIT_SN_MASK_BE;
1982         } else { /* SN Size == PDCP_SN_SIZE_18 */
1983                 SEQLOAD(p, MATH0, 5, 3, 0);
1984                 sn_mask = (swap == false) ? PDCP_U_PLANE_18BIT_SN_MASK :
1985                                         PDCP_U_PLANE_18BIT_SN_MASK_BE;
1986         }
1987         JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
1988         MATHB(p, MATH0, AND, sn_mask, MATH1, 8, IFB | IMMED2);
1989
1990         if (sn_size == PDCP_SN_SIZE_15)
1991                 SEQSTORE(p, MATH0, 6, 2, 0);
1992         else /* SN Size == PDCP_SN_SIZE_18 */
1993                 SEQSTORE(p, MATH0, 5, 3, 0);
1994
1995         MATHB(p, MATH1, SHLD, MATH1, MATH1, 8, 0);
1996         MOVEB(p, DESCBUF, 8, MATH2, 0, 8, WAITCOMP | IMMED);
1997         MATHB(p, MATH1, OR, MATH2, MATH2, 8, 0);
1998
1999         MATHB(p, SEQINSZ, SUB, MATH3, VSEQINSZ, 4, 0);
2000         MATHB(p, SEQINSZ, SUB, MATH3, VSEQOUTSZ, 4, 0);
2001
2002         SEQFIFOSTORE(p, MSG, 0, 0, VLF);
2003
2004         op = dir == OP_TYPE_ENCAP_PROTOCOL ? DIR_ENC : DIR_DEC;
2005         switch (cipherdata->algtype) {
2006         case PDCP_CIPHER_TYPE_SNOW:
2007                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 8, WAITCOMP | IMMED);
2008                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F8,
2009                               OP_ALG_AAI_F8,
2010                               OP_ALG_AS_INITFINAL,
2011                               ICV_CHECK_DISABLE,
2012                               op);
2013                 break;
2014
2015         case PDCP_CIPHER_TYPE_AES:
2016                 MOVEB(p, MATH2, 0, CONTEXT1, 0x10, 0x10, WAITCOMP | IMMED);
2017                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
2018                               OP_ALG_AAI_CTR,
2019                               OP_ALG_AS_INITFINAL,
2020                               ICV_CHECK_DISABLE,
2021                               op);
2022                 break;
2023
2024         case PDCP_CIPHER_TYPE_ZUC:
2025                 if (rta_sec_era < RTA_SEC_ERA_5) {
2026                         pr_err("Invalid era for selected algorithm\n");
2027                         return -ENOTSUP;
2028                 }
2029                 MOVEB(p, MATH2, 0, CONTEXT1, 0, 0x08, IMMED);
2030                 MOVEB(p, MATH2, 0, CONTEXT1, 0x08, 0x08, WAITCOMP | IMMED);
2031
2032                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCE,
2033                               OP_ALG_AAI_F8,
2034                               OP_ALG_AS_INITFINAL,
2035                               ICV_CHECK_DISABLE,
2036                               op);
2037                 break;
2038
2039         default:
2040                 pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2041                        "pdcp_insert_uplane_15bit_op", cipherdata->algtype);
2042                 return -EINVAL;
2043         }
2044
2045         SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | FLUSH1);
2046
2047         return 0;
2048 }
2049
2050 /*
2051  * Function for inserting the snippet of code responsible for creating
2052  * the HFN override code via either DPOVRD or via the input frame.
2053  */
2054 static inline int
2055 insert_hfn_ov_op(struct program *p,
2056                  uint32_t shift,
2057                  enum pdb_type_e pdb_type,
2058                  unsigned char era_2_sw_hfn_ovrd)
2059 {
2060         uint32_t imm = PDCP_DPOVRD_HFN_OV_EN;
2061         uint16_t hfn_pdb_offset;
2062
2063         if (rta_sec_era == RTA_SEC_ERA_2 && !era_2_sw_hfn_ovrd)
2064                 return 0;
2065
2066         switch (pdb_type) {
2067         case PDCP_PDB_TYPE_NO_PDB:
2068                 /*
2069                  * If there is no PDB, then HFN override mechanism does not
2070                  * make any sense, thus in this case the function will
2071                  * return the pointer to the current position in the
2072                  * descriptor buffer
2073                  */
2074                 return 0;
2075
2076         case PDCP_PDB_TYPE_REDUCED_PDB:
2077                 hfn_pdb_offset = 4;
2078                 break;
2079
2080         case PDCP_PDB_TYPE_FULL_PDB:
2081                 hfn_pdb_offset = 8;
2082                 break;
2083
2084         default:
2085                 return -EINVAL;
2086         }
2087
2088         if (rta_sec_era > RTA_SEC_ERA_2) {
2089                 MATHB(p, DPOVRD, AND, imm, NONE, 8, IFB | IMMED2);
2090         } else {
2091                 SEQLOAD(p, MATH0, 4, 4, 0);
2092                 JUMP(p, 1, LOCAL_JUMP, ALL_TRUE, CALM);
2093                 MATHB(p, MATH0, AND, imm, NONE, 8, IFB | IMMED2);
2094                 SEQSTORE(p, MATH0, 4, 4, 0);
2095         }
2096
2097         if (rta_sec_era >= RTA_SEC_ERA_8)
2098                 JUMP(p, 6, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2099         else
2100                 JUMP(p, 5, LOCAL_JUMP, ALL_TRUE, MATH_Z);
2101
2102         if (rta_sec_era > RTA_SEC_ERA_2)
2103                 MATHB(p, DPOVRD, LSHIFT, shift, MATH0, 4, IMMED2);
2104         else
2105                 MATHB(p, MATH0, LSHIFT, shift, MATH0, 4, IMMED2);
2106
2107         MATHB(p, MATH0, SHLD, MATH0, MATH0, 8, 0);
2108         MOVE(p, MATH0, 0, DESCBUF, hfn_pdb_offset, 4, IMMED);
2109
2110         if (rta_sec_era >= RTA_SEC_ERA_8)
2111                 /*
2112                  * For ERA8, DPOVRD could be handled by the PROTOCOL command
2113                  * itself. For now, this is not done. Thus, clear DPOVRD here
2114                  * to alleviate any side-effects.
2115                  */
2116                 MATHB(p, DPOVRD, AND, ZERO, DPOVRD, 4, STL);
2117
2118         return 0;
2119 }
2120
2121 /*
2122  * PDCP Control PDB creation function
2123  */
2124 static inline enum pdb_type_e
2125 cnstr_pdcp_c_plane_pdb(struct program *p,
2126                        uint32_t hfn,
2127                        enum pdcp_sn_size sn_size,
2128                        unsigned char bearer,
2129                        unsigned char direction,
2130                        uint32_t hfn_threshold,
2131                        struct alginfo *cipherdata,
2132                        struct alginfo *authdata)
2133 {
2134         struct pdcp_pdb pdb;
2135         enum pdb_type_e
2136                 pdb_mask[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2137                         {       /* NULL */
2138                                 PDCP_PDB_TYPE_NO_PDB,           /* NULL */
2139                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2140                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2141                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2142                         },
2143                         {       /* SNOW f8 */
2144                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2145                                 PDCP_PDB_TYPE_FULL_PDB,         /* SNOW f9 */
2146                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2147                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2148                         },
2149                         {       /* AES CTR */
2150                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2151                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2152                                 PDCP_PDB_TYPE_FULL_PDB,         /* AES CMAC */
2153                                 PDCP_PDB_TYPE_REDUCED_PDB       /* ZUC-I */
2154                         },
2155                         {       /* ZUC-E */
2156                                 PDCP_PDB_TYPE_FULL_PDB,         /* NULL */
2157                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* SNOW f9 */
2158                                 PDCP_PDB_TYPE_REDUCED_PDB,      /* AES CMAC */
2159                                 PDCP_PDB_TYPE_FULL_PDB          /* ZUC-I */
2160                         },
2161         };
2162
2163         if (rta_sec_era >= RTA_SEC_ERA_8) {
2164                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2165
2166                 /* To support 12-bit seq numbers, we use u-plane opt in pdb.
2167                  * SEC supports 5-bit only with c-plane opt in pdb.
2168                  */
2169                 if (sn_size == PDCP_SN_SIZE_12) {
2170                         pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2171                         pdb.bearer_dir_res = (uint32_t)
2172                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2173                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2174
2175                         pdb.hfn_thr_res =
2176                         hfn_threshold << PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2177
2178                 } else {
2179                         /* This means 5-bit c-plane.
2180                          * Here we use c-plane opt in pdb
2181                          */
2182
2183                         /* This is a HW issue. Bit 2 should be set to zero,
2184                          * but it does not work this way. Override here.
2185                          */
2186                         pdb.opt_res.rsvd = 0x00000002;
2187
2188                         /* Copy relevant information from user to PDB */
2189                         pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2190                         pdb.bearer_dir_res = (uint32_t)
2191                                 ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2192                                 (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2193                         pdb.hfn_thr_res =
2194                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2195                 }
2196
2197                 /* copy PDB in descriptor*/
2198                 __rta_out32(p, pdb.opt_res.opt);
2199                 __rta_out32(p, pdb.hfn_res);
2200                 __rta_out32(p, pdb.bearer_dir_res);
2201                 __rta_out32(p, pdb.hfn_thr_res);
2202
2203                 return PDCP_PDB_TYPE_FULL_PDB;
2204         }
2205
2206         switch (pdb_mask[cipherdata->algtype][authdata->algtype]) {
2207         case PDCP_PDB_TYPE_NO_PDB:
2208                 break;
2209
2210         case PDCP_PDB_TYPE_REDUCED_PDB:
2211                 __rta_out32(p, (hfn << PDCP_C_PLANE_PDB_HFN_SHIFT));
2212                 __rta_out32(p,
2213                             (uint32_t)((bearer <<
2214                                         PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2215                                         (direction <<
2216                                          PDCP_C_PLANE_PDB_DIR_SHIFT)));
2217                 break;
2218
2219         case PDCP_PDB_TYPE_FULL_PDB:
2220                 memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2221
2222                 /* This is a HW issue. Bit 2 should be set to zero,
2223                  * but it does not work this way. Override here.
2224                  */
2225                 pdb.opt_res.rsvd = 0x00000002;
2226
2227                 /* Copy relevant information from user to PDB */
2228                 pdb.hfn_res = hfn << PDCP_C_PLANE_PDB_HFN_SHIFT;
2229                 pdb.bearer_dir_res = (uint32_t)
2230                         ((bearer << PDCP_C_PLANE_PDB_BEARER_SHIFT) |
2231                          (direction << PDCP_C_PLANE_PDB_DIR_SHIFT));
2232                 pdb.hfn_thr_res =
2233                         hfn_threshold << PDCP_C_PLANE_PDB_HFN_THR_SHIFT;
2234
2235                 /* copy PDB in descriptor*/
2236                 __rta_out32(p, pdb.opt_res.opt);
2237                 __rta_out32(p, pdb.hfn_res);
2238                 __rta_out32(p, pdb.bearer_dir_res);
2239                 __rta_out32(p, pdb.hfn_thr_res);
2240
2241                 break;
2242
2243         default:
2244                 return PDCP_PDB_TYPE_INVALID;
2245         }
2246
2247         return pdb_mask[cipherdata->algtype][authdata->algtype];
2248 }
2249
2250 /*
2251  * PDCP UPlane PDB creation function
2252  */
2253 static inline int
2254 cnstr_pdcp_u_plane_pdb(struct program *p,
2255                        enum pdcp_sn_size sn_size,
2256                        uint32_t hfn, unsigned short bearer,
2257                        unsigned short direction,
2258                        uint32_t hfn_threshold)
2259 {
2260         struct pdcp_pdb pdb;
2261         /* Read options from user */
2262         /* Depending on sequence number length, the HFN and HFN threshold
2263          * have different lengths.
2264          */
2265         memset(&pdb, 0x00, sizeof(struct pdcp_pdb));
2266
2267         switch (sn_size) {
2268         case PDCP_SN_SIZE_7:
2269                 pdb.opt_res.opt |= PDCP_U_PLANE_PDB_OPT_SHORT_SN;
2270                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_SHORT_SN_HFN_SHIFT;
2271                 pdb.hfn_thr_res =
2272                         hfn_threshold<<PDCP_U_PLANE_PDB_SHORT_SN_HFN_THR_SHIFT;
2273                 break;
2274
2275         case PDCP_SN_SIZE_12:
2276                 pdb.opt_res.opt &= (uint32_t)(~PDCP_U_PLANE_PDB_OPT_SHORT_SN);
2277                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_LONG_SN_HFN_SHIFT;
2278                 pdb.hfn_thr_res =
2279                         hfn_threshold<<PDCP_U_PLANE_PDB_LONG_SN_HFN_THR_SHIFT;
2280                 break;
2281
2282         case PDCP_SN_SIZE_15:
2283                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_15B_SN);
2284                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_15BIT_SN_HFN_SHIFT;
2285                 pdb.hfn_thr_res =
2286                         hfn_threshold<<PDCP_U_PLANE_PDB_15BIT_SN_HFN_THR_SHIFT;
2287                 break;
2288
2289         case PDCP_SN_SIZE_18:
2290                 pdb.opt_res.opt = (uint32_t)(PDCP_U_PLANE_PDB_OPT_18B_SN);
2291                 pdb.hfn_res = hfn << PDCP_U_PLANE_PDB_18BIT_SN_HFN_SHIFT;
2292                 pdb.hfn_thr_res =
2293                         hfn_threshold<<PDCP_U_PLANE_PDB_18BIT_SN_HFN_THR_SHIFT;
2294                 break;
2295
2296         default:
2297                 pr_err("Invalid Sequence Number Size setting in PDB\n");
2298                 return -EINVAL;
2299         }
2300
2301         pdb.bearer_dir_res = (uint32_t)
2302                                 ((bearer << PDCP_U_PLANE_PDB_BEARER_SHIFT) |
2303                                  (direction << PDCP_U_PLANE_PDB_DIR_SHIFT));
2304
2305         /* copy PDB in descriptor*/
2306         __rta_out32(p, pdb.opt_res.opt);
2307         __rta_out32(p, pdb.hfn_res);
2308         __rta_out32(p, pdb.bearer_dir_res);
2309         __rta_out32(p, pdb.hfn_thr_res);
2310
2311         return 0;
2312 }
2313 /**
2314  * cnstr_shdsc_pdcp_c_plane_encap - Function for creating a PDCP Control Plane
2315  *                                  encapsulation descriptor.
2316  * @descbuf: pointer to buffer for descriptor construction
2317  * @ps: if 36/40bit addressing is desired, this parameter must be true
2318  * @swap: must be true when core endianness doesn't match SEC endianness
2319  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2320  *       PDCP frames.
2321  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2322  * @bearer: radio bearer ID
2323  * @direction: the direction of the PDCP frame (UL/DL)
2324  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2325  *                 keys should be renegotiated at the earliest convenience.
2326  * @cipherdata: pointer to block cipher transform definitions
2327  *              Valid algorithm values are those from cipher_type_pdcp enum.
2328  * @authdata: pointer to authentication transform definitions
2329  *            Valid algorithm values are those from auth_type_pdcp enum.
2330  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2331  *                     this descriptor. Note: Can only be used for
2332  *                     SEC ERA 2.
2333  * Return: size of descriptor written in words or negative number on error.
2334  *         Once the function returns, the value of this parameter can be used
2335  *         for reclaiming the space that wasn't used for the descriptor.
2336  *
2337  * Note: descbuf must be large enough to contain a full 256 byte long
2338  * descriptor; after the function returns, by subtracting the actual number of
2339  * bytes used, the user can reuse the remaining buffer space for other purposes.
2340  */
2341 static inline int
2342 cnstr_shdsc_pdcp_c_plane_encap(uint32_t *descbuf,
2343                                bool ps,
2344                                bool swap,
2345                                uint32_t hfn,
2346                                enum pdcp_sn_size sn_size,
2347                                unsigned char bearer,
2348                                unsigned char direction,
2349                                uint32_t hfn_threshold,
2350                                struct alginfo *cipherdata,
2351                                struct alginfo *authdata,
2352                                unsigned char era_2_sw_hfn_ovrd)
2353 {
2354         static int
2355                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2356                         (struct program*, bool swap, struct alginfo *,
2357                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2358                         unsigned char __maybe_unused) = {
2359                 {       /* NULL */
2360                         pdcp_insert_cplane_null_op,     /* NULL */
2361                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2362                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2363                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2364                 },
2365                 {       /* SNOW f8 */
2366                         pdcp_insert_cplane_enc_only_op, /* NULL */
2367                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2368                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2369                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2370                 },
2371                 {       /* AES CTR */
2372                         pdcp_insert_cplane_enc_only_op, /* NULL */
2373                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2374                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2375                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2376                 },
2377                 {       /* ZUC-E */
2378                         pdcp_insert_cplane_enc_only_op, /* NULL */
2379                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2380                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2381                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2382                 },
2383         };
2384         static enum rta_share_type
2385                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2386                 {       /* NULL */
2387                         SHR_WAIT,       /* NULL */
2388                         SHR_ALWAYS,     /* SNOW f9 */
2389                         SHR_ALWAYS,     /* AES CMAC */
2390                         SHR_ALWAYS      /* ZUC-I */
2391                 },
2392                 {       /* SNOW f8 */
2393                         SHR_ALWAYS,     /* NULL */
2394                         SHR_ALWAYS,     /* SNOW f9 */
2395                         SHR_WAIT,       /* AES CMAC */
2396                         SHR_WAIT        /* ZUC-I */
2397                 },
2398                 {       /* AES CTR */
2399                         SHR_ALWAYS,     /* NULL */
2400                         SHR_ALWAYS,     /* SNOW f9 */
2401                         SHR_ALWAYS,     /* AES CMAC */
2402                         SHR_WAIT        /* ZUC-I */
2403                 },
2404                 {       /* ZUC-E */
2405                         SHR_ALWAYS,     /* NULL */
2406                         SHR_WAIT,       /* SNOW f9 */
2407                         SHR_WAIT,       /* AES CMAC */
2408                         SHR_ALWAYS      /* ZUC-I */
2409                 },
2410         };
2411         enum pdb_type_e pdb_type;
2412         struct program prg;
2413         struct program *p = &prg;
2414         int err;
2415         LABEL(pdb_end);
2416
2417         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2418                 pr_err("Cannot select SW HFN override for other era than 2");
2419                 return -EINVAL;
2420         }
2421
2422         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2423                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2424                 return -EINVAL;
2425         }
2426
2427         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2428         if (swap)
2429                 PROGRAM_SET_BSWAP(p);
2430         if (ps)
2431                 PROGRAM_SET_36BIT_ADDR(p);
2432
2433         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2434
2435         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2436                         hfn,
2437                         sn_size,
2438                         bearer,
2439                         direction,
2440                         hfn_threshold,
2441                         cipherdata,
2442                         authdata);
2443
2444         SET_LABEL(p, pdb_end);
2445
2446         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2447                                era_2_sw_hfn_ovrd);
2448         if (err)
2449                 return err;
2450
2451         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2452                 swap,
2453                 cipherdata,
2454                 authdata,
2455                 OP_TYPE_ENCAP_PROTOCOL,
2456                 sn_size,
2457                 era_2_sw_hfn_ovrd);
2458         if (err)
2459                 return err;
2460
2461         PATCH_HDR(p, 0, pdb_end);
2462
2463         return PROGRAM_FINALIZE(p);
2464 }
2465
2466 /**
2467  * cnstr_shdsc_pdcp_c_plane_decap - Function for creating a PDCP Control Plane
2468  *                                  decapsulation descriptor.
2469  * @descbuf: pointer to buffer for descriptor construction
2470  * @ps: if 36/40bit addressing is desired, this parameter must be true
2471  * @swap: must be true when core endianness doesn't match SEC endianness
2472  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2473  *       PDCP frames.
2474  * @sn_size: size of sequence numbers, only 5/12 bit sequence numbers are valid
2475  * @bearer: radio bearer ID
2476  * @direction: the direction of the PDCP frame (UL/DL)
2477  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2478  *                 keys should be renegotiated at the earliest convenience.
2479  * @cipherdata: pointer to block cipher transform definitions
2480  *              Valid algorithm values are those from cipher_type_pdcp enum.
2481  * @authdata: pointer to authentication transform definitions
2482  *            Valid algorithm values are those from auth_type_pdcp enum.
2483  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2484  *                     this descriptor. Note: Can only be used for
2485  *                     SEC ERA 2.
2486  *
2487  * Return: size of descriptor written in words or negative number on error.
2488  *         Once the function returns, the value of this parameter can be used
2489  *         for reclaiming the space that wasn't used for the descriptor.
2490  *
2491  * Note: descbuf must be large enough to contain a full 256 byte long
2492  * descriptor; after the function returns, by subtracting the actual number of
2493  * bytes used, the user can reuse the remaining buffer space for other purposes.
2494  */
2495 static inline int
2496 cnstr_shdsc_pdcp_c_plane_decap(uint32_t *descbuf,
2497                                bool ps,
2498                                bool swap,
2499                                uint32_t hfn,
2500                                enum pdcp_sn_size sn_size,
2501                                unsigned char bearer,
2502                                unsigned char direction,
2503                                uint32_t hfn_threshold,
2504                                struct alginfo *cipherdata,
2505                                struct alginfo *authdata,
2506                                unsigned char era_2_sw_hfn_ovrd)
2507 {
2508         static int
2509                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2510                         (struct program*, bool swap, struct alginfo *,
2511                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2512                          unsigned char) = {
2513                 {       /* NULL */
2514                         pdcp_insert_cplane_null_op,     /* NULL */
2515                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2516                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2517                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2518                 },
2519                 {       /* SNOW f8 */
2520                         pdcp_insert_cplane_enc_only_op, /* NULL */
2521                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2522                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2523                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2524                 },
2525                 {       /* AES CTR */
2526                         pdcp_insert_cplane_enc_only_op, /* NULL */
2527                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2528                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2529                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2530                 },
2531                 {       /* ZUC-E */
2532                         pdcp_insert_cplane_enc_only_op, /* NULL */
2533                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2534                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2535                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2536                 },
2537         };
2538         static enum rta_share_type
2539                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2540                 {       /* NULL */
2541                         SHR_WAIT,       /* NULL */
2542                         SHR_ALWAYS,     /* SNOW f9 */
2543                         SHR_ALWAYS,     /* AES CMAC */
2544                         SHR_ALWAYS      /* ZUC-I */
2545                 },
2546                 {       /* SNOW f8 */
2547                         SHR_ALWAYS,     /* NULL */
2548                         SHR_ALWAYS,     /* SNOW f9 */
2549                         SHR_WAIT,       /* AES CMAC */
2550                         SHR_WAIT        /* ZUC-I */
2551                 },
2552                 {       /* AES CTR */
2553                         SHR_ALWAYS,     /* NULL */
2554                         SHR_ALWAYS,     /* SNOW f9 */
2555                         SHR_ALWAYS,     /* AES CMAC */
2556                         SHR_WAIT        /* ZUC-I */
2557                 },
2558                 {       /* ZUC-E */
2559                         SHR_ALWAYS,     /* NULL */
2560                         SHR_WAIT,       /* SNOW f9 */
2561                         SHR_WAIT,       /* AES CMAC */
2562                         SHR_ALWAYS      /* ZUC-I */
2563                 },
2564         };
2565         enum pdb_type_e pdb_type;
2566         struct program prg;
2567         struct program *p = &prg;
2568         int err;
2569         LABEL(pdb_end);
2570
2571         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2572                 pr_err("Cannot select SW HFN override for other era than 2");
2573                 return -EINVAL;
2574         }
2575
2576         if (sn_size != PDCP_SN_SIZE_12 && sn_size != PDCP_SN_SIZE_5) {
2577                 pr_err("C-plane supports only 5-bit and 12-bit sequence numbers\n");
2578                 return -EINVAL;
2579         }
2580
2581         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2582         if (swap)
2583                 PROGRAM_SET_BSWAP(p);
2584         if (ps)
2585                 PROGRAM_SET_36BIT_ADDR(p);
2586
2587         SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2588
2589         pdb_type = cnstr_pdcp_c_plane_pdb(p,
2590                         hfn,
2591                         sn_size,
2592                         bearer,
2593                         direction,
2594                         hfn_threshold,
2595                         cipherdata,
2596                         authdata);
2597
2598         SET_LABEL(p, pdb_end);
2599
2600         err = insert_hfn_ov_op(p, sn_size, pdb_type,
2601                                era_2_sw_hfn_ovrd);
2602         if (err)
2603                 return err;
2604
2605         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2606                 swap,
2607                 cipherdata,
2608                 authdata,
2609                 OP_TYPE_DECAP_PROTOCOL,
2610                 sn_size,
2611                 era_2_sw_hfn_ovrd);
2612         if (err)
2613                 return err;
2614
2615         PATCH_HDR(p, 0, pdb_end);
2616
2617         return PROGRAM_FINALIZE(p);
2618 }
2619
2620 static int
2621 pdcp_insert_uplane_with_int_op(struct program *p,
2622                               bool swap __maybe_unused,
2623                               struct alginfo *cipherdata,
2624                               struct alginfo *authdata,
2625                               enum pdcp_sn_size sn_size,
2626                               unsigned char era_2_sw_hfn_ovrd,
2627                               unsigned int dir)
2628 {
2629         static int
2630                 (*pdcp_cp_fp[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID])
2631                         (struct program*, bool swap, struct alginfo *,
2632                          struct alginfo *, unsigned int, enum pdcp_sn_size,
2633                         unsigned char __maybe_unused) = {
2634                 {       /* NULL */
2635                         pdcp_insert_cplane_null_op,     /* NULL */
2636                         pdcp_insert_cplane_int_only_op, /* SNOW f9 */
2637                         pdcp_insert_cplane_int_only_op, /* AES CMAC */
2638                         pdcp_insert_cplane_int_only_op  /* ZUC-I */
2639                 },
2640                 {       /* SNOW f8 */
2641                         pdcp_insert_cplane_enc_only_op, /* NULL */
2642                         pdcp_insert_cplane_acc_op,      /* SNOW f9 */
2643                         pdcp_insert_cplane_snow_aes_op, /* AES CMAC */
2644                         pdcp_insert_cplane_snow_zuc_op  /* ZUC-I */
2645                 },
2646                 {       /* AES CTR */
2647                         pdcp_insert_cplane_enc_only_op, /* NULL */
2648                         pdcp_insert_cplane_aes_snow_op, /* SNOW f9 */
2649                         pdcp_insert_cplane_acc_op,      /* AES CMAC */
2650                         pdcp_insert_cplane_aes_zuc_op   /* ZUC-I */
2651                 },
2652                 {       /* ZUC-E */
2653                         pdcp_insert_cplane_enc_only_op, /* NULL */
2654                         pdcp_insert_cplane_zuc_snow_op, /* SNOW f9 */
2655                         pdcp_insert_cplane_zuc_aes_op,  /* AES CMAC */
2656                         pdcp_insert_cplane_acc_op       /* ZUC-I */
2657                 },
2658         };
2659         int err;
2660
2661         err = pdcp_cp_fp[cipherdata->algtype][authdata->algtype](p,
2662                 swap,
2663                 cipherdata,
2664                 authdata,
2665                 dir,
2666                 sn_size,
2667                 era_2_sw_hfn_ovrd);
2668         if (err)
2669                 return err;
2670
2671         return 0;
2672 }
2673
2674
2675 /**
2676  * cnstr_shdsc_pdcp_u_plane_encap - Function for creating a PDCP User Plane
2677  *                                  encapsulation descriptor.
2678  * @descbuf: pointer to buffer for descriptor construction
2679  * @ps: if 36/40bit addressing is desired, this parameter must be true
2680  * @swap: must be true when core endianness doesn't match SEC endianness
2681  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2682  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2683  *       PDCP frames.
2684  * @bearer: radio bearer ID
2685  * @direction: the direction of the PDCP frame (UL/DL)
2686  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2687  *                 keys should be renegotiated at the earliest convenience.
2688  * @cipherdata: pointer to block cipher transform definitions
2689  *              Valid algorithm values are those from cipher_type_pdcp enum.
2690  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2691  *                     this descriptor. Note: Can only be used for
2692  *                     SEC ERA 2.
2693  *
2694  * Return: size of descriptor written in words or negative number on error.
2695  *         Once the function returns, the value of this parameter can be used
2696  *         for reclaiming the space that wasn't used for the descriptor.
2697  *
2698  * Note: descbuf must be large enough to contain a full 256 byte long
2699  * descriptor; after the function returns, by subtracting the actual number of
2700  * bytes used, the user can reuse the remaining buffer space for other purposes.
2701  */
2702 static inline int
2703 cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
2704                                bool ps,
2705                                bool swap,
2706                                enum pdcp_sn_size sn_size,
2707                                uint32_t hfn,
2708                                unsigned short bearer,
2709                                unsigned short direction,
2710                                uint32_t hfn_threshold,
2711                                struct alginfo *cipherdata,
2712                                struct alginfo *authdata,
2713                                unsigned char era_2_sw_hfn_ovrd)
2714 {
2715         struct program prg;
2716         struct program *p = &prg;
2717         int err;
2718         static enum rta_share_type
2719                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2720                 {       /* NULL */
2721                         SHR_WAIT,       /* NULL */
2722                         SHR_ALWAYS,     /* SNOW f9 */
2723                         SHR_ALWAYS,     /* AES CMAC */
2724                         SHR_ALWAYS      /* ZUC-I */
2725                 },
2726                 {       /* SNOW f8 */
2727                         SHR_ALWAYS,     /* NULL */
2728                         SHR_ALWAYS,     /* SNOW f9 */
2729                         SHR_WAIT,       /* AES CMAC */
2730                         SHR_WAIT        /* ZUC-I */
2731                 },
2732                 {       /* AES CTR */
2733                         SHR_ALWAYS,     /* NULL */
2734                         SHR_ALWAYS,     /* SNOW f9 */
2735                         SHR_ALWAYS,     /* AES CMAC */
2736                         SHR_WAIT        /* ZUC-I */
2737                 },
2738                 {       /* ZUC-E */
2739                         SHR_ALWAYS,     /* NULL */
2740                         SHR_WAIT,       /* SNOW f9 */
2741                         SHR_WAIT,       /* AES CMAC */
2742                         SHR_ALWAYS      /* ZUC-I */
2743                 },
2744         };
2745         LABEL(pdb_end);
2746
2747         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2748                 pr_err("Cannot select SW HFN ovrd for other era than 2");
2749                 return -EINVAL;
2750         }
2751
2752         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2753                 pr_err("Cannot use u-plane auth with era < 8");
2754                 return -EINVAL;
2755         }
2756
2757         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2758         if (swap)
2759                 PROGRAM_SET_BSWAP(p);
2760         if (ps)
2761                 PROGRAM_SET_36BIT_ADDR(p);
2762
2763         if (authdata)
2764                 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2765         else
2766                 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2767         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2768                                    hfn_threshold)) {
2769                 pr_err("Error creating PDCP UPlane PDB\n");
2770                 return -EINVAL;
2771         }
2772         SET_LABEL(p, pdb_end);
2773
2774         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2775                                era_2_sw_hfn_ovrd);
2776         if (err)
2777                 return err;
2778
2779         switch (sn_size) {
2780         case PDCP_SN_SIZE_7:
2781         case PDCP_SN_SIZE_12:
2782                 switch (cipherdata->algtype) {
2783                 case PDCP_CIPHER_TYPE_ZUC:
2784                         if (rta_sec_era < RTA_SEC_ERA_5) {
2785                                 pr_err("Invalid era for selected algorithm\n");
2786                                 return -ENOTSUP;
2787                         }
2788                         /* fallthrough */
2789                 case PDCP_CIPHER_TYPE_AES:
2790                 case PDCP_CIPHER_TYPE_SNOW:
2791                 case PDCP_CIPHER_TYPE_NULL:
2792                         /* Insert auth key if requested */
2793                         if (authdata && authdata->algtype) {
2794                                 KEY(p, KEY2, authdata->key_enc_flags,
2795                                     (uint64_t)authdata->key, authdata->keylen,
2796                                     INLINE_KEY(authdata));
2797                         }
2798                         /* Insert Cipher Key */
2799                         KEY(p, KEY1, cipherdata->key_enc_flags,
2800                             (uint64_t)cipherdata->key, cipherdata->keylen,
2801                             INLINE_KEY(cipherdata));
2802
2803                         if (authdata)
2804                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2805                                          OP_PCLID_LTE_PDCP_USER_RN,
2806                                          ((uint16_t)cipherdata->algtype << 8) |
2807                                          (uint16_t)authdata->algtype);
2808                         else
2809                                 PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
2810                                          OP_PCLID_LTE_PDCP_USER,
2811                                          (uint16_t)cipherdata->algtype);
2812                         break;
2813                 default:
2814                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
2815                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
2816                                cipherdata->algtype);
2817                         return -EINVAL;
2818                 }
2819                 break;
2820
2821         case PDCP_SN_SIZE_15:
2822         case PDCP_SN_SIZE_18:
2823                 if (authdata) {
2824                         err = pdcp_insert_uplane_with_int_op(p, swap,
2825                                         cipherdata, authdata,
2826                                         sn_size, era_2_sw_hfn_ovrd,
2827                                         OP_TYPE_ENCAP_PROTOCOL);
2828                         if (err)
2829                                 return err;
2830
2831                         break;
2832                 }
2833
2834                 switch (cipherdata->algtype) {
2835                 case PDCP_CIPHER_TYPE_NULL:
2836                         insert_copy_frame_op(p,
2837                                              cipherdata,
2838                                              OP_TYPE_ENCAP_PROTOCOL);
2839                         break;
2840
2841                 default:
2842                         err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
2843                                         OP_TYPE_ENCAP_PROTOCOL, sn_size);
2844                         if (err)
2845                                 return err;
2846                         break;
2847                 }
2848                 break;
2849
2850         case PDCP_SN_SIZE_5:
2851         default:
2852                 pr_err("Invalid SN size selected\n");
2853                 return -ENOTSUP;
2854         }
2855
2856         PATCH_HDR(p, 0, pdb_end);
2857         return PROGRAM_FINALIZE(p);
2858 }
2859
2860 /**
2861  * cnstr_shdsc_pdcp_u_plane_decap - Function for creating a PDCP User Plane
2862  *                                  decapsulation descriptor.
2863  * @descbuf: pointer to buffer for descriptor construction
2864  * @ps: if 36/40bit addressing is desired, this parameter must be true
2865  * @swap: must be true when core endianness doesn't match SEC endianness
2866  * @sn_size: selects Sequence Number Size: 7/12/15 bits
2867  * @hfn: starting Hyper Frame Number to be used together with the SN from the
2868  *       PDCP frames.
2869  * @bearer: radio bearer ID
2870  * @direction: the direction of the PDCP frame (UL/DL)
2871  * @hfn_threshold: HFN value that once reached triggers a warning from SEC that
2872  *                 keys should be renegotiated at the earliest convenience.
2873  * @cipherdata: pointer to block cipher transform definitions
2874  *              Valid algorithm values are those from cipher_type_pdcp enum.
2875  * @era_2_sw_hfn_ovrd: if software HFN override mechanism is desired for
2876  *                     this descriptor. Note: Can only be used for
2877  *                     SEC ERA 2.
2878  *
2879  * Return: size of descriptor written in words or negative number on error.
2880  *         Once the function returns, the value of this parameter can be used
2881  *         for reclaiming the space that wasn't used for the descriptor.
2882  *
2883  * Note: descbuf must be large enough to contain a full 256 byte long
2884  * descriptor; after the function returns, by subtracting the actual number of
2885  * bytes used, the user can reuse the remaining buffer space for other purposes.
2886  */
2887 static inline int
2888 cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
2889                                bool ps,
2890                                bool swap,
2891                                enum pdcp_sn_size sn_size,
2892                                uint32_t hfn,
2893                                unsigned short bearer,
2894                                unsigned short direction,
2895                                uint32_t hfn_threshold,
2896                                struct alginfo *cipherdata,
2897                                struct alginfo *authdata,
2898                                unsigned char era_2_sw_hfn_ovrd)
2899 {
2900         struct program prg;
2901         struct program *p = &prg;
2902         int err;
2903         static enum rta_share_type
2904                 desc_share[PDCP_CIPHER_TYPE_INVALID][PDCP_AUTH_TYPE_INVALID] = {
2905                 {       /* NULL */
2906                         SHR_WAIT,       /* NULL */
2907                         SHR_ALWAYS,     /* SNOW f9 */
2908                         SHR_ALWAYS,     /* AES CMAC */
2909                         SHR_ALWAYS      /* ZUC-I */
2910                 },
2911                 {       /* SNOW f8 */
2912                         SHR_ALWAYS,     /* NULL */
2913                         SHR_ALWAYS,     /* SNOW f9 */
2914                         SHR_WAIT,       /* AES CMAC */
2915                         SHR_WAIT        /* ZUC-I */
2916                 },
2917                 {       /* AES CTR */
2918                         SHR_ALWAYS,     /* NULL */
2919                         SHR_ALWAYS,     /* SNOW f9 */
2920                         SHR_ALWAYS,     /* AES CMAC */
2921                         SHR_WAIT        /* ZUC-I */
2922                 },
2923                 {       /* ZUC-E */
2924                         SHR_ALWAYS,     /* NULL */
2925                         SHR_WAIT,       /* SNOW f9 */
2926                         SHR_WAIT,       /* AES CMAC */
2927                         SHR_ALWAYS      /* ZUC-I */
2928                 },
2929         };
2930
2931         LABEL(pdb_end);
2932
2933         if (rta_sec_era != RTA_SEC_ERA_2 && era_2_sw_hfn_ovrd) {
2934                 pr_err("Cannot select SW HFN override for other era than 2");
2935                 return -EINVAL;
2936         }
2937
2938         if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
2939                 pr_err("Cannot use u-plane auth with era < 8");
2940                 return -EINVAL;
2941         }
2942
2943         PROGRAM_CNTXT_INIT(p, descbuf, 0);
2944         if (swap)
2945                 PROGRAM_SET_BSWAP(p);
2946         if (ps)
2947                 PROGRAM_SET_36BIT_ADDR(p);
2948         if (authdata)
2949                 SHR_HDR(p, desc_share[cipherdata->algtype][authdata->algtype], 0, 0);
2950         else
2951                 SHR_HDR(p, SHR_ALWAYS, 0, 0);
2952
2953         if (cnstr_pdcp_u_plane_pdb(p, sn_size, hfn, bearer, direction,
2954                                    hfn_threshold)) {
2955                 pr_err("Error creating PDCP UPlane PDB\n");
2956                 return -EINVAL;
2957         }
2958         SET_LABEL(p, pdb_end);
2959
2960         err = insert_hfn_ov_op(p, sn_size, PDCP_PDB_TYPE_FULL_PDB,
2961                                era_2_sw_hfn_ovrd);
2962         if (err)
2963                 return err;
2964
2965         switch (sn_size) {
2966         case PDCP_SN_SIZE_7:
2967         case PDCP_SN_SIZE_12:
2968                 switch (cipherdata->algtype) {
2969                 case PDCP_CIPHER_TYPE_ZUC:
2970                         if (rta_sec_era < RTA_SEC_ERA_5) {
2971                                 pr_err("Invalid era for selected algorithm\n");
2972                                 return -ENOTSUP;
2973                         }
2974                         /* fallthrough */
2975                 case PDCP_CIPHER_TYPE_AES:
2976                 case PDCP_CIPHER_TYPE_SNOW:
2977                 case PDCP_CIPHER_TYPE_NULL:
2978                         /* Insert auth key if requested */
2979                         if (authdata && authdata->algtype)
2980                                 KEY(p, KEY2, authdata->key_enc_flags,
2981                                     (uint64_t)authdata->key, authdata->keylen,
2982                                     INLINE_KEY(authdata));
2983
2984                         /* Insert Cipher Key */
2985                         KEY(p, KEY1, cipherdata->key_enc_flags,
2986                             cipherdata->key, cipherdata->keylen,
2987                             INLINE_KEY(cipherdata));
2988                         if (authdata)
2989                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2990                                          OP_PCLID_LTE_PDCP_USER_RN,
2991                                          ((uint16_t)cipherdata->algtype << 8) |
2992                                          (uint16_t)authdata->algtype);
2993                         else
2994                                 PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
2995                                          OP_PCLID_LTE_PDCP_USER,
2996                                          (uint16_t)cipherdata->algtype);
2997                         break;
2998                 default:
2999                         pr_err("%s: Invalid encrypt algorithm selected: %d\n",
3000                                "cnstr_pcl_shdsc_pdcp_u_plane_decap",
3001                                cipherdata->algtype);
3002                         return -EINVAL;
3003                 }
3004                 break;
3005
3006         case PDCP_SN_SIZE_15:
3007         case PDCP_SN_SIZE_18:
3008                 if (authdata) {
3009                         err = pdcp_insert_uplane_with_int_op(p, swap,
3010                                         cipherdata, authdata,
3011                                         sn_size, era_2_sw_hfn_ovrd,
3012                                         OP_TYPE_DECAP_PROTOCOL);
3013                         if (err)
3014                                 return err;
3015
3016                         break;
3017                 }
3018
3019                 switch (cipherdata->algtype) {
3020                 case PDCP_CIPHER_TYPE_NULL:
3021                         insert_copy_frame_op(p,
3022                                              cipherdata,
3023                                              OP_TYPE_DECAP_PROTOCOL);
3024                         break;
3025
3026                 default:
3027                         err = pdcp_insert_uplane_no_int_op(p, swap, cipherdata,
3028                                 OP_TYPE_DECAP_PROTOCOL, sn_size);
3029                         if (err)
3030                                 return err;
3031                         break;
3032                 }
3033                 break;
3034
3035         case PDCP_SN_SIZE_5:
3036         default:
3037                 pr_err("Invalid SN size selected\n");
3038                 return -ENOTSUP;
3039         }
3040
3041         PATCH_HDR(p, 0, pdb_end);
3042         return PROGRAM_FINALIZE(p);
3043 }
3044
3045 /**
3046  * cnstr_shdsc_pdcp_short_mac - Function for creating a PDCP Short MAC
3047  *                              descriptor.
3048  * @descbuf: pointer to buffer for descriptor construction
3049  * @ps: if 36/40bit addressing is desired, this parameter must be true
3050  * @swap: must be true when core endianness doesn't match SEC endianness
3051  * @authdata: pointer to authentication transform definitions
3052  *            Valid algorithm values are those from auth_type_pdcp enum.
3053  *
3054  * Return: size of descriptor written in words or negative number on error.
3055  *         Once the function returns, the value of this parameter can be used
3056  *         for reclaiming the space that wasn't used for the descriptor.
3057  *
3058  * Note: descbuf must be large enough to contain a full 256 byte long
3059  * descriptor; after the function returns, by subtracting the actual number of
3060  * bytes used, the user can reuse the remaining buffer space for other purposes.
3061  */
3062 static inline int
3063 cnstr_shdsc_pdcp_short_mac(uint32_t *descbuf,
3064                            bool ps,
3065                            bool swap,
3066                            struct alginfo *authdata)
3067 {
3068         struct program prg;
3069         struct program *p = &prg;
3070         uint32_t iv[3] = {0, 0, 0};
3071         LABEL(local_offset);
3072         REFERENCE(move_cmd_read_descbuf);
3073         REFERENCE(move_cmd_write_descbuf);
3074
3075         PROGRAM_CNTXT_INIT(p, descbuf, 0);
3076         if (swap)
3077                 PROGRAM_SET_BSWAP(p);
3078         if (ps)
3079                 PROGRAM_SET_36BIT_ADDR(p);
3080
3081         SHR_HDR(p, SHR_ALWAYS, 1, 0);
3082
3083         if (rta_sec_era > RTA_SEC_ERA_2) {
3084                 MATHB(p, SEQINSZ, SUB, ZERO, VSEQINSZ, 4, 0);
3085                 MATHB(p, SEQINSZ, SUB, ZERO, MATH1, 4, 0);
3086         } else {
3087                 MATHB(p, SEQINSZ, ADD, ONE, MATH1, 4, 0);
3088                 MATHB(p, MATH1, SUB, ONE, MATH1, 4, 0);
3089                 MATHB(p, ZERO, ADD, MATH1, VSEQINSZ, 4, 0);
3090                 MOVE(p, MATH1, 0, MATH0, 0, 8, IMMED);
3091
3092                 /*
3093                  * Since MOVELEN is available only starting with
3094                  * SEC ERA 3, use poor man's MOVELEN: create a MOVE
3095                  * command dynamically by writing the length from M1 by
3096                  * OR-ing the command in the M1 register and MOVE the
3097                  * result into the descriptor buffer. Care must be taken
3098                  * wrt. the location of the command because of SEC
3099                  * pipelining. The actual MOVEs are written at the end
3100                  * of the descriptor due to calculations needed on the
3101                  * offset in the descriptor for the MOVE command.
3102                  */
3103                 move_cmd_read_descbuf = MOVE(p, DESCBUF, 0, MATH0, 0, 6,
3104                                              IMMED);
3105                 move_cmd_write_descbuf = MOVE(p, MATH0, 0, DESCBUF, 0, 8,
3106                                               WAITCOMP | IMMED);
3107         }
3108         MATHB(p, ZERO, ADD, MATH1, VSEQOUTSZ, 4, 0);
3109
3110         switch (authdata->algtype) {
3111         case PDCP_AUTH_TYPE_NULL:
3112                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3113                 if (rta_sec_era > RTA_SEC_ERA_2) {
3114                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3115                 } else {
3116                         SET_LABEL(p, local_offset);
3117
3118                         /* Shut off automatic Info FIFO entries */
3119                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3120
3121                         /* Placeholder for MOVE command with length from M1
3122                          * register
3123                          */
3124                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3125
3126                         /* Enable automatic Info FIFO entries */
3127                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3128                 }
3129
3130                 LOAD(p, (uintptr_t)iv, MATH0, 0, 8, IMMED | COPY);
3131                 SEQFIFOLOAD(p, MSG1, 0, VLF | LAST1 | LAST2 | FLUSH1);
3132                 SEQSTORE(p, MATH0, 0, 4, 0);
3133
3134                 break;
3135
3136         case PDCP_AUTH_TYPE_SNOW:
3137                 iv[0] = 0xFFFFFFFF;
3138                 iv[1] = swap ? swab32(0x04000000) : 0x04000000;
3139                 iv[2] = swap ? swab32(0xF8000000) : 0xF8000000;
3140
3141                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3142                     authdata->keylen, INLINE_KEY(authdata));
3143                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3144                 ALG_OPERATION(p, OP_ALG_ALGSEL_SNOW_F9,
3145                               OP_ALG_AAI_F9,
3146                               OP_ALG_AS_INITFINAL,
3147                               ICV_CHECK_DISABLE,
3148                               DIR_ENC);
3149                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3150
3151                 if (rta_sec_era > RTA_SEC_ERA_2) {
3152                         MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3153                 } else {
3154                         SET_LABEL(p, local_offset);
3155
3156
3157                         /* Shut off automatic Info FIFO entries */
3158                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3159
3160                         /* Placeholder for MOVE command with length from M1
3161                          * register
3162                          */
3163                         MOVE(p, IFIFOAB1, 0, OFIFO, 0, 0, IMMED);
3164
3165                         /* Enable automatic Info FIFO entries */
3166                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3167                 }
3168                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3169                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3170
3171                 break;
3172
3173         case PDCP_AUTH_TYPE_AES:
3174                 iv[0] = 0xFFFFFFFF;
3175                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3176                 iv[2] = 0x00000000; /* unused */
3177
3178                 KEY(p, KEY1, authdata->key_enc_flags, authdata->key,
3179                     authdata->keylen, INLINE_KEY(authdata));
3180                 LOAD(p, (uintptr_t)&iv, MATH0, 0, 8, IMMED | COPY);
3181                 MOVE(p, MATH0, 0, IFIFOAB1, 0, 8, IMMED);
3182                 ALG_OPERATION(p, OP_ALG_ALGSEL_AES,
3183                               OP_ALG_AAI_CMAC,
3184                               OP_ALG_AS_INITFINAL,
3185                               ICV_CHECK_DISABLE,
3186                               DIR_ENC);
3187                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3188
3189                 if (rta_sec_era > RTA_SEC_ERA_2) {
3190                         MOVE(p, AB2, 0, OFIFO, 0, MATH1, 0);
3191                 } else {
3192                         SET_LABEL(p, local_offset);
3193
3194                         /* Shut off automatic Info FIFO entries */
3195                         LOAD(p, 0, DCTRL, LDOFF_DISABLE_AUTO_NFIFO, 0, IMMED);
3196
3197                         /* Placeholder for MOVE command with length from M1
3198                          * register
3199                          */
3200                         MOVE(p, IFIFOAB2, 0, OFIFO, 0, 0, IMMED);
3201
3202                         /* Enable automatic Info FIFO entries */
3203                         LOAD(p, 0, DCTRL, LDOFF_ENABLE_AUTO_NFIFO, 0, IMMED);
3204                 }
3205                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3206                 SEQSTORE(p, CONTEXT1, 0, 4, 0);
3207
3208                 break;
3209
3210         case PDCP_AUTH_TYPE_ZUC:
3211                 if (rta_sec_era < RTA_SEC_ERA_5) {
3212                         pr_err("Invalid era for selected algorithm\n");
3213                         return -ENOTSUP;
3214                 }
3215                 iv[0] = 0xFFFFFFFF;
3216                 iv[1] = swap ? swab32(0xFC000000) : 0xFC000000;
3217                 iv[2] = 0x00000000; /* unused */
3218
3219                 KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
3220                     authdata->keylen, INLINE_KEY(authdata));
3221                 LOAD(p, (uintptr_t)&iv, CONTEXT2, 0, 12, IMMED | COPY);
3222                 ALG_OPERATION(p, OP_ALG_ALGSEL_ZUCA,
3223                               OP_ALG_AAI_F9,
3224                               OP_ALG_AS_INITFINAL,
3225                               ICV_CHECK_DISABLE,
3226                               DIR_ENC);
3227                 SEQFIFOSTORE(p, MSG, 0, 0, VLF);
3228                 MOVE(p, AB1, 0, OFIFO, 0, MATH1, 0);
3229                 SEQFIFOLOAD(p, MSGINSNOOP, 0, VLF | LAST1 | LAST2 | FLUSH1);
3230                 SEQSTORE(p, CONTEXT2, 0, 4, 0);
3231
3232                 break;
3233
3234         default:
3235                 pr_err("%s: Invalid integrity algorithm selected: %d\n",
3236                        "cnstr_shdsc_pdcp_short_mac", authdata->algtype);
3237                 return -EINVAL;
3238         }
3239
3240
3241         if (rta_sec_era < RTA_SEC_ERA_3) {
3242                 PATCH_MOVE(p, move_cmd_read_descbuf, local_offset);
3243                 PATCH_MOVE(p, move_cmd_write_descbuf, local_offset);
3244         }
3245
3246         return PROGRAM_FINALIZE(p);
3247 }
3248
3249 #endif /* __DESC_PDCP_H__ */