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