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