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