xref: /linux/drivers/target/iscsi/iscsi_target_auth.c (revision cf14fc2be868840c4c9e0e46a472995798b59712)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*******************************************************************************
3  * This file houses the main functions for the iSCSI CHAP support
4  *
5  * (c) Copyright 2007-2013 Datera, Inc.
6  *
7  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
8  *
9  ******************************************************************************/
10 
11 #include <crypto/hash.h>
12 #include <crypto/utils.h>
13 #include <linux/kernel.h>
14 #include <linux/string.h>
15 #include <linux/err.h>
16 #include <linux/hex.h>
17 #include <linux/random.h>
18 #include <linux/scatterlist.h>
19 #include <target/iscsi/iscsi_target_core.h>
20 #include "iscsi_target_nego.h"
21 #include "iscsi_target_auth.h"
22 
23 static char *chap_get_digest_name(const int digest_type)
24 {
25 	switch (digest_type) {
26 	case CHAP_DIGEST_MD5:
27 		return "md5";
28 	case CHAP_DIGEST_SHA1:
29 		return "sha1";
30 	case CHAP_DIGEST_SHA256:
31 		return "sha256";
32 	case CHAP_DIGEST_SHA3_256:
33 		return "sha3-256";
34 	default:
35 		return NULL;
36 	}
37 }
38 
39 static int chap_gen_challenge(
40 	struct iscsit_conn *conn,
41 	int caller,
42 	char *c_str,
43 	unsigned int *c_len)
44 {
45 	int ret;
46 	unsigned char *challenge_asciihex;
47 	struct iscsi_chap *chap = conn->auth_protocol;
48 
49 	challenge_asciihex = kzalloc(chap->challenge_len * 2 + 1, GFP_KERNEL);
50 	if (!challenge_asciihex)
51 		return -ENOMEM;
52 
53 	memset(chap->challenge, 0, MAX_CHAP_CHALLENGE_LEN);
54 
55 	ret = get_random_bytes_wait(chap->challenge, chap->challenge_len);
56 	if (unlikely(ret))
57 		goto out;
58 
59 	bin2hex(challenge_asciihex, chap->challenge,
60 				chap->challenge_len);
61 	/*
62 	 * Set CHAP_C, and copy the generated challenge into c_str.
63 	 */
64 	*c_len += sprintf(c_str + *c_len, "CHAP_C=0x%s", challenge_asciihex);
65 	*c_len += 1;
66 
67 	pr_debug("[%s] Sending CHAP_C=0x%s\n\n", (caller) ? "server" : "client",
68 			challenge_asciihex);
69 
70 out:
71 	kfree(challenge_asciihex);
72 	return ret;
73 }
74 
75 static int chap_test_algorithm(const char *name)
76 {
77 	struct crypto_shash *tfm;
78 
79 	tfm = crypto_alloc_shash(name, 0, 0);
80 	if (IS_ERR(tfm))
81 		return -1;
82 
83 	crypto_free_shash(tfm);
84 	return 0;
85 }
86 
87 static int chap_check_algorithm(const char *a_str)
88 {
89 	char *tmp, *orig, *token, *digest_name;
90 	long digest_type;
91 	int r = CHAP_DIGEST_UNKNOWN;
92 
93 	tmp = kstrdup(a_str, GFP_KERNEL);
94 	if (!tmp) {
95 		pr_err("Memory allocation failed for CHAP_A temporary buffer\n");
96 		return CHAP_DIGEST_UNKNOWN;
97 	}
98 	orig = tmp;
99 
100 	token = strsep(&tmp, "=");
101 	if (!token)
102 		goto out;
103 
104 	if (strcmp(token, "CHAP_A")) {
105 		pr_err("Unable to locate CHAP_A key\n");
106 		goto out;
107 	}
108 	while (token) {
109 		token = strsep(&tmp, ",");
110 		if (!token)
111 			goto out;
112 
113 		if (kstrtol(token, 10, &digest_type))
114 			continue;
115 
116 		digest_name = chap_get_digest_name(digest_type);
117 		if (!digest_name)
118 			continue;
119 
120 		pr_debug("Selected %s Algorithm\n", digest_name);
121 		if (chap_test_algorithm(digest_name) < 0) {
122 			pr_err("failed to allocate %s algo\n", digest_name);
123 		} else {
124 			r = digest_type;
125 			goto out;
126 		}
127 	}
128 out:
129 	kfree(orig);
130 	return r;
131 }
132 
133 static void chap_close(struct iscsit_conn *conn)
134 {
135 	kfree(conn->auth_protocol);
136 	conn->auth_protocol = NULL;
137 }
138 
139 static struct iscsi_chap *chap_server_open(
140 	struct iscsit_conn *conn,
141 	struct iscsi_node_auth *auth,
142 	const char *a_str,
143 	char *aic_str,
144 	unsigned int *aic_len)
145 {
146 	int digest_type;
147 	struct iscsi_chap *chap;
148 
149 	if (!(auth->naf_flags & NAF_USERID_SET) ||
150 	    !(auth->naf_flags & NAF_PASSWORD_SET)) {
151 		pr_err("CHAP user or password not set for"
152 				" Initiator ACL\n");
153 		return NULL;
154 	}
155 
156 	conn->auth_protocol = kzalloc_obj(struct iscsi_chap);
157 	if (!conn->auth_protocol)
158 		return NULL;
159 
160 	chap = conn->auth_protocol;
161 	digest_type = chap_check_algorithm(a_str);
162 	switch (digest_type) {
163 	case CHAP_DIGEST_MD5:
164 		chap->digest_size = MD5_SIGNATURE_SIZE;
165 		break;
166 	case CHAP_DIGEST_SHA1:
167 		chap->digest_size = SHA1_SIGNATURE_SIZE;
168 		break;
169 	case CHAP_DIGEST_SHA256:
170 		chap->digest_size = SHA256_SIGNATURE_SIZE;
171 		break;
172 	case CHAP_DIGEST_SHA3_256:
173 		chap->digest_size = SHA3_256_SIGNATURE_SIZE;
174 		break;
175 	case CHAP_DIGEST_UNKNOWN:
176 	default:
177 		pr_err("Unsupported CHAP_A value\n");
178 		chap_close(conn);
179 		return NULL;
180 	}
181 
182 	chap->digest_name = chap_get_digest_name(digest_type);
183 
184 	/* Tie the challenge length to the digest size */
185 	chap->challenge_len = chap->digest_size;
186 
187 	pr_debug("[server] Got CHAP_A=%d\n", digest_type);
188 	*aic_len = sprintf(aic_str, "CHAP_A=%d", digest_type);
189 	*aic_len += 1;
190 	pr_debug("[server] Sending CHAP_A=%d\n", digest_type);
191 
192 	/*
193 	 * Set Identifier.
194 	 */
195 	chap->id = conn->tpg->tpg_chap_id++;
196 	*aic_len += sprintf(aic_str + *aic_len, "CHAP_I=%d", chap->id);
197 	*aic_len += 1;
198 	pr_debug("[server] Sending CHAP_I=%d\n", chap->id);
199 	/*
200 	 * Generate Challenge.
201 	 */
202 	if (chap_gen_challenge(conn, 1, aic_str, aic_len) < 0) {
203 		chap_close(conn);
204 		return NULL;
205 	}
206 
207 	return chap;
208 }
209 
210 static const char base64_lookup_table[] =
211 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
212 
213 static int chap_base64_decode(u8 *dst, const char *src, size_t len)
214 {
215 	int i, bits = 0, ac = 0;
216 	const char *p;
217 	u8 *cp = dst;
218 
219 	for (i = 0; i < len; i++) {
220 		if (src[i] == '=')
221 			return cp - dst;
222 
223 		p = strchr(base64_lookup_table, src[i]);
224 		if (p == NULL || src[i] == 0)
225 			return -2;
226 
227 		ac <<= 6;
228 		ac += (p - base64_lookup_table);
229 		bits += 6;
230 		if (bits >= 8) {
231 			*cp++ = (ac >> (bits - 8)) & 0xff;
232 			ac &= ~(BIT(16) - BIT(bits - 8));
233 			bits -= 8;
234 		}
235 	}
236 	if (ac)
237 		return -1;
238 
239 	return cp - dst;
240 }
241 
242 static int chap_server_compute_hash(
243 	struct iscsit_conn *conn,
244 	struct iscsi_node_auth *auth,
245 	char *nr_in_ptr,
246 	char *nr_out_ptr,
247 	unsigned int *nr_out_len)
248 {
249 	unsigned long id;
250 	unsigned char id_as_uchar;
251 	unsigned char type;
252 	unsigned char identifier[10], *initiatorchg = NULL;
253 	unsigned char *initiatorchg_binhex = NULL;
254 	unsigned char *digest = NULL;
255 	unsigned char *response = NULL;
256 	unsigned char *client_digest = NULL;
257 	unsigned char *server_digest = NULL;
258 	unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH];
259 	size_t compare_len;
260 	struct iscsi_chap *chap = conn->auth_protocol;
261 	struct crypto_shash *tfm = NULL;
262 	struct shash_desc *desc = NULL;
263 	int auth_ret = -1, ret, initiatorchg_len;
264 
265 	digest = kzalloc(chap->digest_size, GFP_KERNEL);
266 	if (!digest) {
267 		pr_err("Unable to allocate the digest buffer\n");
268 		goto out;
269 	}
270 
271 	response = kzalloc(chap->digest_size * 2 + 2, GFP_KERNEL);
272 	if (!response) {
273 		pr_err("Unable to allocate the response buffer\n");
274 		goto out;
275 	}
276 
277 	client_digest = kzalloc(chap->digest_size, GFP_KERNEL);
278 	if (!client_digest) {
279 		pr_err("Unable to allocate the client_digest buffer\n");
280 		goto out;
281 	}
282 
283 	server_digest = kzalloc(chap->digest_size, GFP_KERNEL);
284 	if (!server_digest) {
285 		pr_err("Unable to allocate the server_digest buffer\n");
286 		goto out;
287 	}
288 
289 	memset(identifier, 0, 10);
290 	memset(chap_n, 0, MAX_CHAP_N_SIZE);
291 	memset(chap_r, 0, MAX_RESPONSE_LENGTH);
292 
293 	initiatorchg = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
294 	if (!initiatorchg) {
295 		pr_err("Unable to allocate challenge buffer\n");
296 		goto out;
297 	}
298 
299 	initiatorchg_binhex = kzalloc(CHAP_CHALLENGE_STR_LEN, GFP_KERNEL);
300 	if (!initiatorchg_binhex) {
301 		pr_err("Unable to allocate initiatorchg_binhex buffer\n");
302 		goto out;
303 	}
304 	/*
305 	 * Extract CHAP_N.
306 	 */
307 	if (extract_param(nr_in_ptr, "CHAP_N", MAX_CHAP_N_SIZE, chap_n,
308 				&type) < 0) {
309 		pr_err("Could not find CHAP_N.\n");
310 		goto out;
311 	}
312 	if (type == HEX) {
313 		pr_err("Could not find CHAP_N.\n");
314 		goto out;
315 	}
316 
317 	/* Include the terminating NULL in the compare */
318 	compare_len = strlen(auth->userid) + 1;
319 	if (strncmp(chap_n, auth->userid, compare_len) != 0) {
320 		pr_err("CHAP_N values do not match!\n");
321 		goto out;
322 	}
323 	pr_debug("[server] Got CHAP_N=%s\n", chap_n);
324 	/*
325 	 * Extract CHAP_R.
326 	 */
327 	if (extract_param(nr_in_ptr, "CHAP_R", MAX_RESPONSE_LENGTH, chap_r,
328 				&type) < 0) {
329 		pr_err("Could not find CHAP_R.\n");
330 		goto out;
331 	}
332 
333 	switch (type) {
334 	case HEX:
335 		if (strlen(chap_r) != chap->digest_size * 2) {
336 			pr_err("Malformed CHAP_R\n");
337 			goto out;
338 		}
339 		if (hex2bin(client_digest, chap_r, chap->digest_size) < 0) {
340 			pr_err("Malformed CHAP_R: invalid HEX\n");
341 			goto out;
342 		}
343 		break;
344 	case BASE64: {
345 		size_t r_len = strlen(chap_r);
346 
347 		while (r_len > 0 && chap_r[r_len - 1] == '=')
348 			r_len--;
349 		if (r_len > DIV_ROUND_UP(chap->digest_size * 4, 3)) {
350 			pr_err("Malformed CHAP_R: base64 payload too long\n");
351 			goto out;
352 		}
353 		if (chap_base64_decode(client_digest, chap_r, strlen(chap_r)) !=
354 		    chap->digest_size) {
355 			pr_err("Malformed CHAP_R: invalid BASE64\n");
356 			goto out;
357 		}
358 		break;
359 	}
360 	default:
361 		pr_err("Could not find CHAP_R\n");
362 		goto out;
363 	}
364 
365 	pr_debug("[server] Got CHAP_R=%s\n", chap_r);
366 
367 	tfm = crypto_alloc_shash(chap->digest_name, 0, 0);
368 	if (IS_ERR(tfm)) {
369 		tfm = NULL;
370 		pr_err("Unable to allocate struct crypto_shash\n");
371 		goto out;
372 	}
373 
374 	desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(tfm), GFP_KERNEL);
375 	if (!desc) {
376 		pr_err("Unable to allocate struct shash_desc\n");
377 		goto out;
378 	}
379 
380 	desc->tfm = tfm;
381 
382 	ret = crypto_shash_init(desc);
383 	if (ret < 0) {
384 		pr_err("crypto_shash_init() failed\n");
385 		goto out;
386 	}
387 
388 	ret = crypto_shash_update(desc, &chap->id, 1);
389 	if (ret < 0) {
390 		pr_err("crypto_shash_update() failed for id\n");
391 		goto out;
392 	}
393 
394 	ret = crypto_shash_update(desc, (char *)&auth->password,
395 				  strlen(auth->password));
396 	if (ret < 0) {
397 		pr_err("crypto_shash_update() failed for password\n");
398 		goto out;
399 	}
400 
401 	ret = crypto_shash_finup(desc, chap->challenge,
402 				 chap->challenge_len, server_digest);
403 	if (ret < 0) {
404 		pr_err("crypto_shash_finup() failed for challenge\n");
405 		goto out;
406 	}
407 
408 	bin2hex(response, server_digest, chap->digest_size);
409 	pr_debug("[server] %s Server Digest: %s\n",
410 		chap->digest_name, response);
411 
412 	if (crypto_memneq(server_digest, client_digest, chap->digest_size)) {
413 		pr_debug("[server] %s Digests do not match!\n\n",
414 			chap->digest_name);
415 		goto out;
416 	} else
417 		pr_debug("[server] %s Digests match, CHAP connection"
418 				" successful.\n\n", chap->digest_name);
419 	/*
420 	 * One way authentication has succeeded, return now if mutual
421 	 * authentication is not enabled.
422 	 */
423 	if (!auth->authenticate_target) {
424 		auth_ret = 0;
425 		goto out;
426 	}
427 	/*
428 	 * Get CHAP_I.
429 	 */
430 	ret = extract_param(nr_in_ptr, "CHAP_I", 10, identifier, &type);
431 	if (ret == -ENOENT) {
432 		pr_debug("Could not find CHAP_I. Initiator uses One way authentication.\n");
433 		auth_ret = 0;
434 		goto out;
435 	}
436 	if (ret < 0) {
437 		pr_err("Could not find CHAP_I.\n");
438 		goto out;
439 	}
440 
441 	if (type == HEX)
442 		ret = kstrtoul(identifier, 16, &id);
443 	else if (type == DECIMAL)
444 		ret = kstrtoul(identifier, 10, &id);
445 	else
446 		ret = -EINVAL;
447 
448 	if (ret < 0) {
449 		pr_err("kstrtoul() failed for CHAP identifier: %d\n", ret);
450 		goto out;
451 	}
452 	if (id > 255) {
453 		pr_err("chap identifier: %lu greater than 255\n", id);
454 		goto out;
455 	}
456 	/*
457 	 * RFC 1994 says Identifier is no more than octet (8 bits).
458 	 */
459 	pr_debug("[server] Got CHAP_I=%lu\n", id);
460 	/*
461 	 * Get CHAP_C.
462 	 */
463 	if (extract_param(nr_in_ptr, "CHAP_C", CHAP_CHALLENGE_STR_LEN,
464 			initiatorchg, &type) < 0) {
465 		pr_err("Could not find CHAP_C.\n");
466 		goto out;
467 	}
468 
469 	switch (type) {
470 	case HEX:
471 		initiatorchg_len = DIV_ROUND_UP(strlen(initiatorchg), 2);
472 		if (!initiatorchg_len) {
473 			pr_err("Unable to convert incoming challenge\n");
474 			goto out;
475 		}
476 		if (initiatorchg_len > 1024) {
477 			pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
478 			goto out;
479 		}
480 
481 		if (hex2bin(initiatorchg_binhex, initiatorchg,
482 			    initiatorchg_len) < 0) {
483 			pr_err("Malformed CHAP_C: invalid HEX\n");
484 			goto out;
485 		}
486 		break;
487 	case BASE64:
488 		/*
489 		 * No overflow check needed: initiatorchg_binhex is
490 		 * CHAP_CHALLENGE_STR_LEN bytes and extract_param() caps
491 		 * initiatorchg at CHAP_CHALLENGE_STR_LEN characters, so
492 		 * the decoded output is at most DIV_ROUND_UP(
493 		 * (CHAP_CHALLENGE_STR_LEN - 1) * 3, 4) bytes, which is
494 		 * less than CHAP_CHALLENGE_STR_LEN.
495 		 */
496 		initiatorchg_len = chap_base64_decode(initiatorchg_binhex,
497 						      initiatorchg,
498 						      strlen(initiatorchg));
499 		if (initiatorchg_len < 0) {
500 			pr_err("Malformed CHAP_C: invalid BASE64\n");
501 			goto out;
502 		}
503 		if (!initiatorchg_len) {
504 			pr_err("Unable to convert incoming challenge\n");
505 			goto out;
506 		}
507 		if (initiatorchg_len > 1024) {
508 			pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
509 			goto out;
510 		}
511 		break;
512 	default:
513 		pr_err("Could not find CHAP_C.\n");
514 		goto out;
515 	}
516 
517 	pr_debug("[server] Got CHAP_C=%s\n", initiatorchg);
518 	/*
519 	 * During mutual authentication, the CHAP_C generated by the
520 	 * initiator must not match the original CHAP_C generated by
521 	 * the target.
522 	 */
523 	if (initiatorchg_len == chap->challenge_len &&
524 				!memcmp(initiatorchg_binhex, chap->challenge,
525 				initiatorchg_len)) {
526 		pr_err("initiator CHAP_C matches target CHAP_C, failing"
527 		       " login attempt\n");
528 		goto out;
529 	}
530 	/*
531 	 * Generate CHAP_N and CHAP_R for mutual authentication.
532 	 */
533 	ret = crypto_shash_init(desc);
534 	if (ret < 0) {
535 		pr_err("crypto_shash_init() failed\n");
536 		goto out;
537 	}
538 
539 	/* To handle both endiannesses */
540 	id_as_uchar = id;
541 	ret = crypto_shash_update(desc, &id_as_uchar, 1);
542 	if (ret < 0) {
543 		pr_err("crypto_shash_update() failed for id\n");
544 		goto out;
545 	}
546 
547 	ret = crypto_shash_update(desc, auth->password_mutual,
548 				  strlen(auth->password_mutual));
549 	if (ret < 0) {
550 		pr_err("crypto_shash_update() failed for"
551 				" password_mutual\n");
552 		goto out;
553 	}
554 	/*
555 	 * Convert received challenge to binary hex.
556 	 */
557 	ret = crypto_shash_finup(desc, initiatorchg_binhex, initiatorchg_len,
558 				 digest);
559 	if (ret < 0) {
560 		pr_err("crypto_shash_finup() failed for ma challenge\n");
561 		goto out;
562 	}
563 
564 	/*
565 	 * Generate CHAP_N and CHAP_R.
566 	 */
567 	*nr_out_len = sprintf(nr_out_ptr, "CHAP_N=%s", auth->userid_mutual);
568 	*nr_out_len += 1;
569 	pr_debug("[server] Sending CHAP_N=%s\n", auth->userid_mutual);
570 	/*
571 	 * Convert response from binary hex to ascii hext.
572 	 */
573 	bin2hex(response, digest, chap->digest_size);
574 	*nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s",
575 			response);
576 	*nr_out_len += 1;
577 	pr_debug("[server] Sending CHAP_R=0x%s\n", response);
578 	auth_ret = 0;
579 out:
580 	kfree_sensitive(desc);
581 	if (tfm)
582 		crypto_free_shash(tfm);
583 	kfree(initiatorchg);
584 	kfree(initiatorchg_binhex);
585 	kfree(digest);
586 	kfree(response);
587 	kfree(server_digest);
588 	kfree(client_digest);
589 	return auth_ret;
590 }
591 
592 u32 chap_main_loop(
593 	struct iscsit_conn *conn,
594 	struct iscsi_node_auth *auth,
595 	char *in_text,
596 	char *out_text,
597 	int *in_len,
598 	int *out_len)
599 {
600 	struct iscsi_chap *chap = conn->auth_protocol;
601 
602 	if (!chap) {
603 		chap = chap_server_open(conn, auth, in_text, out_text, out_len);
604 		if (!chap)
605 			return 2;
606 		chap->chap_state = CHAP_STAGE_SERVER_AIC;
607 		return 0;
608 	} else if (chap->chap_state == CHAP_STAGE_SERVER_AIC) {
609 		convert_null_to_semi(in_text, *in_len);
610 		if (chap_server_compute_hash(conn, auth, in_text, out_text,
611 				out_len) < 0) {
612 			chap_close(conn);
613 			return 2;
614 		}
615 		if (auth->authenticate_target)
616 			chap->chap_state = CHAP_STAGE_SERVER_NR;
617 		else
618 			*out_len = 0;
619 		chap_close(conn);
620 		return 1;
621 	}
622 
623 	return 2;
624 }
625