net/rxrpc: Use local FCrypt-PCBC implementation

Use the local implementation of FCrypt-PCBC instead of the crypto API
one.  This will allow the crypto API one to be removed.  It also
simplifies the code quite a bit.

The local FCrypt-PCBC implementation is also significantly faster than
the crypto API one, since the crypto API one had a lot of overhead.  For
example, benchmarking on an x86_64 CPU, I see that FCrypt-PCBC
decryption throughput improved from 83 MB/s to 157 MB/s.

(Meanwhile, AES-256-GCM decryption is 8064 MB/s on the same CPU.
Clearly, anyone looking for good performance, or anything that is
actually secure for that matter, needs to look elsewhere anyway.)

Acked-by: David Howells <dhowells@redhat.com>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Tested-by: Marc Dionne <marc.dionne@auristor.com>
Link: https://patch.msgid.link/20260522050740.84561-3-ebiggers@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Biggers 2026-05-22 00:07:33 -05:00 committed by Jakub Kicinski
parent f10e73dffd
commit 97b768514a
3 changed files with 76 additions and 280 deletions

View File

@ -60,7 +60,6 @@ config RXKAD
select CRYPTO_MANAGER
select CRYPTO_SKCIPHER
select CRYPTO_PCBC
select CRYPTO_FCRYPT
help
Provide kerberos 4 and AFS kaserver security handling for AF_RXRPC
through the use of the key retention service.

View File

@ -577,7 +577,7 @@ struct rxrpc_connection {
const struct rxrpc_security *security; /* applied security module */
union {
struct {
struct crypto_sync_skcipher *cipher; /* encryption handle */
struct fcrypt_key *cipher; /* encryption key */
struct rxrpc_crypt csum_iv; /* packet checksum base */
u32 nonce; /* response re-use preventer */
} rxkad;

View File

@ -8,6 +8,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <crypto/skcipher.h>
#include <linux/fips.h>
#include <linux/module.h>
#include <linux/net.h>
#include <linux/skbuff.h>
@ -30,6 +31,8 @@
#define SNAME_SZ 40 /* size of service name */
#define RXKAD_ALIGN 8
static const u8 zero_iv[FCRYPT_BSIZE];
struct rxkad_level1_hdr {
__be32 data_size; /* true data size (excluding padding) */
};
@ -39,17 +42,8 @@ struct rxkad_level2_hdr {
__be32 checksum; /* decrypted data checksum */
};
static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
struct crypto_sync_skcipher *ci);
/*
* this holds a pinned cipher so that keventd doesn't get called by the cipher
* alloc routine, but since we have it to hand, we use it to decrypt RESPONSE
* packets
*/
static struct crypto_sync_skcipher *rxkad_ci;
static struct skcipher_request *rxkad_ci_req;
static DEFINE_MUTEX(rxkad_ci_mutex);
static void rxkad_prime_packet_security(struct rxrpc_connection *conn,
const struct fcrypt_key *cipher);
/*
* Parse the information from a server key
@ -100,23 +94,19 @@ static void rxkad_destroy_server_key(struct key *key)
static int rxkad_init_connection_security(struct rxrpc_connection *conn,
struct rxrpc_key_token *token)
{
struct crypto_sync_skcipher *ci;
struct fcrypt_key *ci;
int ret;
_enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
conn->security_ix = token->security_index;
ci = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
if (IS_ERR(ci)) {
_debug("no cipher");
ret = PTR_ERR(ci);
ci = kmalloc_obj(*ci);
if (!ci) {
ret = -ENOMEM;
goto error;
}
if (crypto_sync_skcipher_setkey(ci, token->kad->session_key,
sizeof(token->kad->session_key)) < 0)
BUG();
fcrypt_preparekey(ci, token->kad->session_key);
switch (conn->security_level) {
case RXRPC_SECURITY_PLAIN:
@ -125,18 +115,16 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn,
break;
default:
ret = -EKEYREJECTED;
goto error;
goto error_ci;
}
ret = rxkad_prime_packet_security(conn, ci);
if (ret < 0)
goto error_ci;
rxkad_prime_packet_security(conn, ci);
conn->rxkad.cipher = ci;
return 0;
error_ci:
crypto_free_sync_skcipher(ci);
kfree_sensitive(ci);
error:
_leave(" = %d", ret);
return ret;
@ -188,62 +176,28 @@ static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t rem
* prime the encryption state with the invariant parts of a connection's
* description
*/
static int rxkad_prime_packet_security(struct rxrpc_connection *conn,
struct crypto_sync_skcipher *ci)
static void rxkad_prime_packet_security(struct rxrpc_connection *conn,
const struct fcrypt_key *cipher)
{
struct skcipher_request *req;
struct rxrpc_key_token *token;
struct scatterlist sg;
struct rxrpc_crypt iv;
__be32 *tmpbuf;
size_t tmpsize = 4 * sizeof(__be32);
int ret;
__be32 tmpbuf[4];
_enter("");
if (!conn->key)
return 0;
tmpbuf = kmalloc(tmpsize, GFP_KERNEL);
if (!tmpbuf)
return -ENOMEM;
req = skcipher_request_alloc(&ci->base, GFP_NOFS);
if (!req) {
kfree(tmpbuf);
return -ENOMEM;
}
return;
token = conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv));
tmpbuf[0] = htonl(conn->proto.epoch);
tmpbuf[1] = htonl(conn->proto.cid);
tmpbuf[2] = 0;
tmpbuf[3] = htonl(conn->security_ix);
sg_init_one(&sg, tmpbuf, tmpsize);
skcipher_request_set_sync_tfm(req, ci);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, tmpsize, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_free(req);
memcpy(&conn->rxkad.csum_iv, tmpbuf + 2, sizeof(conn->rxkad.csum_iv));
kfree(tmpbuf);
_leave(" = %d", ret);
return ret;
}
/*
* Allocate and prepare the crypto request on a call. For any particular call,
* this is called serially for the packets, so no lock should be necessary.
*/
static struct skcipher_request *rxkad_get_call_crypto(struct rxrpc_call *call)
{
struct crypto_skcipher *tfm = &call->conn->rxkad.cipher->base;
return skcipher_request_alloc(tfm, GFP_NOFS);
static_assert(sizeof(tmpbuf) % FCRYPT_BSIZE == 0);
fcrypt_pcbc_encrypt(cipher, /* iv= */ token->kad->session_key, tmpbuf,
tmpbuf, sizeof(tmpbuf) / FCRYPT_BSIZE);
memcpy(&conn->rxkad.csum_iv, &tmpbuf[2], sizeof(conn->rxkad.csum_iv));
_leave("");
}
/*
@ -256,16 +210,12 @@ static void rxkad_free_call_crypto(struct rxrpc_call *call)
/*
* partially encrypt a packet (level 1 security)
*/
static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
struct rxrpc_txbuf *txb,
struct skcipher_request *req)
static void rxkad_secure_packet_auth(const struct rxrpc_call *call,
struct rxrpc_txbuf *txb)
{
struct rxkad_level1_hdr *hdr = txb->data;
struct rxrpc_crypt iv;
struct scatterlist sg;
size_t pad;
u16 check;
int ret;
_enter("");
@ -282,33 +232,20 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
}
/* start the encryption afresh */
memset(&iv, 0, sizeof(iv));
sg_init_one(&sg, hdr, 8);
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
_leave(" = %d", ret);
return ret;
fcrypt_pcbc_encrypt(call->conn->rxkad.cipher, zero_iv, hdr, hdr, 1);
_leave("");
}
/*
* wholly encrypt a packet (level 2 security)
*/
static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
struct rxrpc_txbuf *txb,
struct skcipher_request *req)
static void rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
struct rxrpc_txbuf *txb)
{
const struct rxrpc_key_token *token;
struct rxkad_level2_hdr *rxkhdr = txb->data;
struct rxrpc_crypt iv;
struct scatterlist sg;
size_t content, pad;
u16 check;
int ret;
_enter("");
@ -318,22 +255,18 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
rxkhdr->checksum = 0;
content = sizeof(struct rxkad_level2_hdr) + txb->len;
static_assert(RXKAD_ALIGN == FCRYPT_BSIZE);
txb->pkt_len = round_up(content, RXKAD_ALIGN);
pad = txb->pkt_len - content;
if (pad)
memset(txb->data + txb->offset, 0, pad);
/* Now txb->pkt_len % FCRYPT_BSIZE == 0. */
/* encrypt from the session key */
token = call->conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv));
sg_init_one(&sg, rxkhdr, txb->pkt_len);
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, txb->pkt_len, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
return ret;
fcrypt_pcbc_encrypt(call->conn->rxkad.cipher, token->kad->session_key,
rxkhdr, rxkhdr, txb->pkt_len / FCRYPT_BSIZE);
_leave("");
}
/*
@ -341,9 +274,6 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
*/
static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
{
struct skcipher_request *req;
struct rxrpc_crypt iv;
struct scatterlist sg;
union {
__be32 buf[2];
} crypto __aligned(8);
@ -361,27 +291,16 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
if (ret < 0)
return ret;
req = rxkad_get_call_crypto(call);
if (!req)
return -ENOMEM;
/* continue encrypting from where we left off */
memcpy(&iv, call->conn->rxkad.csum_iv.x, sizeof(iv));
/* calculate the security checksum */
x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
x |= txb->seq & 0x3fffffff;
crypto.buf[0] = htonl(call->call_id);
crypto.buf[1] = htonl(x);
sg_init_one(&sg, crypto.buf, 8);
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
if (ret < 0)
goto out;
/* continue encrypting from where we left off */
fcrypt_pcbc_encrypt(call->conn->rxkad.cipher,
call->conn->rxkad.csum_iv.x, crypto.buf, crypto.buf,
1);
y = ntohl(crypto.buf[1]);
y = (y >> 16) & 0xffff;
@ -395,14 +314,16 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
ret = 0;
break;
case RXRPC_SECURITY_AUTH:
ret = rxkad_secure_packet_auth(call, txb, req);
rxkad_secure_packet_auth(call, txb);
if (txb->alloc_size == RXRPC_JUMBO_DATALEN)
txb->jumboable = true;
ret = 0;
break;
case RXRPC_SECURITY_ENCRYPT:
ret = rxkad_secure_packet_encrypt(call, txb, req);
rxkad_secure_packet_encrypt(call, txb);
if (txb->alloc_size == RXRPC_JUMBO_DATALEN)
txb->jumboable = true;
ret = 0;
break;
default:
ret = -EPERM;
@ -417,8 +338,6 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
memset(p + txb->pkt_len, 0, gap);
}
out:
skcipher_request_free(req);
_leave(" = %d [set %x]", ret, y);
return ret;
}
@ -427,17 +346,13 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
* decrypt partial encryption on a packet (level 1 security)
*/
static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
rxrpc_seq_t seq,
struct skcipher_request *req)
rxrpc_seq_t seq)
{
struct rxkad_level1_hdr *sechdr;
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_crypt iv;
struct scatterlist sg[1];
void *data = call->rx_dec_buffer;
u32 len = sp->len, data_size, buf;
u16 check;
int ret;
_enter("");
@ -445,21 +360,8 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON,
rxkad_abort_1_short_header);
/* Decrypt the skbuff in-place. TODO: We really want to decrypt
* directly into the target buffer.
*/
sg_init_one(sg, data, len);
/* start the decryption afresh */
memset(&iv, 0, sizeof(iv));
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, 8, iv.x);
ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
if (ret < 0)
return ret;
/* Decrypt the first 8-byte block of the packet, using the zero IV. */
fcrypt_pcbc_decrypt(call->conn->rxkad.cipher, zero_iv, data, data, 1);
/* Extract the decrypted packet length */
sechdr = data;
@ -488,18 +390,14 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
* wholly decrypt a packet (level 2 security)
*/
static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
rxrpc_seq_t seq,
struct skcipher_request *req)
rxrpc_seq_t seq)
{
const struct rxrpc_key_token *token;
struct rxkad_level2_hdr *sechdr;
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_crypt iv;
struct scatterlist sg[1];
void *data = call->rx_dec_buffer;
u32 len = sp->len, data_size, buf;
u16 check;
int ret;
_enter(",{%d}", len);
@ -510,26 +408,10 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
/* Don't let the crypto algo see a misaligned length. */
len = round_down(len, 8);
/* Decrypt in place in the call's decryption buffer. TODO: We really
* want to decrypt directly into the target buffer.
*/
sg_init_one(sg, data, len);
/* decrypt from the session key */
token = call->conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv));
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, len, iv.x);
ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
if (ret < 0) {
if (ret == -ENOMEM)
return ret;
return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON,
rxkad_abort_2_crypto_unaligned);
}
fcrypt_pcbc_decrypt(call->conn->rxkad.cipher, token->kad->session_key,
data, data, len / FCRYPT_BSIZE);
/* Extract the decrypted packet length */
sechdr = data;
@ -562,9 +444,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct skcipher_request *req;
struct rxrpc_crypt iv;
struct scatterlist sg;
union {
__be32 buf[2];
} crypto __aligned(8);
@ -579,27 +458,16 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)
if (!call->conn->rxkad.cipher)
return 0;
req = rxkad_get_call_crypto(call);
if (!req)
return -ENOMEM;
/* continue encrypting from where we left off */
memcpy(&iv, call->conn->rxkad.csum_iv.x, sizeof(iv));
/* validate the security checksum */
x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
x |= seq & 0x3fffffff;
crypto.buf[0] = htonl(call->call_id);
crypto.buf[1] = htonl(x);
sg_init_one(&sg, crypto.buf, 8);
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sg, &sg, 8, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
if (ret < 0)
goto out;
/* continue encrypting from where we left off */
fcrypt_pcbc_encrypt(call->conn->rxkad.cipher,
call->conn->rxkad.csum_iv.x, crypto.buf, crypto.buf,
1);
y = ntohl(crypto.buf[1]);
cksum = (y >> 16) & 0xffff;
@ -617,18 +485,16 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb)
ret = 0;
break;
case RXRPC_SECURITY_AUTH:
ret = rxkad_verify_packet_1(call, skb, seq, req);
ret = rxkad_verify_packet_1(call, skb, seq);
break;
case RXRPC_SECURITY_ENCRYPT:
ret = rxkad_verify_packet_2(call, skb, seq, req);
ret = rxkad_verify_packet_2(call, skb, seq);
break;
default:
ret = -ENOANO;
break;
}
out:
skcipher_request_free(req);
return ret;
}
@ -712,41 +578,6 @@ static void rxkad_calc_response_checksum(struct rxkad_response *response)
response->encrypted.checksum = htonl(csum);
}
/*
* encrypt the response packet
*/
static int rxkad_encrypt_response(struct rxrpc_connection *conn,
struct sk_buff *response,
const struct rxkad_key *s2)
{
struct skcipher_request *req;
struct rxrpc_crypt iv;
struct scatterlist sg[1];
size_t encsize = sizeof(((struct rxkad_response *)0)->encrypted);
int ret;
sg_init_table(sg, ARRAY_SIZE(sg));
ret = skb_to_sgvec(response, sg,
sizeof(struct rxrpc_wire_header) +
offsetof(struct rxkad_response, encrypted), encsize);
if (ret < 0)
return ret;
req = skcipher_request_alloc(&conn->rxkad.cipher->base, GFP_NOFS);
if (!req)
return -ENOMEM;
/* continue encrypting from where we left off */
memcpy(&iv, s2->session_key, sizeof(iv));
skcipher_request_set_sync_tfm(req, conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, encsize, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_free(req);
return ret;
}
/*
* Validate a challenge packet.
*/
@ -846,6 +677,12 @@ int rxkad_insert_response_header(struct rxrpc_connection *conn,
rxkad_calc_response_checksum(&h.resp);
/* encrypt the response packet */
static_assert(sizeof(h.resp.encrypted) % FCRYPT_BSIZE == 0);
fcrypt_pcbc_encrypt(conn->rxkad.cipher, token->kad->session_key,
&h.resp.encrypted, &h.resp.encrypted,
sizeof(h.resp.encrypted) / FCRYPT_BSIZE);
ret = skb_store_bits(response, *offset, &h, sizeof(h));
*offset += sizeof(h);
return ret;
@ -890,10 +727,6 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
if (ret < 0)
goto error;
ret = rxkad_encrypt_response(conn, response, token->kad);
if (ret < 0)
goto error;
ret = skb_store_bits(response, offset, token->kad->ticket,
token->kad->ticket_len);
if (ret < 0)
@ -1072,39 +905,22 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
/*
* decrypt the response packet
*/
static int rxkad_decrypt_response(struct rxrpc_connection *conn,
struct rxkad_response *resp,
const struct rxrpc_crypt *session_key)
static void rxkad_decrypt_response(struct rxrpc_connection *conn,
struct rxkad_response *resp,
const struct rxrpc_crypt *session_key)
{
struct skcipher_request *req = rxkad_ci_req;
struct scatterlist sg[1];
struct rxrpc_crypt iv;
int ret;
struct fcrypt_key cipher;
_enter(",,%08x%08x",
ntohl(session_key->n[0]), ntohl(session_key->n[1]));
mutex_lock(&rxkad_ci_mutex);
ret = crypto_sync_skcipher_setkey(rxkad_ci, session_key->x,
sizeof(*session_key));
if (ret < 0)
goto unlock;
memcpy(&iv, session_key, sizeof(iv));
sg_init_table(sg, 1);
sg_set_buf(sg, &resp->encrypted, sizeof(resp->encrypted));
skcipher_request_set_sync_tfm(req, rxkad_ci);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, sg, sg, sizeof(resp->encrypted), iv.x);
ret = crypto_skcipher_decrypt(req);
skcipher_request_zero(req);
unlock:
mutex_unlock(&rxkad_ci_mutex);
fcrypt_preparekey(&cipher, session_key->x);
static_assert(sizeof(resp->encrypted) % FCRYPT_BSIZE == 0);
fcrypt_pcbc_decrypt(&cipher, session_key->x, &resp->encrypted,
&resp->encrypted,
sizeof(resp->encrypted) / FCRYPT_BSIZE);
_leave("");
return ret;
}
/*
@ -1191,9 +1007,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
/* use the session key from inside the ticket to decrypt the
* response */
ret = rxkad_decrypt_response(conn, response, &session_key);
if (ret < 0)
goto error;
rxkad_decrypt_response(conn, response, &session_key);
if (ntohl(response->encrypted.epoch) != conn->proto.epoch ||
ntohl(response->encrypted.cid) != conn->proto.cid ||
@ -1270,8 +1084,8 @@ static void rxkad_clear(struct rxrpc_connection *conn)
{
_enter("");
if (conn->rxkad.cipher)
crypto_free_sync_skcipher(conn->rxkad.cipher);
kfree_sensitive(conn->rxkad.cipher);
conn->rxkad.cipher = NULL;
}
/*
@ -1279,26 +1093,11 @@ static void rxkad_clear(struct rxrpc_connection *conn)
*/
static int rxkad_init(void)
{
struct crypto_sync_skcipher *tfm;
struct skcipher_request *req;
/* pin the cipher we need so that the crypto layer doesn't invoke
* keventd to go get it */
tfm = crypto_alloc_sync_skcipher("pcbc(fcrypt)", 0, 0);
if (IS_ERR(tfm))
return PTR_ERR(tfm);
req = skcipher_request_alloc(&tfm->base, GFP_KERNEL);
if (!req)
goto nomem_tfm;
rxkad_ci_req = req;
rxkad_ci = tfm;
if (fips_enabled) {
pr_warn("rxkad support is disabled due to FIPS\n");
return -ENOENT;
}
return 0;
nomem_tfm:
crypto_free_sync_skcipher(tfm);
return -ENOMEM;
}
/*
@ -1306,8 +1105,6 @@ static int rxkad_init(void)
*/
static void rxkad_exit(void)
{
crypto_free_sync_skcipher(rxkad_ci);
skcipher_request_free(rxkad_ci_req);
}
/*