From: Eric Biggers <ebiggers@kernel.org>
To: linux-scsi@vger.kernel.org, target-devel@vger.kernel.org,
"Martin K . Petersen" <mkp@kernel.org>
Cc: linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
David Disseldorp <ddiss@suse.de>, Lee Duncan <lduncan@suse.com>,
Alexandru Hossu <hossu.alexandru@gmail.com>,
Eric Biggers <ebiggers@kernel.org>
Subject: [PATCH] scsi: target: iscsi: Use crypto library API
Date: Wed, 30 Sep 2026 21:48:57 -0700 [thread overview]
Message-ID: <20261001044857.169487-1-ebiggers@kernel.org> (raw)
Make iscsi_target_auth.c call into the crypto library directly instead
of going through crypto_shash. This is simpler and much more efficient,
as it avoids overhead of the crypto_shash layer. The hash computation
itself also no longer has error codes that need to be checked.
For simplicity, still do a memory allocation per operation to buffer the
data (which is typically less than 50 bytes here) so that the one-shot
digest functions can be used. It's still much more efficient than doing
the super slow crypto_alloc_shash().
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
---
drivers/target/iscsi/Kconfig | 7 +-
drivers/target/iscsi/iscsi_target_auth.c | 192 +++++++++--------------
drivers/target/iscsi/iscsi_target_auth.h | 8 +-
3 files changed, 78 insertions(+), 129 deletions(-)
diff --git a/drivers/target/iscsi/Kconfig b/drivers/target/iscsi/Kconfig
index 70d76f3dd693..44bbf1f32859 100644
--- a/drivers/target/iscsi/Kconfig
+++ b/drivers/target/iscsi/Kconfig
@@ -3,8 +3,11 @@ config ISCSI_TARGET
tristate "SCSI Target Mode Stack"
depends on INET
select CRC32
- select CRYPTO
- select CRYPTO_HASH
+ select CRYPTO_LIB_MD5
+ select CRYPTO_LIB_SHA1
+ select CRYPTO_LIB_SHA256
+ select CRYPTO_LIB_SHA3
+ select CRYPTO_LIB_UTILS
help
Say M to enable the SCSI target mode stack. A SCSI target mode stack
is software that makes local storage available over a storage network
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index f3c0cdd31830..945dd6409723 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -8,31 +8,73 @@
*
******************************************************************************/
-#include <crypto/hash.h>
+#include <crypto/md5.h>
+#include <crypto/sha1.h>
+#include <crypto/sha2.h>
+#include <crypto/sha3.h>
#include <crypto/utils.h>
+#include <linux/fips.h>
#include <linux/kernel.h>
#include <linux/string.h>
-#include <linux/err.h>
#include <linux/hex.h>
#include <linux/random.h>
-#include <linux/scatterlist.h>
+#include <linux/slab.h>
#include <target/iscsi/iscsi_target_core.h>
#include "iscsi_target_nego.h"
#include "iscsi_target_auth.h"
-static char *chap_get_digest_name(const int digest_type)
+static const struct {
+ const char *digest_name; /* Used only in log messages */
+ unsigned int digest_size;
+} chap_digest_algs[] = {
+ [CHAP_DIGEST_MD5] = {
+ .digest_name = "md5",
+ .digest_size = MD5_DIGEST_SIZE,
+ },
+ [CHAP_DIGEST_SHA1] = {
+ .digest_name = "sha1",
+ .digest_size = SHA1_DIGEST_SIZE,
+ },
+ [CHAP_DIGEST_SHA256] = {
+ .digest_name = "sha256",
+ .digest_size = SHA256_DIGEST_SIZE,
+ },
+ [CHAP_DIGEST_SHA3_256] = {
+ .digest_name = "sha3-256",
+ .digest_size = SHA3_256_DIGEST_SIZE,
+ },
+};
+
+static int chap_digest(int digest_type, u8 chap_id, const char *password,
+ const u8 *challenge, size_t challenge_len,
+ u8 *out_digest)
{
+ size_t pass_len = strlen(password);
+ size_t data_len = 1 + pass_len + challenge_len;
+ u8 *data __free(kfree_sensitive) = kmalloc(data_len, GFP_KERNEL);
+
+ if (!data)
+ return -ENOMEM;
+ data[0] = chap_id;
+ memcpy(&data[1], password, pass_len);
+ memcpy(&data[1 + pass_len], challenge, challenge_len);
+
switch (digest_type) {
case CHAP_DIGEST_MD5:
- return "md5";
+ md5(data, data_len, out_digest);
+ return 0;
case CHAP_DIGEST_SHA1:
- return "sha1";
+ sha1(data, data_len, out_digest);
+ return 0;
case CHAP_DIGEST_SHA256:
- return "sha256";
+ sha256(data, data_len, out_digest);
+ return 0;
case CHAP_DIGEST_SHA3_256:
- return "sha3-256";
+ sha3_256(data, data_len, out_digest);
+ return 0;
default:
- return NULL;
+ WARN_ON_ONCE(1);
+ return -EINVAL;
}
}
@@ -72,21 +114,9 @@ static int chap_gen_challenge(
return ret;
}
-static int chap_test_algorithm(const char *name)
-{
- struct crypto_shash *tfm;
-
- tfm = crypto_alloc_shash(name, 0, 0);
- if (IS_ERR(tfm))
- return -1;
-
- crypto_free_shash(tfm);
- return 0;
-}
-
static int chap_check_algorithm(const char *a_str)
{
- char *tmp, *orig, *token, *digest_name;
+ char *tmp, *orig, *token;
long digest_type;
int r = CHAP_DIGEST_UNKNOWN;
@@ -113,17 +143,17 @@ static int chap_check_algorithm(const char *a_str)
if (kstrtol(token, 10, &digest_type))
continue;
- digest_name = chap_get_digest_name(digest_type);
- if (!digest_name)
+ if (fips_enabled && digest_type == CHAP_DIGEST_MD5)
continue;
- pr_debug("Selected %s Algorithm\n", digest_name);
- if (chap_test_algorithm(digest_name) < 0) {
- pr_err("failed to allocate %s algo\n", digest_name);
- } else {
- r = digest_type;
- goto out;
- }
+ if (digest_type < 0 ||
+ digest_type >= ARRAY_SIZE(chap_digest_algs) ||
+ chap_digest_algs[digest_type].digest_name == NULL)
+ continue;
+ pr_debug("Selected %s Algorithm\n",
+ chap_digest_algs[digest_type].digest_name);
+ r = digest_type;
+ goto out;
}
out:
kfree(orig);
@@ -159,27 +189,15 @@ static struct iscsi_chap *chap_server_open(
chap = conn->auth_protocol;
digest_type = chap_check_algorithm(a_str);
- switch (digest_type) {
- case CHAP_DIGEST_MD5:
- chap->digest_size = MD5_SIGNATURE_SIZE;
- break;
- case CHAP_DIGEST_SHA1:
- chap->digest_size = SHA1_SIGNATURE_SIZE;
- break;
- case CHAP_DIGEST_SHA256:
- chap->digest_size = SHA256_SIGNATURE_SIZE;
- break;
- case CHAP_DIGEST_SHA3_256:
- chap->digest_size = SHA3_256_SIGNATURE_SIZE;
- break;
- case CHAP_DIGEST_UNKNOWN:
- default:
+ if (digest_type == CHAP_DIGEST_UNKNOWN) {
pr_err("Unsupported CHAP_A value\n");
chap_close(conn);
return NULL;
}
- chap->digest_name = chap_get_digest_name(digest_type);
+ chap->digest_name = chap_digest_algs[digest_type].digest_name;
+ chap->digest_type = digest_type;
+ chap->digest_size = chap_digest_algs[digest_type].digest_size;
/* Tie the challenge length to the digest size */
chap->challenge_len = chap->digest_size;
@@ -247,7 +265,6 @@ static int chap_server_compute_hash(
unsigned int *nr_out_len)
{
unsigned long id;
- unsigned char id_as_uchar;
unsigned char type;
unsigned char identifier[10], *initiatorchg = NULL;
unsigned char *initiatorchg_binhex = NULL;
@@ -258,8 +275,6 @@ static int chap_server_compute_hash(
unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
size_t compare_len;
struct iscsi_chap *chap = conn->auth_protocol;
- struct crypto_shash *tfm = NULL;
- struct shash_desc *desc = NULL;
int auth_ret = -1, ret, initiatorchg_len;
digest = kzalloc(chap->digest_size, GFP_KERNEL);
@@ -364,44 +379,10 @@ static int chap_server_compute_hash(
pr_debug("[server] Got CHAP_R=%s\n", chap_r);
- tfm = crypto_alloc_shash(chap->digest_name, 0, 0);
- if (IS_ERR(tfm)) {
- tfm = NULL;
- pr_err("Unable to allocate struct crypto_shash\n");
- goto out;
- }
-
- desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
- if (!desc) {
- pr_err("Unable to allocate struct shash_desc\n");
- goto out;
- }
-
- desc->tfm = tfm;
-
- ret = crypto_shash_init(desc);
- if (ret < 0) {
- pr_err("crypto_shash_init() failed\n");
- goto out;
- }
-
- ret = crypto_shash_update(desc, &chap->id, 1);
- if (ret < 0) {
- pr_err("crypto_shash_update() failed for id\n");
- goto out;
- }
-
- ret = crypto_shash_update(desc, (char *)&auth->password,
- strlen(auth->password));
- if (ret < 0) {
- pr_err("crypto_shash_update() failed for password\n");
- goto out;
- }
-
- ret = crypto_shash_finup(desc, chap->challenge,
- chap->challenge_len, server_digest);
+ ret = chap_digest(chap->digest_type, chap->id, auth->password,
+ chap->challenge, chap->challenge_len, server_digest);
if (ret < 0) {
- pr_err("crypto_shash_finup() failed for challenge\n");
+ pr_err("chap_digest() failed\n");
goto out;
}
@@ -530,40 +511,12 @@ static int chap_server_compute_hash(
/*
* Generate CHAP_N and CHAP_R for mutual authentication.
*/
- ret = crypto_shash_init(desc);
+ ret = chap_digest(chap->digest_type, id, auth->password_mutual,
+ initiatorchg_binhex, initiatorchg_len, digest);
if (ret < 0) {
- pr_err("crypto_shash_init() failed\n");
+ pr_err("chap_digest() failed\n");
goto out;
}
-
- /* To handle both endiannesses */
- id_as_uchar = id;
- ret = crypto_shash_update(desc, &id_as_uchar, 1);
- if (ret < 0) {
- pr_err("crypto_shash_update() failed for id\n");
- goto out;
- }
-
- ret = crypto_shash_update(desc, auth->password_mutual,
- strlen(auth->password_mutual));
- if (ret < 0) {
- pr_err("crypto_shash_update() failed for"
- " password_mutual\n");
- goto out;
- }
- /*
- * Convert received challenge to binary hex.
- */
- ret = crypto_shash_finup(desc, initiatorchg_binhex, initiatorchg_len,
- digest);
- if (ret < 0) {
- pr_err("crypto_shash_finup() failed for ma challenge\n");
- goto out;
- }
-
- /*
- * Generate CHAP_N and CHAP_R.
- */
*nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual);
*nr_out_len += 1;
pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual);
@@ -577,9 +530,6 @@ static int chap_server_compute_hash(
pr_debug("[server] Sending CHAP_R=0x%s\n", response);
auth_ret = 0;
out:
- kfree_sensitive(desc);
- if (tfm)
- crypto_free_shash(tfm);
kfree(initiatorchg);
kfree(initiatorchg_binhex);
kfree(digest);
diff --git a/drivers/target/iscsi/iscsi_target_auth.h b/drivers/target/iscsi/iscsi_target_auth.h
index ceb9b7754770..7ed288936af2 100644
--- a/drivers/target/iscsi/iscsi_target_auth.h
+++ b/drivers/target/iscsi/iscsi_target_auth.h
@@ -15,11 +15,6 @@
#define MAX_RESPONSE_LENGTH 128 /* sufficient for SHA3 256 */
#define MAX_CHAP_N_SIZE 512
-#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
-#define SHA1_SIGNATURE_SIZE 20 /* 20 bytes in a SHA1 message digest */
-#define SHA256_SIGNATURE_SIZE 32 /* 32 bytes in a SHA256 message digest */
-#define SHA3_256_SIGNATURE_SIZE 32 /* 32 bytes in a SHA3 256 message digest */
-
#define CHAP_STAGE_CLIENT_A 1
#define CHAP_STAGE_SERVER_AIC 2
#define CHAP_STAGE_CLIENT_NR 3
@@ -36,7 +31,8 @@ struct iscsi_chap {
unsigned char id;
unsigned char challenge[MAX_CHAP_CHALLENGE_LEN];
unsigned int challenge_len;
- unsigned char *digest_name;
+ const char *digest_name;
+ int digest_type;
unsigned int digest_size;
unsigned int authenticate_target;
unsigned int chap_state;
base-commit: 551c722f40809618230001baccf219193e22fc5a
--
2.56.0
next reply other threads:[~2026-10-01 4:53 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-01 4:48 Eric Biggers [this message]
2026-10-11 12:36 ` [PATCH] scsi: target: iscsi: Use crypto library API David Disseldorp
2026-10-11 19:12 ` Eric Biggers
2026-10-12 1:46 ` David Disseldorp
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261001044857.169487-1-ebiggers@kernel.org \
--to=ebiggers@kernel.org \
--cc=ddiss@suse.de \
--cc=hossu.alexandru@gmail.com \
--cc=lduncan@suse.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=mkp@kernel.org \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.