Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iscsi-scst: Add SHA256 and SHA3-256 support to CHAP #277

Merged
merged 1 commit into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion iscsi-scst/usr/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ cc-option = $(shell if $(CC) $(1) -Werror -S -o /dev/null -xc /dev/null \

SRCS_D = iscsid.c iscsi_scstd.c conn.c session.c target.c message.c ctldev.c \
log.c chap.c event.c param.c config.c isns.c md5.c sha1.c \
misc.c
misc.c af_alg.c
OBJS_D = $(SRCS_D:.c=.o)

SRCS_ADM = iscsi_adm.c param.c
Expand Down
84 changes: 84 additions & 0 deletions iscsi-scst/usr/af_alg.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* af_alg - wrapper functions to call AF_ALG hash algorithms.
*
* Copyright (C) 2025 Brian Meagher <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#include "af_alg.h"

#include <sys/socket.h>
#include <linux/if_alg.h>
#include <string.h>
#include <sys/param.h>
#include <stdbool.h>

int af_alg_init(const char *algorithm)
{
int sockfd, datafd, algo_len;
struct sockaddr_alg sa = {
.salg_family = AF_ALG,
.salg_type = "hash",
};

algo_len = strlen(algorithm);
if (algo_len >= sizeof(sa.salg_name))
return -1;

sockfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
if (sockfd == -1)
return -1;

/* +1 for null-terminator */
memcpy(sa.salg_name, algorithm, algo_len + 1);

if (bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
close(sockfd);
return -1;
}

datafd = accept(sockfd, NULL, 0);
if (datafd < 0) {
close(sockfd);
return -1;
}
close(sockfd);
return datafd;
}

void af_alg_update(int datafd, const void *data_in, size_t len)
{
send(datafd, data_in, len, MSG_MORE);
}

ssize_t af_alg_final(int datafd, void *out, size_t len)
{
char buffer[1024];
ssize_t bytes;

send(datafd, NULL, 0, 0);

bytes = recv(datafd, buffer, sizeof(buffer), 0);
memcpy(out, buffer, MIN(len, bytes));
return bytes;
}

bool af_alg_supported(char *alg)
{
int sock = af_alg_init(alg);

if (sock < 0)
return false;
close(sock);
return true;
}
30 changes: 30 additions & 0 deletions iscsi-scst/usr/af_alg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2025 Brian Meagher <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, version 2
* of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/

#ifndef SCST_AF_ALG_H
#define SCST_AF_ALG_H

#include <unistd.h>
#include <stdbool.h>

#define SCST_AF_ALG_SHA256_NAME "sha256"
#define SCST_AF_ALG_SHA3_256_NAME "sha3-256"

int af_alg_init(const char *algorithm);
void af_alg_update(int datafd, const void *data_in, size_t len);
ssize_t af_alg_final(int datafd, void *out, size_t len);
bool af_alg_supported(char *alg);

#endif
92 changes: 92 additions & 0 deletions iscsi-scst/usr/chap.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <unistd.h>
#include "sha1.h"
#include "md5.h"
#include "af_alg.h"
#include <sys/param.h>

#include "iscsid.h"

Expand All @@ -39,9 +41,13 @@

#define CHAP_DIGEST_ALG_MD5 5
#define CHAP_DIGEST_ALG_SHA1 6
#define CHAP_DIGEST_ALG_SHA256 7
#define CHAP_DIGEST_ALG_SHA3_256 8

#define CHAP_MD5_DIGEST_LEN 16
#define CHAP_SHA1_DIGEST_LEN 20
#define CHAP_SHA256_DIGEST_LEN 32
#define CHAP_SHA3_256_DIGEST_LEN 32

#define CHAP_INITIATOR_ERROR -1
#define CHAP_AUTH_ERROR -2
Expand Down Expand Up @@ -338,6 +344,49 @@ static inline void chap_calc_digest_sha1(char chap_id, const char *secret, int s
sha1_final(&ctx, digest);
}

static inline void
chap_calc_digest_af_alg(char *alg, char chap_id,
const char *secret, int secret_len,
const u8 *challenge, int challenge_len,
u8 *digest, int digest_len)
{
int datafd = af_alg_init(alg);
char buffer[1024];
int bytes;

if (datafd < 0) {
log_error("CHAP unable to use %s algorithm", alg);
return;
}

af_alg_update(datafd, &chap_id, 1);
af_alg_update(datafd, secret, secret_len);
af_alg_update(datafd, challenge, challenge_len);
bytes = af_alg_final(datafd, buffer, sizeof(buffer));
close(datafd);
memcpy(digest, buffer, MIN(bytes, digest_len));
}

static inline void
chap_calc_digest_sha256(char chap_id, const char *secret, int secret_len,
const u8 *challenge, int challenge_len, u8 *digest)
{
chap_calc_digest_af_alg(SCST_AF_ALG_SHA256_NAME,
chap_id, secret, secret_len,
challenge, challenge_len,
digest, CHAP_SHA256_DIGEST_LEN);
}

static inline void
chap_calc_digest_sha3_256(char chap_id, const char *secret, int secret_len,
const u8 *challenge, int challenge_len, u8 *digest)
{
chap_calc_digest_af_alg(SCST_AF_ALG_SHA3_256_NAME,
chap_id, secret, secret_len,
challenge, challenge_len,
digest, CHAP_SHA3_256_DIGEST_LEN);
}

/*
* To generate challenge for CHAP, use stronger random number generator as
* opposed to simple rand().
Expand Down Expand Up @@ -374,7 +423,16 @@ static int chap_initiator_auth_create_challenge(struct connection *conn)
conn->auth.chap.digest_alg = CHAP_DIGEST_ALG_SHA1;
conn->auth_state = CHAP_AUTH_STATE_CHALLENGE;
break;
} else if (!strcmp(p, "7") && af_alg_supported(SCST_AF_ALG_SHA256_NAME)) {
conn->auth.chap.digest_alg = CHAP_DIGEST_ALG_SHA256;
conn->auth_state = CHAP_AUTH_STATE_CHALLENGE;
break;
} else if (!strcmp(p, "8") && af_alg_supported(SCST_AF_ALG_SHA3_256_NAME)) {
conn->auth.chap.digest_alg = CHAP_DIGEST_ALG_SHA3_256;
conn->auth_state = CHAP_AUTH_STATE_CHALLENGE;
break;
}

}
if (!p)
return CHAP_INITIATOR_ERROR;
Expand Down Expand Up @@ -458,6 +516,12 @@ static int chap_initiator_auth_check_response(struct connection *conn)
case CHAP_DIGEST_ALG_SHA1:
digest_len = CHAP_SHA1_DIGEST_LEN;
break;
case CHAP_DIGEST_ALG_SHA256:
digest_len = CHAP_SHA256_DIGEST_LEN;
break;
case CHAP_DIGEST_ALG_SHA3_256:
digest_len = CHAP_SHA3_256_DIGEST_LEN;
break;
default:
retval = CHAP_TARGET_ERROR;
goto out;
Expand Down Expand Up @@ -490,6 +554,18 @@ static int chap_initiator_auth_check_response(struct connection *conn)
conn->auth.chap.challenge_size,
our_digest);
break;
case CHAP_DIGEST_ALG_SHA256:
chap_calc_digest_sha256(conn->auth.chap.id, pass, strlen(pass),
conn->auth.chap.challenge,
conn->auth.chap.challenge_size,
our_digest);
break;
case CHAP_DIGEST_ALG_SHA3_256:
chap_calc_digest_sha3_256(conn->auth.chap.id, pass, strlen(pass),
conn->auth.chap.challenge,
conn->auth.chap.challenge_size,
our_digest);
break;
default:
retval = CHAP_TARGET_ERROR;
goto out;
Expand Down Expand Up @@ -571,6 +647,12 @@ static int chap_target_auth_create_response(struct connection *conn)
case CHAP_DIGEST_ALG_SHA1:
digest_len = CHAP_SHA1_DIGEST_LEN;
break;
case CHAP_DIGEST_ALG_SHA256:
digest_len = CHAP_SHA256_DIGEST_LEN;
break;
case CHAP_DIGEST_ALG_SHA3_256:
digest_len = CHAP_SHA3_256_DIGEST_LEN;
break;
default:
retval = CHAP_TARGET_ERROR;
goto out;
Expand Down Expand Up @@ -619,6 +701,16 @@ static int chap_target_auth_create_response(struct connection *conn)
chap_calc_digest_sha1(chap_id, ISCSI_USER_PASS(user),
strlen(ISCSI_USER_PASS(user)), challenge, challenge_len, digest);
break;
case CHAP_DIGEST_ALG_SHA256:
chap_calc_digest_sha256(chap_id, ISCSI_USER_PASS(user),
strlen(ISCSI_USER_PASS(user)),
challenge, challenge_len, digest);
break;
case CHAP_DIGEST_ALG_SHA3_256:
chap_calc_digest_sha3_256(chap_id, ISCSI_USER_PASS(user),
strlen(ISCSI_USER_PASS(user)),
challenge, challenge_len, digest);
break;
default:
retval = CHAP_TARGET_ERROR;
goto out;
Expand Down