net/mlx5: wrap default miss flow action per OS
[dpdk.git] / drivers / crypto / bcmfs / bcmfs_sym_session.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_crypto.h>
7 #include <rte_crypto_sym.h>
8 #include <rte_log.h>
9
10 #include "bcmfs_logs.h"
11 #include "bcmfs_sym_defs.h"
12 #include "bcmfs_sym_pmd.h"
13 #include "bcmfs_sym_session.h"
14
15 /** Configure the session from a crypto xform chain */
16 static enum bcmfs_sym_chain_order
17 crypto_get_chain_order(const struct rte_crypto_sym_xform *xform)
18 {
19         enum bcmfs_sym_chain_order res = BCMFS_SYM_CHAIN_NOT_SUPPORTED;
20
21         if (xform != NULL) {
22                 if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD)
23                         res = BCMFS_SYM_CHAIN_AEAD;
24
25                 if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
26                         if (xform->next == NULL)
27                                 res =  BCMFS_SYM_CHAIN_ONLY_AUTH;
28                         else if (xform->next->type ==
29                                         RTE_CRYPTO_SYM_XFORM_CIPHER)
30                                 res = BCMFS_SYM_CHAIN_AUTH_CIPHER;
31                 }
32                 if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
33                         if (xform->next == NULL)
34                                 res =  BCMFS_SYM_CHAIN_ONLY_CIPHER;
35                         else if (xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
36                                 res =  BCMFS_SYM_CHAIN_CIPHER_AUTH;
37                 }
38         }
39
40         return res;
41 }
42
43 /* Get session cipher key from input cipher key */
44 static void
45 get_key(const uint8_t *input_key, int keylen, uint8_t *session_key)
46 {
47         memcpy(session_key, input_key, keylen);
48 }
49
50 /* Set session cipher parameters */
51 static int
52 crypto_set_session_cipher_parameters(struct bcmfs_sym_session *sess,
53                          const struct rte_crypto_cipher_xform *cipher_xform)
54 {
55         if (cipher_xform->key.length > BCMFS_MAX_KEY_SIZE) {
56                 BCMFS_DP_LOG(ERR, "key length not supported");
57                 return -EINVAL;
58         }
59
60         sess->cipher.key.length = cipher_xform->key.length;
61         sess->cipher.iv.offset = cipher_xform->iv.offset;
62         sess->cipher.iv.length = cipher_xform->iv.length;
63         sess->cipher.op = cipher_xform->op;
64         sess->cipher.algo = cipher_xform->algo;
65
66         get_key(cipher_xform->key.data,
67                 sess->cipher.key.length,
68                 sess->cipher.key.data);
69
70         return 0;
71 }
72
73 /* Set session auth parameters */
74 static int
75 crypto_set_session_auth_parameters(struct bcmfs_sym_session *sess,
76                         const struct rte_crypto_auth_xform *auth_xform)
77 {
78         if (auth_xform->key.length > BCMFS_MAX_KEY_SIZE) {
79                 BCMFS_DP_LOG(ERR, "key length not supported");
80                 return -EINVAL;
81         }
82
83         sess->auth.op = auth_xform->op;
84         sess->auth.key.length = auth_xform->key.length;
85         sess->auth.digest_length = auth_xform->digest_length;
86         sess->auth.iv.length = auth_xform->iv.length;
87         sess->auth.iv.offset = auth_xform->iv.offset;
88         sess->auth.algo = auth_xform->algo;
89
90         get_key(auth_xform->key.data,
91                 auth_xform->key.length,
92                 sess->auth.key.data);
93
94         return 0;
95 }
96
97 /* Set session aead parameters */
98 static int
99 crypto_set_session_aead_parameters(struct bcmfs_sym_session *sess,
100                         const struct rte_crypto_sym_xform *aead_xform)
101 {
102         if (aead_xform->aead.key.length > BCMFS_MAX_KEY_SIZE) {
103                 BCMFS_DP_LOG(ERR, "key length not supported");
104                 return -EINVAL;
105         }
106
107         sess->aead.iv.offset = aead_xform->aead.iv.offset;
108         sess->aead.iv.length = aead_xform->aead.iv.length;
109         sess->aead.aad_length = aead_xform->aead.aad_length;
110         sess->aead.key.length = aead_xform->aead.key.length;
111         sess->aead.digest_length = aead_xform->aead.digest_length;
112         sess->aead.op = aead_xform->aead.op;
113         sess->aead.algo = aead_xform->aead.algo;
114
115         get_key(aead_xform->aead.key.data,
116                 aead_xform->aead.key.length,
117                 sess->aead.key.data);
118
119         return 0;
120 }
121
122 static struct rte_crypto_auth_xform *
123 crypto_get_auth_xform(struct rte_crypto_sym_xform *xform)
124 {
125         do {
126                 if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
127                         return &xform->auth;
128
129                 xform = xform->next;
130         } while (xform);
131
132         return NULL;
133 }
134
135 static struct rte_crypto_cipher_xform *
136 crypto_get_cipher_xform(struct rte_crypto_sym_xform *xform)
137 {
138         do {
139                 if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
140                         return &xform->cipher;
141
142                 xform = xform->next;
143         } while (xform);
144
145         return NULL;
146 }
147
148 /** Parse crypto xform chain and set private session parameters */
149 static int
150 crypto_set_session_parameters(struct bcmfs_sym_session *sess,
151                               struct rte_crypto_sym_xform *xform)
152 {
153         int rc = 0;
154         struct rte_crypto_cipher_xform *cipher_xform =
155                         crypto_get_cipher_xform(xform);
156         struct rte_crypto_auth_xform *auth_xform =
157                         crypto_get_auth_xform(xform);
158
159         sess->chain_order = crypto_get_chain_order(xform);
160
161         switch (sess->chain_order) {
162         case BCMFS_SYM_CHAIN_ONLY_CIPHER:
163                 if (crypto_set_session_cipher_parameters(sess, cipher_xform))
164                         rc = -EINVAL;
165                 break;
166         case BCMFS_SYM_CHAIN_ONLY_AUTH:
167                 if (crypto_set_session_auth_parameters(sess, auth_xform))
168                         rc = -EINVAL;
169                 break;
170         case BCMFS_SYM_CHAIN_AUTH_CIPHER:
171                 sess->cipher_first = false;
172                 if (crypto_set_session_auth_parameters(sess, auth_xform)) {
173                         rc = -EINVAL;
174                         goto error;
175                 }
176
177                 if (crypto_set_session_cipher_parameters(sess, cipher_xform))
178                         rc = -EINVAL;
179                 break;
180         case BCMFS_SYM_CHAIN_CIPHER_AUTH:
181                 sess->cipher_first = true;
182                 if (crypto_set_session_auth_parameters(sess, auth_xform)) {
183                         rc = -EINVAL;
184                         goto error;
185                 }
186
187                 if (crypto_set_session_cipher_parameters(sess, cipher_xform))
188                         rc = -EINVAL;
189                 break;
190         case BCMFS_SYM_CHAIN_AEAD:
191                 if (crypto_set_session_aead_parameters(sess, xform))
192                         rc = -EINVAL;
193                 break;
194         default:
195                 BCMFS_DP_LOG(ERR, "Invalid chain order\n");
196                 rc = -EINVAL;
197                 break;
198         }
199
200 error:
201         return rc;
202 }
203
204 struct bcmfs_sym_session *
205 bcmfs_sym_get_session(struct rte_crypto_op *op)
206 {
207         struct bcmfs_sym_session *sess = NULL;
208
209         if (unlikely(op->sess_type == RTE_CRYPTO_OP_SESSIONLESS)) {
210                 BCMFS_DP_LOG(ERR, "operations op(%p) is sessionless", op);
211         } else if (likely(op->sym->session != NULL)) {
212                 /* get existing session */
213                 sess = (struct bcmfs_sym_session *)
214                           get_sym_session_private_data(op->sym->session,
215                                                        cryptodev_bcmfs_driver_id);
216         }
217
218         if (sess == NULL)
219                 op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
220
221         return sess;
222 }
223
224 int
225 bcmfs_sym_session_configure(struct rte_cryptodev *dev,
226                             struct rte_crypto_sym_xform *xform,
227                             struct rte_cryptodev_sym_session *sess,
228                             struct rte_mempool *mempool)
229 {
230         void *sess_private_data;
231         int ret;
232
233         if (unlikely(sess == NULL)) {
234                 BCMFS_DP_LOG(ERR, "Invalid session struct");
235                 return -EINVAL;
236         }
237
238         if (rte_mempool_get(mempool, &sess_private_data)) {
239                 BCMFS_DP_LOG(ERR,
240                         "Couldn't get object from session mempool");
241                 return -ENOMEM;
242         }
243
244         ret = crypto_set_session_parameters(sess_private_data, xform);
245
246         if (ret != 0) {
247                 BCMFS_DP_LOG(ERR, "Failed configure session parameters");
248                 /* Return session to mempool */
249                 rte_mempool_put(mempool, sess_private_data);
250                 return ret;
251         }
252
253         set_sym_session_private_data(sess, dev->driver_id,
254                                      sess_private_data);
255
256         return 0;
257 }
258
259 /* Clear the memory of session so it doesn't leave key material behind */
260 void
261 bcmfs_sym_session_clear(struct rte_cryptodev *dev,
262                         struct rte_cryptodev_sym_session  *sess)
263 {
264         uint8_t index = dev->driver_id;
265         void *sess_priv = get_sym_session_private_data(sess, index);
266
267         if (sess_priv) {
268                 struct rte_mempool *sess_mp;
269
270                 memset(sess_priv, 0, sizeof(struct bcmfs_sym_session));
271                 sess_mp = rte_mempool_from_obj(sess_priv);
272
273                 set_sym_session_private_data(sess, index, NULL);
274                 rte_mempool_put(sess_mp, sess_priv);
275         }
276 }
277
278 unsigned int
279 bcmfs_sym_session_get_private_size(struct rte_cryptodev *dev __rte_unused)
280 {
281         return sizeof(struct bcmfs_sym_session);
282 }