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