dpdk/drivers/crypto/bcmfs/bcmfs_sym_session.c
<<
>>
Prefs
   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 */
  16static enum bcmfs_sym_chain_order
  17crypto_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 */
  44static void
  45get_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 */
  51static int
  52crypto_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 */
  74static int
  75crypto_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 */
  98static int
  99crypto_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
 122static struct rte_crypto_auth_xform *
 123crypto_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
 135static struct rte_crypto_cipher_xform *
 136crypto_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 */
 149static int
 150crypto_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
 200error:
 201        return rc;
 202}
 203
 204struct bcmfs_sym_session *
 205bcmfs_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
 224int
 225bcmfs_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 */
 260void
 261bcmfs_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
 278unsigned int
 279bcmfs_sym_session_get_private_size(struct rte_cryptodev *dev __rte_unused)
 280{
 281        return sizeof(struct bcmfs_sym_session);
 282}
 283