+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/** Check DOCSIS security session configuration is valid */
+static int
+check_docsis_sec_session(struct rte_security_session_conf *conf)
+{
+ struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+ struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+ /* Downlink: CRC generate -> Cipher encrypt */
+ if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+ if (crypto_sym != NULL &&
+ crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+ crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+ crypto_sym->cipher.algo ==
+ RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+ (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+ crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+ crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+ crypto_sym->next == NULL) {
+ return 0;
+ }
+ /* Uplink: Cipher decrypt -> CRC verify */
+ } else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+ if (crypto_sym != NULL &&
+ crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+ crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+ crypto_sym->cipher.algo ==
+ RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+ (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+ crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+ crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+ crypto_sym->next == NULL) {
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/** Set DOCSIS security session auth (CRC) parameters */
+static int
+aesni_mb_set_docsis_sec_session_auth_parameters(struct aesni_mb_session *sess,
+ struct rte_security_docsis_xform *xform)
+{
+ if (xform == NULL) {
+ AESNI_MB_LOG(ERR, "Invalid DOCSIS xform");
+ return -EINVAL;
+ }
+
+ /* Select CRC generate/verify */
+ if (xform->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+ sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+ sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
+ } else if (xform->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+ sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+ sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
+ } else {
+ AESNI_MB_LOG(ERR, "Unsupported DOCSIS direction");
+ return -ENOTSUP;
+ }
+
+ sess->auth.req_digest_len = RTE_ETHER_CRC_LEN;
+ sess->auth.gen_digest_len = RTE_ETHER_CRC_LEN;
+
+ return 0;
+}
+
+/**
+ * Parse DOCSIS security session configuration and set private session
+ * parameters
+ */
+int
+aesni_mb_set_docsis_sec_session_parameters(
+ __rte_unused struct rte_cryptodev *dev,
+ struct rte_security_session_conf *conf,
+ void *sess)
+{
+ struct rte_security_docsis_xform *docsis_xform;
+ struct rte_crypto_sym_xform *cipher_xform;
+ struct aesni_mb_session *aesni_sess = sess;
+ struct aesni_mb_private *internals = dev->data->dev_private;
+ int ret;
+
+ ret = check_docsis_sec_session(conf);
+ if (ret) {
+ AESNI_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
+ return ret;
+ }
+
+ switch (conf->docsis.direction) {
+ case RTE_SECURITY_DOCSIS_UPLINK:
+ aesni_sess->chain_order = IMB_ORDER_CIPHER_HASH;
+ docsis_xform = &conf->docsis;
+ cipher_xform = conf->crypto_xform;
+ break;
+ case RTE_SECURITY_DOCSIS_DOWNLINK:
+ aesni_sess->chain_order = IMB_ORDER_HASH_CIPHER;
+ cipher_xform = conf->crypto_xform;
+ docsis_xform = &conf->docsis;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Default IV length = 0 */
+ aesni_sess->iv.length = 0;
+
+ ret = aesni_mb_set_docsis_sec_session_auth_parameters(aesni_sess,
+ docsis_xform);
+ if (ret != 0) {
+ AESNI_MB_LOG(ERR, "Invalid/unsupported DOCSIS parameters");
+ return -EINVAL;
+ }
+
+ ret = aesni_mb_set_session_cipher_parameters(internals->mb_mgr,
+ aesni_sess, cipher_xform);
+
+ if (ret != 0) {
+ AESNI_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif
+