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