Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2023 Marvell.
3 : : */
4 : :
5 : : #include <rte_crypto.h>
6 : : #include <rte_crypto_sym.h>
7 : : #include <rte_cryptodev.h>
8 : : #include <rte_memcpy.h>
9 : : #include <rte_mbuf_dyn.h>
10 : : #include <rte_pdcp.h>
11 : : #include <rte_pdcp_hdr.h>
12 : :
13 : : #include "pdcp_cnt.h"
14 : : #include "pdcp_crypto.h"
15 : : #include "pdcp_entity.h"
16 : : #include "pdcp_process.h"
17 : :
18 : : /* Enum of supported algorithms for ciphering */
19 : : enum pdcp_cipher_algo {
20 : : PDCP_CIPHER_ALGO_NULL,
21 : : PDCP_CIPHER_ALGO_AES,
22 : : PDCP_CIPHER_ALGO_ZUC,
23 : : PDCP_CIPHER_ALGO_SNOW3G,
24 : : PDCP_CIPHER_ALGO_MAX
25 : : };
26 : :
27 : : /* Enum of supported algorithms for integrity */
28 : : enum pdcp_auth_algo {
29 : : PDCP_AUTH_ALGO_NULL,
30 : : PDCP_AUTH_ALGO_AES,
31 : : PDCP_AUTH_ALGO_ZUC,
32 : : PDCP_AUTH_ALGO_SNOW3G,
33 : : PDCP_AUTH_ALGO_MAX
34 : : };
35 : :
36 : : /* IV generation functions based on type of operation (cipher - auth) */
37 : :
38 : : static void
39 : 0 : pdcp_iv_gen_null_null(struct rte_crypto_op *cop, const struct entity_priv *en_priv, uint32_t count)
40 : : {
41 : : /* No IV required for NULL cipher + NULL auth */
42 : : RTE_SET_USED(cop);
43 : : RTE_SET_USED(en_priv);
44 : : RTE_SET_USED(count);
45 : 0 : }
46 : :
47 : : static void
48 : 0 : pdcp_iv_gen_null_aes_cmac(struct rte_crypto_op *cop, const struct entity_priv *en_priv,
49 : : uint32_t count)
50 : : {
51 : : struct rte_crypto_sym_op *op = cop->sym;
52 [ # # ]: 0 : struct rte_mbuf *mb = op->m_src;
53 : : uint8_t *m_ptr;
54 : : uint64_t m;
55 : :
56 : : /* AES-CMAC requires message to be prepended with info on count etc */
57 : :
58 : : /* Prepend by 8 bytes to add custom message */
59 : : m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
60 : :
61 [ # # # # ]: 0 : m = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
62 : :
63 : : rte_memcpy(m_ptr, &m, 8);
64 : 0 : }
65 : :
66 : : static void
67 : 0 : pdcp_iv_gen_null_zs(struct rte_crypto_op *cop, const struct entity_priv *en_priv, uint32_t count)
68 : : {
69 : : uint64_t iv_u64[2];
70 : : uint8_t *iv;
71 : :
72 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
73 : :
74 [ # # # # ]: 0 : iv_u64[0] = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
75 : : rte_memcpy(iv, &iv_u64[0], 8);
76 : :
77 : 0 : iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
78 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64[1], 8);
79 : 0 : }
80 : :
81 : : static void
82 : 0 : pdcp_iv_gen_aes_ctr_null(struct rte_crypto_op *cop, const struct entity_priv *en_priv,
83 : : uint32_t count)
84 : : {
85 : : uint64_t iv_u64[2];
86 : : uint8_t *iv;
87 : :
88 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
89 : :
90 [ # # ]: 0 : iv_u64[0] = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
91 [ # # ]: 0 : iv_u64[1] = 0;
92 : : rte_memcpy(iv, iv_u64, 16);
93 : 0 : }
94 : :
95 : : static void
96 : 0 : pdcp_iv_gen_zs_null(struct rte_crypto_op *cop, const struct entity_priv *en_priv, uint32_t count)
97 : : {
98 : : uint64_t iv_u64;
99 : : uint8_t *iv;
100 : :
101 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
102 : :
103 [ # # # # ]: 0 : iv_u64 = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
104 : : rte_memcpy(iv, &iv_u64, 8);
105 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64, 8);
106 : 0 : }
107 : :
108 : : static void
109 : 0 : pdcp_iv_gen_zs_zs(struct rte_crypto_op *cop, const struct entity_priv *en_priv, uint32_t count)
110 : : {
111 : : uint64_t iv_u64[2];
112 : : uint8_t *iv;
113 : :
114 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
115 : :
116 : : /* Generating cipher IV */
117 [ # # # # ]: 0 : iv_u64[0] = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
118 : : rte_memcpy(iv, &iv_u64[0], 8);
119 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64[0], 8);
120 : :
121 : 0 : iv += PDCP_IV_LEN;
122 : :
123 : : /* Generating auth IV */
124 [ # # # # ]: 0 : iv_u64[0] = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
125 : : rte_memcpy(iv, &iv_u64[0], 8);
126 : :
127 : 0 : iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
128 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64[1], 8);
129 : 0 : }
130 : :
131 : : static void
132 : 0 : pdcp_iv_gen_zs_aes_cmac(struct rte_crypto_op *cop, const struct entity_priv *en_priv,
133 : : uint32_t count)
134 : : {
135 : : struct rte_crypto_sym_op *op = cop->sym;
136 : 0 : struct rte_mbuf *mb = op->m_src;
137 : : uint8_t *m_ptr, *iv;
138 : : uint64_t iv_u64[2];
139 : : uint64_t m;
140 : :
141 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
142 [ # # # # ]: 0 : iv_u64[0] = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
143 : : rte_memcpy(iv, &iv_u64[0], 8);
144 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64[0], 8);
145 : :
146 : : m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
147 [ # # # # ]: 0 : m = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
148 : : rte_memcpy(m_ptr, &m, 8);
149 : 0 : }
150 : :
151 : : static void
152 : 0 : pdcp_iv_gen_aes_ctr_aes_cmac(struct rte_crypto_op *cop, const struct entity_priv *en_priv,
153 : : uint32_t count)
154 : : {
155 : : struct rte_crypto_sym_op *op = cop->sym;
156 : 0 : struct rte_mbuf *mb = op->m_src;
157 : : uint8_t *m_ptr, *iv;
158 : : uint64_t iv_u64[2];
159 : : uint64_t m;
160 : :
161 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
162 : :
163 [ # # ]: 0 : iv_u64[0] = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
164 [ # # ]: 0 : iv_u64[1] = 0;
165 : : rte_memcpy(iv, iv_u64, PDCP_IV_LEN);
166 : :
167 : : m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
168 [ # # # # ]: 0 : m = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
169 : : rte_memcpy(m_ptr, &m, 8);
170 : 0 : }
171 : :
172 : : static void
173 : 0 : pdcp_iv_gen_aes_ctr_zs(struct rte_crypto_op *cop, const struct entity_priv *en_priv, uint32_t count)
174 : : {
175 : : uint64_t iv_u64[2];
176 : : uint8_t *iv;
177 : :
178 : 0 : iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
179 : :
180 [ # # ]: 0 : iv_u64[0] = en_priv->cipher_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
181 [ # # ]: 0 : iv_u64[1] = 0;
182 : : rte_memcpy(iv, iv_u64, PDCP_IV_LEN);
183 : :
184 : 0 : iv += PDCP_IV_LEN;
185 : :
186 [ # # # # ]: 0 : iv_u64[0] = en_priv->auth_iv_part.u64[0] | ((uint64_t)(rte_cpu_to_be_32(count)));
187 : : rte_memcpy(iv, &iv_u64[0], 8);
188 : :
189 : 0 : iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
190 [ # # ]: 0 : rte_memcpy(iv + 8, &iv_u64[1], 8);
191 : 0 : }
192 : :
193 : : static int
194 : : pdcp_crypto_xfrm_get(const struct rte_pdcp_entity_conf *conf, struct rte_crypto_sym_xform **c_xfrm,
195 : : struct rte_crypto_sym_xform **a_xfrm)
196 : : {
197 : : *c_xfrm = NULL;
198 : : *a_xfrm = NULL;
199 : :
200 [ # # ]: 0 : if (conf->crypto_xfrm == NULL)
201 : : return -EINVAL;
202 : :
203 [ # # # # ]: 0 : if (conf->crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
204 : : *c_xfrm = conf->crypto_xfrm;
205 : 0 : *a_xfrm = conf->crypto_xfrm->next;
206 [ # # # # ]: 0 : } else if (conf->crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
207 : : *a_xfrm = conf->crypto_xfrm;
208 : 0 : *c_xfrm = conf->crypto_xfrm->next;
209 : : } else {
210 : : return -EINVAL;
211 : : }
212 : :
213 : : return 0;
214 : : }
215 : :
216 : : static int
217 [ # # ]: 0 : pdcp_iv_gen_func_set(struct rte_pdcp_entity *entity, const struct rte_pdcp_entity_conf *conf)
218 : : {
219 : : struct rte_crypto_sym_xform *c_xfrm, *a_xfrm;
220 : : enum rte_security_pdcp_direction direction;
221 : : enum pdcp_cipher_algo cipher_algo;
222 : : enum pdcp_auth_algo auth_algo;
223 : : struct entity_priv *en_priv;
224 : : int ret;
225 : :
226 : : en_priv = entity_priv_get(entity);
227 : :
228 : 0 : direction = conf->pdcp_xfrm.pkt_dir;
229 [ # # ]: 0 : if (conf->reverse_iv_direction)
230 : 0 : direction = !direction;
231 : :
232 : : ret = pdcp_crypto_xfrm_get(conf, &c_xfrm, &a_xfrm);
233 [ # # ]: 0 : if (ret)
234 : : return ret;
235 : :
236 [ # # ]: 0 : if (c_xfrm == NULL)
237 : : return -EINVAL;
238 : :
239 [ # # # # : 0 : memset(&en_priv->auth_iv_part, 0, sizeof(en_priv->auth_iv_part));
# ]
240 : 0 : memset(&en_priv->cipher_iv_part, 0, sizeof(en_priv->cipher_iv_part));
241 : :
242 [ # # # # : 0 : switch (c_xfrm->cipher.algo) {
# ]
243 : : case RTE_CRYPTO_CIPHER_NULL:
244 : : cipher_algo = PDCP_CIPHER_ALGO_NULL;
245 : : break;
246 : 0 : case RTE_CRYPTO_CIPHER_AES_CTR:
247 : : cipher_algo = PDCP_CIPHER_ALGO_AES;
248 : 0 : en_priv->cipher_iv_part.aes_ctr.bearer = conf->pdcp_xfrm.bearer;
249 : 0 : en_priv->cipher_iv_part.aes_ctr.direction = direction;
250 : 0 : break;
251 : 0 : case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
252 : : cipher_algo = PDCP_CIPHER_ALGO_SNOW3G;
253 : 0 : en_priv->cipher_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
254 : 0 : en_priv->cipher_iv_part.zs.direction = direction;
255 : 0 : break;
256 : 0 : case RTE_CRYPTO_CIPHER_ZUC_EEA3:
257 : : cipher_algo = PDCP_CIPHER_ALGO_ZUC;
258 : 0 : en_priv->cipher_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
259 : 0 : en_priv->cipher_iv_part.zs.direction = direction;
260 : 0 : break;
261 : : default:
262 : : return -ENOTSUP;
263 : : }
264 : :
265 [ # # ]: 0 : if (a_xfrm != NULL) {
266 [ # # # # : 0 : switch (a_xfrm->auth.algo) {
# ]
267 : : case RTE_CRYPTO_AUTH_NULL:
268 : : auth_algo = PDCP_AUTH_ALGO_NULL;
269 : : break;
270 : 0 : case RTE_CRYPTO_AUTH_AES_CMAC:
271 : : auth_algo = PDCP_AUTH_ALGO_AES;
272 : 0 : en_priv->auth_iv_part.aes_cmac.bearer = conf->pdcp_xfrm.bearer;
273 : 0 : en_priv->auth_iv_part.aes_cmac.direction = direction;
274 : 0 : break;
275 : 0 : case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
276 : : auth_algo = PDCP_AUTH_ALGO_SNOW3G;
277 : 0 : en_priv->auth_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
278 : 0 : en_priv->auth_iv_part.zs.direction_64 = direction;
279 : 0 : en_priv->auth_iv_part.zs.direction_112 = direction;
280 : 0 : break;
281 : 0 : case RTE_CRYPTO_AUTH_ZUC_EIA3:
282 : : auth_algo = PDCP_AUTH_ALGO_ZUC;
283 : 0 : en_priv->auth_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
284 : 0 : en_priv->auth_iv_part.zs.direction_64 = direction;
285 : 0 : en_priv->auth_iv_part.zs.direction_112 = direction;
286 : 0 : break;
287 : : default:
288 : : return -ENOTSUP;
289 : : }
290 : : } else {
291 : : auth_algo = PDCP_AUTH_ALGO_NULL;
292 : : }
293 : :
294 : : static const iv_gen_t iv_gen_map[PDCP_CIPHER_ALGO_MAX][PDCP_AUTH_ALGO_MAX] = {
295 : : [PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_NULL] = pdcp_iv_gen_null_null,
296 : : [PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_AES] = pdcp_iv_gen_null_aes_cmac,
297 : : [PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_SNOW3G] = pdcp_iv_gen_null_zs,
298 : : [PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_ZUC] = pdcp_iv_gen_null_zs,
299 : :
300 : : [PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_NULL] = pdcp_iv_gen_aes_ctr_null,
301 : : [PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_AES] = pdcp_iv_gen_aes_ctr_aes_cmac,
302 : : [PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_SNOW3G] = pdcp_iv_gen_aes_ctr_zs,
303 : : [PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_ZUC] = pdcp_iv_gen_aes_ctr_zs,
304 : :
305 : : [PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_NULL] = pdcp_iv_gen_zs_null,
306 : : [PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_AES] = pdcp_iv_gen_zs_aes_cmac,
307 : : [PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_SNOW3G] = pdcp_iv_gen_zs_zs,
308 : : [PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_ZUC] = pdcp_iv_gen_zs_zs,
309 : :
310 : : [PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_NULL] = pdcp_iv_gen_zs_null,
311 : : [PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_AES] = pdcp_iv_gen_zs_aes_cmac,
312 : : [PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_SNOW3G] = pdcp_iv_gen_zs_zs,
313 : : [PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_ZUC] = pdcp_iv_gen_zs_zs,
314 : : };
315 : :
316 : 0 : en_priv->iv_gen = iv_gen_map[cipher_algo][auth_algo];
317 : :
318 : 0 : return 0;
319 : : }
320 : :
321 : : static inline void
322 : 0 : cop_prepare(const struct entity_priv *en_priv, struct rte_mbuf *mb, struct rte_crypto_op *cop,
323 : : uint8_t data_offset, uint32_t count, const bool is_auth)
324 : : {
325 : : const struct rte_crypto_op cop_init = {
326 : : .type = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
327 : : .status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
328 : : .sess_type = RTE_CRYPTO_OP_WITH_SESSION,
329 : : };
330 : : struct rte_crypto_sym_op *op;
331 : : uint32_t pkt_len;
332 : :
333 : 0 : const uint8_t cipher_shift = 3 * en_priv->flags.is_cipher_in_bits;
334 : 0 : const uint8_t auth_shift = 3 * en_priv->flags.is_auth_in_bits;
335 : :
336 : : op = cop->sym;
337 : 0 : cop->raw = cop_init.raw;
338 : 0 : op->m_src = mb;
339 : 0 : op->m_dst = mb;
340 : :
341 : : /* Set IV */
342 : 0 : en_priv->iv_gen(cop, en_priv, count);
343 : :
344 : : /* Prepare op */
345 : 0 : pkt_len = rte_pktmbuf_pkt_len(mb);
346 : 0 : op->cipher.data.offset = data_offset << cipher_shift;
347 : 0 : op->cipher.data.length = (pkt_len - data_offset) << cipher_shift;
348 : :
349 [ # # ]: 0 : if (is_auth) {
350 : 0 : op->auth.data.offset = 0;
351 : 0 : op->auth.data.length = (pkt_len - RTE_PDCP_MAC_I_LEN) << auth_shift;
352 : 0 : op->auth.digest.data = rte_pktmbuf_mtod_offset(mb, uint8_t *,
353 : : (pkt_len - RTE_PDCP_MAC_I_LEN));
354 : 0 : op->auth.digest.phys_addr = rte_pktmbuf_iova_offset(mb,
355 : : (pkt_len - RTE_PDCP_MAC_I_LEN));
356 : : }
357 : :
358 : 0 : __rte_crypto_sym_op_attach_sym_session(op, en_priv->crypto_sess);
359 : 0 : }
360 : :
361 : : static inline bool
362 : 0 : pdcp_pre_process_uplane_sn_12_ul_set_sn(struct entity_priv *en_priv, struct rte_mbuf *mb,
363 : : uint32_t *count)
364 : : {
365 : : struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr;
366 [ # # ]: 0 : const uint8_t hdr_sz = en_priv->hdr_sz;
367 : : uint32_t sn;
368 : :
369 : : /* Prepend PDU header */
370 : : pdu_hdr = (struct rte_pdcp_up_data_pdu_sn_12_hdr *)rte_pktmbuf_prepend(mb, hdr_sz);
371 [ # # ]: 0 : if (unlikely(pdu_hdr == NULL))
372 : : return false;
373 : :
374 : : /* Update sequence num in the PDU header */
375 : 0 : *count = en_priv->state.tx_next++;
376 : : sn = pdcp_sn_from_count_get(*count, RTE_SECURITY_PDCP_SN_SIZE_12);
377 : :
378 : 0 : pdu_hdr->d_c = RTE_PDCP_PDU_TYPE_DATA;
379 : 0 : pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8);
380 : 0 : pdu_hdr->sn_7_0 = (sn & 0xff);
381 : 0 : pdu_hdr->r = 0;
382 : 0 : return true;
383 : : }
384 : :
385 : : static uint16_t
386 : 0 : pdcp_pre_process_uplane_sn_12_ul(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
387 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err_ret)
388 : : {
389 : : struct entity_priv *en_priv = entity_priv_get(entity);
390 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
391 : : struct rte_mbuf *mb;
392 : : uint32_t count;
393 : : uint8_t *mac_i;
394 : : int i;
395 : :
396 : 0 : const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
397 : 0 : const int is_null_auth = en_priv->flags.is_null_auth;
398 : :
399 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
400 : : num);
401 : :
402 [ # # ]: 0 : if (en_priv->flags.is_authenticated) {
403 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
404 : 0 : mb = in_mb[i];
405 : : mac_i = (uint8_t *)rte_pktmbuf_append(mb, RTE_PDCP_MAC_I_LEN);
406 [ # # ]: 0 : if (unlikely(mac_i == NULL)) {
407 : 0 : in_mb[nb_err++] = mb;
408 : 0 : continue;
409 : : }
410 : :
411 : : /* Clear MAC-I field for NULL auth */
412 [ # # ]: 0 : if (is_null_auth)
413 : : memset(mac_i, 0, RTE_PDCP_MAC_I_LEN);
414 : :
415 [ # # ]: 0 : if (unlikely(!pdcp_pre_process_uplane_sn_12_ul_set_sn(en_priv, mb,
416 : : &count))) {
417 : 0 : in_mb[nb_err++] = mb;
418 : 0 : continue;
419 : : }
420 : :
421 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, true);
422 : : }
423 : : } else {
424 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
425 : 0 : mb = in_mb[i];
426 [ # # ]: 0 : if (unlikely(!pdcp_pre_process_uplane_sn_12_ul_set_sn(en_priv, mb,
427 : : &count))) {
428 : 0 : in_mb[nb_err++] = mb;
429 : 0 : continue;
430 : : }
431 : :
432 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, false);
433 : : }
434 : : }
435 : :
436 [ # # ]: 0 : if (unlikely(nb_err))
437 : : /* Using mempool API since crypto API is not providing bulk free */
438 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
439 : :
440 : 0 : *nb_err_ret = num - nb_prep;
441 : :
442 : 0 : return nb_prep;
443 : : }
444 : :
445 : : static inline bool
446 : 0 : pdcp_pre_process_uplane_sn_18_ul_set_sn(struct entity_priv *en_priv, struct rte_mbuf *mb,
447 : : uint32_t *count)
448 : : {
449 : : struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr;
450 [ # # ]: 0 : const uint8_t hdr_sz = en_priv->hdr_sz;
451 : : uint32_t sn;
452 : :
453 : : /* Prepend PDU header */
454 : : pdu_hdr = (struct rte_pdcp_up_data_pdu_sn_18_hdr *)rte_pktmbuf_prepend(mb, hdr_sz);
455 [ # # ]: 0 : if (unlikely(pdu_hdr == NULL))
456 : : return false;
457 : :
458 : : /* Update sequence num in the PDU header */
459 : 0 : *count = en_priv->state.tx_next++;
460 : : sn = pdcp_sn_from_count_get(*count, RTE_SECURITY_PDCP_SN_SIZE_18);
461 : :
462 : 0 : pdu_hdr->d_c = RTE_PDCP_PDU_TYPE_DATA;
463 : 0 : pdu_hdr->sn_17_16 = ((sn & 0x30000) >> 16);
464 : 0 : pdu_hdr->sn_15_8 = ((sn & 0xff00) >> 8);
465 : 0 : pdu_hdr->sn_7_0 = (sn & 0xff);
466 : 0 : pdu_hdr->r = 0;
467 : :
468 : 0 : return true;
469 : : }
470 : :
471 : : static inline uint16_t
472 : 0 : pdcp_pre_process_uplane_sn_18_ul(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
473 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err_ret)
474 : : {
475 : : struct entity_priv *en_priv = entity_priv_get(entity);
476 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
477 : : struct rte_mbuf *mb;
478 : : uint32_t count;
479 : : uint8_t *mac_i;
480 : : int i;
481 : :
482 : 0 : const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
483 : 0 : const int is_null_auth = en_priv->flags.is_null_auth;
484 : :
485 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
486 : : num);
487 : :
488 [ # # ]: 0 : if (en_priv->flags.is_authenticated) {
489 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
490 : 0 : mb = in_mb[i];
491 : : mac_i = (uint8_t *)rte_pktmbuf_append(mb, RTE_PDCP_MAC_I_LEN);
492 [ # # ]: 0 : if (unlikely(mac_i == NULL)) {
493 : 0 : in_mb[nb_err++] = mb;
494 : 0 : continue;
495 : : }
496 : :
497 : : /* Clear MAC-I field for NULL auth */
498 [ # # ]: 0 : if (is_null_auth)
499 : : memset(mac_i, 0, RTE_PDCP_MAC_I_LEN);
500 : :
501 [ # # ]: 0 : if (unlikely(!pdcp_pre_process_uplane_sn_18_ul_set_sn(en_priv, mb,
502 : : &count))) {
503 : 0 : in_mb[nb_err++] = mb;
504 : 0 : continue;
505 : : }
506 : :
507 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, true);
508 : : }
509 : : } else {
510 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
511 : 0 : mb = in_mb[i];
512 [ # # ]: 0 : if (unlikely(!pdcp_pre_process_uplane_sn_18_ul_set_sn(en_priv, mb,
513 : : &count))) {
514 : :
515 : 0 : in_mb[nb_err++] = mb;
516 : 0 : continue;
517 : : }
518 : :
519 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, false);
520 : : }
521 : : }
522 : :
523 [ # # ]: 0 : if (unlikely(nb_err))
524 : : /* Using mempool API since crypto API is not providing bulk free */
525 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
526 : :
527 : 0 : *nb_err_ret = num - nb_prep;
528 : :
529 : 0 : return nb_prep;
530 : : }
531 : :
532 : : static uint16_t
533 : 0 : pdcp_pre_process_cplane_sn_12_ul(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
534 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err_ret)
535 : : {
536 : : struct entity_priv *en_priv = entity_priv_get(entity);
537 : : struct rte_pdcp_cp_data_pdu_sn_12_hdr *pdu_hdr;
538 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
539 : : struct rte_mbuf *mb;
540 : : uint32_t count, sn;
541 : : uint8_t *mac_i;
542 : : int i;
543 : :
544 : 0 : const uint8_t hdr_sz = en_priv->hdr_sz;
545 : 0 : const uint8_t data_offset = hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
546 : 0 : const int is_null_auth = en_priv->flags.is_null_auth;
547 : :
548 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
549 : : num);
550 : :
551 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
552 [ # # ]: 0 : mb = in_mb[i];
553 : : /* Prepend PDU header */
554 : : pdu_hdr = (struct rte_pdcp_cp_data_pdu_sn_12_hdr *)rte_pktmbuf_prepend(mb, hdr_sz);
555 [ # # ]: 0 : if (unlikely(pdu_hdr == NULL)) {
556 : 0 : in_mb[nb_err++] = mb;
557 : 0 : continue;
558 : : }
559 : :
560 : : mac_i = (uint8_t *)rte_pktmbuf_append(mb, RTE_PDCP_MAC_I_LEN);
561 [ # # ]: 0 : if (unlikely(mac_i == NULL)) {
562 : 0 : in_mb[nb_err++] = mb;
563 : 0 : continue;
564 : : }
565 : :
566 : : /* Clear MAC-I field for NULL auth */
567 [ # # ]: 0 : if (is_null_auth)
568 : : memset(mac_i, 0, RTE_PDCP_MAC_I_LEN);
569 : :
570 : : /* Update sequence number in the PDU header */
571 : 0 : count = en_priv->state.tx_next++;
572 : : sn = pdcp_sn_from_count_get(count, RTE_SECURITY_PDCP_SN_SIZE_12);
573 : :
574 : 0 : pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8);
575 : 0 : pdu_hdr->sn_7_0 = (sn & 0xff);
576 : 0 : pdu_hdr->r = 0;
577 : :
578 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, true);
579 : : }
580 : :
581 [ # # ]: 0 : if (unlikely(nb_err))
582 : : /* Using mempool API since crypto API is not providing bulk free */
583 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
584 : :
585 : 0 : *nb_err_ret = num - nb_prep;
586 : :
587 : 0 : return nb_prep;
588 : : }
589 : :
590 : : static uint16_t
591 : 0 : pdcp_post_process_ul(const struct rte_pdcp_entity *entity,
592 : : struct rte_mbuf *in_mb[], struct rte_mbuf *out_mb[],
593 : : uint16_t num, uint16_t *nb_err_ret)
594 : 0 : {
595 : : struct entity_priv *en_priv = entity_priv_get(entity);
596 : 0 : const uint32_t hdr_trim_sz = en_priv->aad_sz;
597 : : int i, nb_success = 0, nb_err = 0;
598 : 0 : struct rte_mbuf *mb, *err_mb[num];
599 : :
600 : : #ifdef RTE_ARCH_PPC_64
601 : : err_mb[0] = NULL; /* workaround PPC-GCC bug */
602 : : #endif
603 [ # # ]: 0 : for (i = 0; i < num; i++) {
604 : 0 : mb = in_mb[i];
605 [ # # ]: 0 : if (unlikely(mb->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
606 : 0 : err_mb[nb_err++] = mb;
607 : 0 : continue;
608 : : }
609 : :
610 [ # # ]: 0 : if (hdr_trim_sz)
611 [ # # ]: 0 : rte_pktmbuf_adj(mb, hdr_trim_sz);
612 : :
613 : 0 : out_mb[nb_success++] = mb;
614 : : }
615 : :
616 [ # # ]: 0 : if (unlikely(nb_err != 0))
617 [ # # ]: 0 : rte_memcpy(&out_mb[nb_success], err_mb, nb_err * sizeof(struct rte_mbuf *));
618 : :
619 : 0 : *nb_err_ret = nb_err;
620 : 0 : return nb_success;
621 : : }
622 : :
623 : : static inline int
624 : : pdcp_sn_count_get(const uint32_t rx_deliv, int32_t rsn, uint32_t *count,
625 : : const enum rte_security_pdcp_sn_size sn_size)
626 : : {
627 : : const uint32_t rx_deliv_sn = pdcp_sn_from_count_get(rx_deliv, sn_size);
628 : : const uint32_t window_sz = pdcp_window_size_get(sn_size);
629 : : uint32_t rhfn;
630 : :
631 : : rhfn = pdcp_hfn_from_count_get(rx_deliv, sn_size);
632 : :
633 [ # # # # : 0 : if (rsn < (int32_t)(rx_deliv_sn - window_sz)) {
# # ]
634 [ # # # # : 0 : if (unlikely(rhfn == pdcp_hfn_max(sn_size)))
# # ]
635 : : return -ERANGE;
636 : 0 : rhfn += 1;
637 [ # # # # : 0 : } else if ((uint32_t)rsn >= (rx_deliv_sn + window_sz)) {
# # ]
638 [ # # # # : 0 : if (unlikely(rhfn == PDCP_HFN_MIN))
# # ]
639 : : return -ERANGE;
640 : 0 : rhfn -= 1;
641 : : }
642 : :
643 : : *count = pdcp_count_from_hfn_sn_get(rhfn, rsn, sn_size);
644 : :
645 : 0 : return 0;
646 : : }
647 : :
648 : : static inline uint16_t
649 : 0 : pdcp_pre_process_uplane_sn_12_dl_flags(const struct rte_pdcp_entity *entity,
650 : : struct rte_mbuf *in_mb[], struct rte_crypto_op *cop[],
651 : : uint16_t num, uint16_t *nb_err_ret,
652 : : const bool is_integ_protected)
653 : : {
654 : : struct entity_priv *en_priv = entity_priv_get(entity);
655 : : struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr;
656 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
657 : : rte_pdcp_dynfield_t *mb_dynfield;
658 : : struct rte_mbuf *mb;
659 : : int32_t rsn = 0;
660 : : uint32_t count;
661 : : int i;
662 : :
663 : 0 : const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
664 : :
665 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
666 : : num);
667 : :
668 : 0 : const uint32_t rx_deliv = en_priv->state.rx_deliv;
669 : :
670 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
671 : 0 : mb = in_mb[i];
672 : 0 : pdu_hdr = rte_pktmbuf_mtod(mb, struct rte_pdcp_up_data_pdu_sn_12_hdr *);
673 : :
674 : : /* Check for PDU type */
675 [ # # ]: 0 : if (likely(pdu_hdr->d_c == RTE_PDCP_PDU_TYPE_DATA)) {
676 [ # # ]: 0 : rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
677 : : } else {
678 : : /** NOTE: Control PDU not handled.*/
679 : 0 : in_mb[nb_err++] = mb;
680 : 0 : continue;
681 : : }
682 : :
683 [ # # ]: 0 : if (unlikely(pdcp_sn_count_get(rx_deliv, rsn, &count,
684 : : RTE_SECURITY_PDCP_SN_SIZE_12))) {
685 : 0 : in_mb[nb_err++] = mb;
686 : 0 : continue;
687 : : }
688 : :
689 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, is_integ_protected);
690 : :
691 : : mb_dynfield = pdcp_dynfield(mb);
692 : 0 : *mb_dynfield = count;
693 : : }
694 : :
695 [ # # ]: 0 : if (unlikely(nb_err))
696 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
697 : :
698 : 0 : *nb_err_ret = num - nb_prep;
699 : :
700 : 0 : return nb_prep;
701 : : }
702 : :
703 : : static uint16_t
704 : 0 : pdcp_pre_process_uplane_sn_12_dl_ip(const struct rte_pdcp_entity *entity, struct rte_mbuf *mb[],
705 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err)
706 : : {
707 : 0 : return pdcp_pre_process_uplane_sn_12_dl_flags(entity, mb, cop, num, nb_err, true);
708 : : }
709 : :
710 : : static uint16_t
711 : 0 : pdcp_pre_process_uplane_sn_12_dl(const struct rte_pdcp_entity *entity, struct rte_mbuf *mb[],
712 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err)
713 : : {
714 : 0 : return pdcp_pre_process_uplane_sn_12_dl_flags(entity, mb, cop, num, nb_err, false);
715 : : }
716 : :
717 : : static inline uint16_t
718 : 0 : pdcp_pre_process_uplane_sn_18_dl_flags(const struct rte_pdcp_entity *entity,
719 : : struct rte_mbuf *in_mb[], struct rte_crypto_op *cop[],
720 : : uint16_t num, uint16_t *nb_err_ret,
721 : : const bool is_integ_protected)
722 : : {
723 : : struct entity_priv *en_priv = entity_priv_get(entity);
724 : : struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr;
725 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
726 : : rte_pdcp_dynfield_t *mb_dynfield;
727 : : struct rte_mbuf *mb;
728 : : int32_t rsn = 0;
729 : : uint32_t count;
730 : : int i;
731 : :
732 : 0 : const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
733 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
734 : : num);
735 : :
736 : 0 : const uint32_t rx_deliv = en_priv->state.rx_deliv;
737 : :
738 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
739 : 0 : mb = in_mb[i];
740 : 0 : pdu_hdr = rte_pktmbuf_mtod(mb, struct rte_pdcp_up_data_pdu_sn_18_hdr *);
741 : :
742 : : /* Check for PDU type */
743 [ # # ]: 0 : if (likely(pdu_hdr->d_c == RTE_PDCP_PDU_TYPE_DATA)) {
744 : 0 : rsn = ((pdu_hdr->sn_17_16 << 16) | (pdu_hdr->sn_15_8 << 8) |
745 [ # # ]: 0 : (pdu_hdr->sn_7_0));
746 : : } else {
747 : : /** NOTE: Control PDU not handled.*/
748 : 0 : in_mb[nb_err++] = mb;
749 : 0 : continue;
750 : : }
751 : :
752 [ # # ]: 0 : if (unlikely(pdcp_sn_count_get(rx_deliv, rsn, &count,
753 : : RTE_SECURITY_PDCP_SN_SIZE_18))) {
754 : 0 : in_mb[nb_err++] = mb;
755 : 0 : continue;
756 : : }
757 : :
758 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, is_integ_protected);
759 : :
760 : : mb_dynfield = pdcp_dynfield(mb);
761 : 0 : *mb_dynfield = count;
762 : : }
763 : :
764 [ # # ]: 0 : if (unlikely(nb_err))
765 : : /* Using mempool API since crypto API is not providing bulk free */
766 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
767 : :
768 : 0 : *nb_err_ret = num - nb_prep;
769 : :
770 : 0 : return nb_prep;
771 : : }
772 : :
773 : : static uint16_t
774 : 0 : pdcp_pre_process_uplane_sn_18_dl_ip(const struct rte_pdcp_entity *entity, struct rte_mbuf *mb[],
775 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err)
776 : : {
777 : 0 : return pdcp_pre_process_uplane_sn_18_dl_flags(entity, mb, cop, num, nb_err, true);
778 : : }
779 : :
780 : : static uint16_t
781 : 0 : pdcp_pre_process_uplane_sn_18_dl(const struct rte_pdcp_entity *entity, struct rte_mbuf *mb[],
782 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err)
783 : : {
784 : 0 : return pdcp_pre_process_uplane_sn_18_dl_flags(entity, mb, cop, num, nb_err, false);
785 : : }
786 : :
787 : : static uint16_t
788 : 0 : pdcp_pre_process_cplane_sn_12_dl(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
789 : : struct rte_crypto_op *cop[], uint16_t num, uint16_t *nb_err_ret)
790 : : {
791 : : struct entity_priv *en_priv = entity_priv_get(entity);
792 : : struct rte_pdcp_cp_data_pdu_sn_12_hdr *pdu_hdr;
793 : : uint16_t nb_cop, nb_prep = 0, nb_err = 0;
794 : : rte_pdcp_dynfield_t *mb_dynfield;
795 : : struct rte_mbuf *mb;
796 : : uint32_t count;
797 : : int32_t rsn;
798 : : int i;
799 : :
800 : 0 : const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz + en_priv->cipher_skip_sz;
801 : :
802 : 0 : nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
803 : : num);
804 : :
805 : 0 : const uint32_t rx_deliv = en_priv->state.rx_deliv;
806 : :
807 [ # # ]: 0 : for (i = 0; i < nb_cop; i++) {
808 : 0 : mb = in_mb[i];
809 : 0 : pdu_hdr = rte_pktmbuf_mtod(mb, struct rte_pdcp_cp_data_pdu_sn_12_hdr *);
810 [ # # ]: 0 : rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
811 [ # # ]: 0 : if (unlikely(pdcp_sn_count_get(rx_deliv, rsn, &count,
812 : : RTE_SECURITY_PDCP_SN_SIZE_12))) {
813 : 0 : in_mb[nb_err++] = mb;
814 : 0 : continue;
815 : : }
816 : :
817 : 0 : cop_prepare(en_priv, mb, cop[nb_prep++], data_offset, count, true);
818 : :
819 : : mb_dynfield = pdcp_dynfield(mb);
820 : 0 : *mb_dynfield = count;
821 : : }
822 : :
823 [ # # ]: 0 : if (unlikely(nb_err))
824 : : /* Using mempool API since crypto API is not providing bulk free */
825 [ # # ]: 0 : rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[nb_prep], nb_cop - nb_prep);
826 : :
827 : 0 : *nb_err_ret = num - nb_prep;
828 : :
829 : 0 : return nb_prep;
830 : : }
831 : :
832 : : static inline void
833 : 0 : pdcp_packet_strip(struct rte_mbuf *mb, const uint32_t hdr_trim_sz, const bool trim_mac)
834 : : {
835 [ # # ]: 0 : char *p = rte_pktmbuf_adj(mb, hdr_trim_sz);
836 : : RTE_ASSERT(p != NULL);
837 : : RTE_SET_USED(p);
838 : :
839 [ # # ]: 0 : if (trim_mac) {
840 : : int ret = rte_pktmbuf_trim(mb, RTE_PDCP_MAC_I_LEN);
841 : : RTE_ASSERT(ret == 0);
842 : : RTE_SET_USED(ret);
843 : : }
844 : 0 : }
845 : :
846 : : static inline int
847 [ # # ]: 0 : pdcp_post_process_update_entity_state(const struct rte_pdcp_entity *entity,
848 : : const uint32_t count, struct rte_mbuf *mb,
849 : : struct rte_mbuf *out_mb[],
850 : : const bool trim_mac)
851 : : {
852 : : struct entity_priv *en_priv = entity_priv_get(entity);
853 : : struct pdcp_t_reordering *t_reorder;
854 : : struct pdcp_reorder *reorder;
855 : : uint16_t processed = 0;
856 : :
857 : : struct entity_priv_dl_part *dl = entity_dl_part_get(entity);
858 : 0 : const uint32_t hdr_trim_sz = en_priv->hdr_sz + en_priv->aad_sz;
859 : :
860 [ # # ]: 0 : if (count < en_priv->state.rx_deliv)
861 : : return -EINVAL;
862 : :
863 [ # # ]: 0 : if (count >= en_priv->state.rx_next)
864 : 0 : en_priv->state.rx_next = count + 1;
865 : :
866 [ # # ]: 0 : if (unlikely(pdcp_cnt_bitmap_is_set(dl->bitmap, count)))
867 : : return -EEXIST;
868 : :
869 : 0 : pdcp_cnt_bitmap_set(dl->bitmap, count);
870 : 0 : pdcp_packet_strip(mb, hdr_trim_sz, trim_mac);
871 : :
872 [ # # ]: 0 : if (en_priv->flags.is_out_of_order_delivery) {
873 : 0 : out_mb[0] = mb;
874 : 0 : pdcp_rx_deliv_set(entity, count + 1);
875 : :
876 : 0 : return 1;
877 : : }
878 : :
879 : 0 : reorder = &dl->reorder;
880 : : t_reorder = &dl->t_reorder;
881 : :
882 [ # # ]: 0 : if (count == en_priv->state.rx_deliv) {
883 [ # # ]: 0 : if (reorder->is_active) {
884 : : /*
885 : : * This insert used only to increment reorder->min_seqn
886 : : * To remove it - min_seqn_set() has to work with non-empty buffer
887 : : */
888 : 0 : pdcp_reorder_insert(reorder, mb, count);
889 : :
890 : : /* Get buffered packets */
891 : : struct rte_mbuf **cached_mbufs = &out_mb[processed];
892 : : uint32_t nb_cached = pdcp_reorder_get_sequential(reorder,
893 : 0 : cached_mbufs, entity->max_pkt_cache - processed);
894 : :
895 : 0 : processed += nb_cached;
896 : : } else {
897 : 0 : out_mb[processed++] = mb;
898 : : }
899 : :
900 : : /* Processed should never exceed the window size */
901 : 0 : pdcp_rx_deliv_set(entity, count + processed);
902 : :
903 : : } else {
904 [ # # ]: 0 : if (!reorder->is_active)
905 : : /* Initialize reordering buffer with RX_DELIV */
906 : 0 : pdcp_reorder_start(reorder, en_priv->state.rx_deliv);
907 : : /* Buffer the packet */
908 : 0 : pdcp_reorder_insert(reorder, mb, count);
909 : : }
910 : :
911 : : /* Stop & reset current timer if rx_reord is received */
912 [ # # ]: 0 : if (t_reorder->state == TIMER_RUNNING &&
913 [ # # ]: 0 : en_priv->state.rx_deliv >= en_priv->state.rx_reord) {
914 : 0 : t_reorder->state = TIMER_STOP;
915 : 0 : t_reorder->handle.stop(t_reorder->handle.timer, t_reorder->handle.args);
916 : : /* Stop reorder buffer, only if it's empty */
917 [ # # ]: 0 : if (en_priv->state.rx_deliv == en_priv->state.rx_next)
918 : : pdcp_reorder_stop(reorder);
919 : : }
920 : :
921 : : /*
922 : : * If t-Reordering is not running (includes the case when t-Reordering is stopped due to
923 : : * actions above).
924 : : */
925 [ # # # # ]: 0 : if (t_reorder->state == TIMER_STOP && en_priv->state.rx_deliv < en_priv->state.rx_next) {
926 : : /* Update RX_REORD to RX_NEXT */
927 : 0 : en_priv->state.rx_reord = en_priv->state.rx_next;
928 : : /* Start t-Reordering */
929 : 0 : t_reorder->state = TIMER_RUNNING;
930 : 0 : t_reorder->handle.start(t_reorder->handle.timer, t_reorder->handle.args);
931 : : }
932 : :
933 : 0 : return processed;
934 : : }
935 : :
936 : : static inline uint16_t
937 : 0 : pdcp_post_process_uplane_dl_flags(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
938 : : struct rte_mbuf *out_mb[], uint16_t num, uint16_t *nb_err_ret,
939 : : const bool is_integ_protected)
940 : 0 : {
941 : : int i, nb_processed, nb_success = 0, nb_err = 0;
942 : : rte_pdcp_dynfield_t *mb_dynfield;
943 : 0 : struct rte_mbuf *err_mb[num];
944 : : struct rte_mbuf *mb;
945 : : uint32_t count;
946 : :
947 : : #ifdef RTE_ARCH_PPC_64
948 : : err_mb[0] = NULL; /* workaround PPC-GCC bug */
949 : : #endif
950 [ # # ]: 0 : for (i = 0; i < num; i++) {
951 : 0 : mb = in_mb[i];
952 [ # # ]: 0 : if (unlikely(mb->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED))
953 : 0 : goto error;
954 : :
955 : : mb_dynfield = pdcp_dynfield(mb);
956 : 0 : count = *mb_dynfield;
957 : :
958 : 0 : nb_processed = pdcp_post_process_update_entity_state(
959 : 0 : entity, count, mb, &out_mb[nb_success], is_integ_protected);
960 [ # # ]: 0 : if (nb_processed < 0)
961 : 0 : goto error;
962 : :
963 : 0 : nb_success += nb_processed;
964 : 0 : continue;
965 : :
966 : 0 : error:
967 : 0 : err_mb[nb_err++] = mb;
968 : : }
969 : :
970 [ # # ]: 0 : if (unlikely(nb_err != 0))
971 [ # # ]: 0 : rte_memcpy(&out_mb[nb_success], err_mb, nb_err * sizeof(struct rte_mbuf *));
972 : :
973 : 0 : *nb_err_ret = nb_err;
974 : 0 : return nb_success;
975 : : }
976 : :
977 : : static uint16_t
978 : 0 : pdcp_post_process_uplane_dl_ip(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
979 : : struct rte_mbuf *out_mb[], uint16_t num, uint16_t *nb_err)
980 : : {
981 : 0 : return pdcp_post_process_uplane_dl_flags(entity, in_mb, out_mb, num, nb_err, true);
982 : : }
983 : :
984 : : static uint16_t
985 : 0 : pdcp_post_process_uplane_dl(const struct rte_pdcp_entity *entity, struct rte_mbuf *in_mb[],
986 : : struct rte_mbuf *out_mb[], uint16_t num, uint16_t *nb_err)
987 : : {
988 : 0 : return pdcp_post_process_uplane_dl_flags(entity, in_mb, out_mb, num, nb_err, false);
989 : : }
990 : :
991 : : static uint16_t
992 : 0 : pdcp_post_process_cplane_sn_12_dl(const struct rte_pdcp_entity *entity,
993 : : struct rte_mbuf *in_mb[],
994 : : struct rte_mbuf *out_mb[],
995 : : uint16_t num, uint16_t *nb_err_ret)
996 : 0 : {
997 : : int i, nb_processed, nb_success = 0, nb_err = 0;
998 : : rte_pdcp_dynfield_t *mb_dynfield;
999 : 0 : struct rte_mbuf *err_mb[num];
1000 : : struct rte_mbuf *mb;
1001 : : uint32_t count;
1002 : :
1003 : : #ifdef RTE_ARCH_PPC_64
1004 : : err_mb[0] = NULL; /* workaround PPC-GCC bug */
1005 : : #endif
1006 [ # # ]: 0 : for (i = 0; i < num; i++) {
1007 : 0 : mb = in_mb[i];
1008 [ # # ]: 0 : if (unlikely(mb->ol_flags & RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED))
1009 : 0 : goto error;
1010 : :
1011 : : mb_dynfield = pdcp_dynfield(mb);
1012 : 0 : count = *mb_dynfield;
1013 : :
1014 : 0 : nb_processed = pdcp_post_process_update_entity_state(
1015 : 0 : entity, count, mb, &out_mb[nb_success], true);
1016 [ # # ]: 0 : if (nb_processed < 0)
1017 : 0 : goto error;
1018 : :
1019 : 0 : nb_success += nb_processed;
1020 : 0 : continue;
1021 : :
1022 : 0 : error:
1023 : 0 : err_mb[nb_err++] = mb;
1024 : : }
1025 : :
1026 [ # # ]: 0 : if (unlikely(nb_err != 0))
1027 [ # # ]: 0 : rte_memcpy(&out_mb[nb_success], err_mb, nb_err * sizeof(struct rte_mbuf *));
1028 : :
1029 : 0 : *nb_err_ret = nb_err;
1030 : 0 : return nb_success;
1031 : : }
1032 : :
1033 : : static int
1034 [ # # ]: 0 : pdcp_pre_post_func_set(struct rte_pdcp_entity *entity, const struct rte_pdcp_entity_conf *conf)
1035 : : {
1036 : : struct entity_priv *en_priv = entity_priv_get(entity);
1037 : :
1038 : 0 : entity->pre_process = NULL;
1039 : 0 : entity->post_process = NULL;
1040 : :
1041 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_CONTROL) &&
1042 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
1043 : : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
1044 : 0 : entity->pre_process = pdcp_pre_process_cplane_sn_12_ul;
1045 : 0 : entity->post_process = pdcp_post_process_ul;
1046 : : }
1047 : :
1048 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_CONTROL) &&
1049 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
1050 : : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)) {
1051 : 0 : entity->pre_process = pdcp_pre_process_cplane_sn_12_dl;
1052 : 0 : entity->post_process = pdcp_post_process_cplane_sn_12_dl;
1053 : : }
1054 : :
1055 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1056 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
1057 : : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
1058 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_12_ul;
1059 : 0 : entity->post_process = pdcp_post_process_ul;
1060 : : }
1061 : :
1062 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1063 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
1064 : : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
1065 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_18_ul;
1066 : 0 : entity->post_process = pdcp_post_process_ul;
1067 : : }
1068 : :
1069 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1070 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
1071 [ # # ]: 0 : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
1072 : : (en_priv->flags.is_authenticated)) {
1073 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_12_dl_ip;
1074 : 0 : entity->post_process = pdcp_post_process_uplane_dl_ip;
1075 : : }
1076 : :
1077 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1078 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
1079 : 0 : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
1080 [ # # ]: 0 : (!en_priv->flags.is_authenticated)) {
1081 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_12_dl;
1082 : 0 : entity->post_process = pdcp_post_process_uplane_dl;
1083 : : }
1084 : :
1085 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1086 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
1087 [ # # ]: 0 : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
1088 : : (en_priv->flags.is_authenticated)) {
1089 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_18_dl_ip;
1090 : 0 : entity->post_process = pdcp_post_process_uplane_dl_ip;
1091 : : }
1092 : :
1093 [ # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA) &&
1094 [ # # ]: 0 : (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
1095 : 0 : (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
1096 [ # # ]: 0 : (!en_priv->flags.is_authenticated)) {
1097 : 0 : entity->pre_process = pdcp_pre_process_uplane_sn_18_dl;
1098 : 0 : entity->post_process = pdcp_post_process_uplane_dl;
1099 : : }
1100 : :
1101 [ # # # # ]: 0 : if (entity->pre_process == NULL || entity->post_process == NULL)
1102 : 0 : return -ENOTSUP;
1103 : :
1104 : : return 0;
1105 : : }
1106 : :
1107 : : static int
1108 [ # # ]: 0 : pdcp_entity_priv_populate(struct entity_priv *en_priv, const struct rte_pdcp_entity_conf *conf)
1109 : : {
1110 : : struct rte_crypto_sym_xform *c_xfrm, *a_xfrm;
1111 : : int ret;
1112 : :
1113 : : ret = pdcp_crypto_xfrm_get(conf, &c_xfrm, &a_xfrm);
1114 [ # # ]: 0 : if (ret)
1115 : : return ret;
1116 : :
1117 : : /**
1118 : : * flags.is_authenticated
1119 : : *
1120 : : * MAC-I would be added in case of control plane packets and when authentication
1121 : : * transform is not NULL.
1122 : : */
1123 : :
1124 [ # # # # ]: 0 : if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_CONTROL) && (a_xfrm == NULL))
1125 : : return -EINVAL;
1126 : :
1127 [ # # ]: 0 : if (a_xfrm != NULL)
1128 : 0 : en_priv->flags.is_authenticated = 1;
1129 : :
1130 : : /**
1131 : : * flags.is_cipher_in_bits
1132 : : *
1133 : : * For ZUC & SNOW3G cipher algos, offset & length need to be provided in bits.
1134 : : */
1135 : :
1136 [ # # ]: 0 : if ((c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2) ||
1137 : : (c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_ZUC_EEA3))
1138 : 0 : en_priv->flags.is_cipher_in_bits = 1;
1139 : :
1140 : : /**
1141 : : * flags.is_auth_in_bits
1142 : : *
1143 : : * For ZUC & SNOW3G authentication algos, offset & length need to be provided in bits.
1144 : : */
1145 : :
1146 [ # # ]: 0 : if (a_xfrm != NULL) {
1147 [ # # ]: 0 : if ((a_xfrm->auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2) ||
1148 : : (a_xfrm->auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3))
1149 : 0 : en_priv->flags.is_auth_in_bits = 1;
1150 : : }
1151 : :
1152 : : /**
1153 : : * flags.is_ul_entity
1154 : : *
1155 : : * Indicate whether the entity is UL/transmitting PDCP entity.
1156 : : */
1157 [ # # ]: 0 : if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
1158 : 0 : en_priv->flags.is_ul_entity = 1;
1159 : :
1160 : : /**
1161 : : * flags.is_null_auth
1162 : : *
1163 : : * For NULL auth, 4B zeros need to be added by lib PDCP. Indicate that
1164 : : * algo is NULL auth to perform the same.
1165 : : */
1166 [ # # # # ]: 0 : if (a_xfrm != NULL && a_xfrm->auth.algo == RTE_CRYPTO_AUTH_NULL)
1167 : 0 : en_priv->flags.is_null_auth = 1;
1168 : :
1169 : : /**
1170 : : * flags.is_status_report_required
1171 : : *
1172 : : * Indicate whether status report is required.
1173 : : */
1174 [ # # ]: 0 : if (conf->status_report_required) {
1175 : : /** Status report is required only for DL entities. */
1176 [ # # ]: 0 : if (conf->pdcp_xfrm.pkt_dir != RTE_SECURITY_PDCP_DOWNLINK)
1177 : : return -EINVAL;
1178 : :
1179 : 0 : en_priv->flags.is_status_report_required = 1;
1180 : : }
1181 : :
1182 : : /**
1183 : : * flags.is_out_of_order_delivery
1184 : : *
1185 : : * Indicate whether the outoforder delivery is enabled for PDCP entity.
1186 : : */
1187 : 0 : en_priv->flags.is_out_of_order_delivery = conf->out_of_order_delivery;
1188 : :
1189 : : /**
1190 : : * hdr_sz
1191 : : *
1192 : : * PDCP header size of the entity
1193 : : */
1194 [ # # ]: 0 : en_priv->hdr_sz = pdcp_hdr_size_get(conf->pdcp_xfrm.sn_size);
1195 : :
1196 : : /**
1197 : : * aad_sz
1198 : : *
1199 : : * For AES-CMAC, additional message is prepended for processing. Need to be trimmed after
1200 : : * crypto processing is done.
1201 : : */
1202 [ # # # # ]: 0 : if (a_xfrm != NULL && a_xfrm->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC)
1203 : 0 : en_priv->aad_sz = 8;
1204 : : else
1205 : 0 : en_priv->aad_sz = 0;
1206 : :
1207 : : /**
1208 : : * cipher_skip_sz
1209 : : *
1210 : : * When SDAP protocol is enabled for the PDCP entity, skip the SDAP header from ciphering.
1211 : : */
1212 [ # # ]: 0 : if (conf->pdcp_xfrm.sdap_enabled)
1213 : 0 : en_priv->cipher_skip_sz = 1;
1214 : : else
1215 : 0 : en_priv->cipher_skip_sz = 0;
1216 : :
1217 : : return 0;
1218 : : }
1219 : :
1220 : : int
1221 : 0 : pdcp_process_func_set(struct rte_pdcp_entity *entity, const struct rte_pdcp_entity_conf *conf)
1222 : : {
1223 : : struct entity_priv *en_priv;
1224 : : int ret;
1225 : :
1226 [ # # ]: 0 : if (entity == NULL || conf == NULL)
1227 : : return -EINVAL;
1228 : :
1229 : : en_priv = entity_priv_get(entity);
1230 : :
1231 : 0 : ret = pdcp_iv_gen_func_set(entity, conf);
1232 [ # # ]: 0 : if (ret)
1233 : : return ret;
1234 : :
1235 : 0 : ret = pdcp_entity_priv_populate(en_priv, conf);
1236 [ # # ]: 0 : if (ret)
1237 : : return ret;
1238 : :
1239 : 0 : ret = pdcp_pre_post_func_set(entity, conf);
1240 [ # # ]: 0 : if (ret)
1241 : 0 : return ret;
1242 : :
1243 : : return 0;
1244 : : }
|