xref: /dpdk/drivers/crypto/bcmfs/bcmfs_sym_session.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
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 }
283