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