@@ -41,16 +41,21 @@ static int chap_gen_challenge(
unsigned int *c_len)
{
int ret;
- unsigned char challenge_asciihex[CHAP_CHALLENGE_LENGTH * 2 + 1];
+ unsigned char *challenge_asciihex;
struct iscsi_chap *chap = conn->auth_protocol;
- memset(challenge_asciihex, 0, CHAP_CHALLENGE_LENGTH * 2 + 1);
+ challenge_asciihex = kzalloc(chap->challenge_len * 2 + 1, GFP_KERNEL);
+ if (!challenge_asciihex)
+ return -ENOMEM;
- ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
+ memset(chap->challenge, 0, MAX_CHAP_CHALLENGE_LEN);
+
+ ret = get_random_bytes_wait(chap->challenge, chap->challenge_len);
if (unlikely(ret))
- return ret;
+ goto out;
+
bin2hex(challenge_asciihex, chap->challenge,
- CHAP_CHALLENGE_LENGTH);
+ chap->challenge_len);
/*
* Set CHAP_C, and copy the generated challenge into c_str.
*/
@@ -59,7 +64,10 @@ static int chap_gen_challenge(
pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
challenge_asciihex);
- return 0;
+
+out:
+ kfree(challenge_asciihex);
+ return ret;
}
static int chap_test_algorithm(const char *name)
@@ -171,6 +179,9 @@ static struct iscsi_chap *chap_server_open(
chap->digest_name = chap_get_digest_name(digest_type);
+ /* Tie the challenge length to the digest size */
+ chap->challenge_len = chap->digest_size;
+
pr_debug("[server] Got CHAP_A=%d\n", digest_type);
*aic_len = sprintf(aic_str, "CHAP_A=%d", digest_type);
*aic_len += 1;
@@ -334,21 +345,23 @@ static int chap_server_compute_hash(
}
ret = crypto_shash_finup(desc, chap->challenge,
- CHAP_CHALLENGE_LENGTH, server_digest);
+ chap->challenge_len, server_digest);
if (ret < 0) {
pr_err("crypto_shash_finup() failed for challenge\n");
goto out;
}
bin2hex(response, server_digest, chap->digest_size);
- pr_debug("[server] %s Server Digest: %s\n", hash_name, response);
+ pr_debug("[server] %s Server Digest: %s\n",
+ chap->digest_name, response);
if (memcmp(server_digest, client_digest, chap->digest_size) != 0) {
- pr_debug("[server] %s Digests do not match!\n\n", hash_name);
+ pr_debug("[server] %s Digests do not match!\n\n",
+ chap->digest_name);
goto out;
} else
pr_debug("[server] %s Digests match, CHAP connection"
- " successful.\n\n", hash_name);
+ " successful.\n\n", chap->digest_name);
/*
* One way authentication has succeeded, return now if mutual
* authentication is not enabled.
@@ -414,7 +427,9 @@ static int chap_server_compute_hash(
* initiator must not match the original CHAP_C generated by
* the target.
*/
- if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) {
+ if (challenge_len == chap->challenge_len &&
+ !memcmp(challenge_binhex, chap->challenge,
+ challenge_len)) {
pr_err("initiator CHAP_C matches target CHAP_C, failing"
" login attempt\n");
goto out;
@@ -10,7 +10,7 @@
#define CHAP_DIGEST_SHA256 7
#define CHAP_DIGEST_SHA3_256 8
-#define CHAP_CHALLENGE_LENGTH 16
+#define MAX_CHAP_CHALLENGE_LEN 32
#define CHAP_CHALLENGE_STR_LEN 4096
#define MAX_RESPONSE_LENGTH 128 /* sufficient for SHA3 256 */
#define MAX_CHAP_N_SIZE 512
@@ -34,7 +34,7 @@ extern u32 chap_main_loop(struct iscsi_conn *, struct iscsi_node_auth *, char *,
struct iscsi_chap {
unsigned char id;
- unsigned char challenge[CHAP_CHALLENGE_LENGTH];
+ unsigned char challenge[MAX_CHAP_CHALLENGE_LEN];
unsigned int challenge_len;
unsigned char *digest_name;
unsigned int digest_size;
The open-iscsi initiator uses the digest size to determine the length of the challenge values it sends to the target. This patch modifies the target driver to behave in the same way. Signed-off-by: Maurizio Lombardi <mlombard@redhat.com> --- drivers/target/iscsi/iscsi_target_auth.c | 37 +++++++++++++++++------- drivers/target/iscsi/iscsi_target_auth.h | 4 +-- 2 files changed, 28 insertions(+), 13 deletions(-)