xref: /dpdk/drivers/crypto/bcmfs/bcmfs_sym_session.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
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");
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 = CRYPTODEV_GET_SYM_SESS_PRIV(op->sym->session);
214 	}
215 
216 	if (sess == NULL)
217 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
218 
219 	return sess;
220 }
221 
222 int
223 bcmfs_sym_session_configure(struct rte_cryptodev *dev __rte_unused,
224 			    struct rte_crypto_sym_xform *xform,
225 			    struct rte_cryptodev_sym_session *sess)
226 {
227 	void *sess_private_data;
228 	int ret;
229 
230 	if (unlikely(sess == NULL)) {
231 		BCMFS_DP_LOG(ERR, "Invalid session struct");
232 		return -EINVAL;
233 	}
234 
235 	sess_private_data = CRYPTODEV_GET_SYM_SESS_PRIV(sess);
236 
237 	ret = crypto_set_session_parameters(sess_private_data, xform);
238 
239 	if (ret != 0) {
240 		BCMFS_DP_LOG(ERR, "Failed configure session parameters");
241 		return ret;
242 	}
243 
244 	return 0;
245 }
246 
247 /* Clear the memory of session so it doesn't leave key material behind */
248 void
249 bcmfs_sym_session_clear(struct rte_cryptodev *dev __rte_unused,
250 			struct rte_cryptodev_sym_session  *sess __rte_unused)
251 {}
252 
253 unsigned int
254 bcmfs_sym_session_get_private_size(struct rte_cryptodev *dev __rte_unused)
255 {
256 	return sizeof(struct bcmfs_sym_session);
257 }
258