* [PATCH] scsi: target: iscsi: Use crypto library API
@ 2026-10-01 4:48 Eric Biggers
0 siblings, 0 replies; only message in thread
From: Eric Biggers @ 2026-10-01 4:48 UTC (permalink / raw)
To: linux-scsi, target-devel, Martin K . Petersen
Cc: linux-crypto, linux-kernel, David Disseldorp, Lee Duncan,
Alexandru Hossu, Eric Biggers
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-10-01 4:53 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 4:48 [PATCH] scsi: target: iscsi: Use crypto library API Eric Biggers
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®