1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 5 * Authors: Doug Rabson <dfr@rabson.org> 6 * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 #include "opt_inet6.h" 32 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/kobj.h> 36 #include <sys/lock.h> 37 #include <sys/malloc.h> 38 #include <sys/mbuf.h> 39 #include <sys/module.h> 40 #include <sys/mutex.h> 41 #include <kgssapi/gssapi.h> 42 #include <kgssapi/gssapi_impl.h> 43 44 #include "kgss_if.h" 45 #include "kcrypto.h" 46 47 #define GSS_TOKEN_SENT_BY_ACCEPTOR 1 48 #define GSS_TOKEN_SEALED 2 49 #define GSS_TOKEN_ACCEPTOR_SUBKEY 4 50 51 static gss_OID_desc krb5_mech_oid = 52 {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; 53 54 struct krb5_data { 55 size_t kd_length; 56 void *kd_data; 57 }; 58 59 struct krb5_keyblock { 60 uint16_t kk_type; /* encryption type */ 61 struct krb5_data kk_key; /* key data */ 62 }; 63 64 struct krb5_address { 65 uint16_t ka_type; 66 struct krb5_data ka_addr; 67 }; 68 69 /* 70 * The km_elem array is ordered so that the highest received sequence 71 * number is listed first. 72 */ 73 struct krb5_msg_order { 74 uint32_t km_flags; 75 uint32_t km_start; 76 uint32_t km_length; 77 uint32_t km_jitter_window; 78 uint32_t km_first_seq; 79 uint32_t *km_elem; 80 }; 81 82 struct krb5_context { 83 struct _gss_ctx_id_t kc_common; 84 struct mtx kc_lock; 85 uint32_t kc_ac_flags; 86 uint32_t kc_ctx_flags; 87 uint32_t kc_more_flags; 88 #define LOCAL 1 89 #define OPEN 2 90 #define COMPAT_OLD_DES3 4 91 #define COMPAT_OLD_DES3_SELECTED 8 92 #define ACCEPTOR_SUBKEY 16 93 struct krb5_address kc_local_address; 94 struct krb5_address kc_remote_address; 95 uint16_t kc_local_port; 96 uint16_t kc_remote_port; 97 struct krb5_keyblock kc_keyblock; 98 struct krb5_keyblock kc_local_subkey; 99 struct krb5_keyblock kc_remote_subkey; 100 volatile uint32_t kc_local_seqnumber; 101 uint32_t kc_remote_seqnumber; 102 uint32_t kc_keytype; 103 uint32_t kc_cksumtype; 104 struct krb5_data kc_source_name; 105 struct krb5_data kc_target_name; 106 uint32_t kc_lifetime; 107 struct krb5_msg_order kc_msg_order; 108 struct krb5_key_state *kc_tokenkey; 109 struct krb5_key_state *kc_encryptkey; 110 struct krb5_key_state *kc_checksumkey; 111 112 struct krb5_key_state *kc_send_seal_Ke; 113 struct krb5_key_state *kc_send_seal_Ki; 114 struct krb5_key_state *kc_send_seal_Kc; 115 struct krb5_key_state *kc_send_sign_Kc; 116 117 struct krb5_key_state *kc_recv_seal_Ke; 118 struct krb5_key_state *kc_recv_seal_Ki; 119 struct krb5_key_state *kc_recv_seal_Kc; 120 struct krb5_key_state *kc_recv_sign_Kc; 121 }; 122 123 static uint16_t 124 get_uint16(const uint8_t **pp, size_t *lenp) 125 { 126 const uint8_t *p = *pp; 127 uint16_t v; 128 129 if (*lenp < 2) 130 return (0); 131 132 v = (p[0] << 8) | p[1]; 133 *pp = p + 2; 134 *lenp = *lenp - 2; 135 136 return (v); 137 } 138 139 static uint32_t 140 get_uint32(const uint8_t **pp, size_t *lenp) 141 { 142 const uint8_t *p = *pp; 143 uint32_t v; 144 145 if (*lenp < 4) 146 return (0); 147 148 v = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; 149 *pp = p + 4; 150 *lenp = *lenp - 4; 151 152 return (v); 153 } 154 155 static void 156 get_data(const uint8_t **pp, size_t *lenp, struct krb5_data *dp) 157 { 158 size_t sz = get_uint32(pp, lenp); 159 160 dp->kd_length = sz; 161 dp->kd_data = malloc(sz, M_GSSAPI, M_WAITOK); 162 163 if (*lenp < sz) 164 sz = *lenp; 165 bcopy(*pp, dp->kd_data, sz); 166 (*pp) += sz; 167 (*lenp) -= sz; 168 } 169 170 static void 171 delete_data(struct krb5_data *dp) 172 { 173 if (dp->kd_data) { 174 free(dp->kd_data, M_GSSAPI); 175 dp->kd_length = 0; 176 dp->kd_data = NULL; 177 } 178 } 179 180 static void 181 get_address(const uint8_t **pp, size_t *lenp, struct krb5_address *ka) 182 { 183 184 ka->ka_type = get_uint16(pp, lenp); 185 get_data(pp, lenp, &ka->ka_addr); 186 } 187 188 static void 189 delete_address(struct krb5_address *ka) 190 { 191 delete_data(&ka->ka_addr); 192 } 193 194 static void 195 get_keyblock(const uint8_t **pp, size_t *lenp, struct krb5_keyblock *kk) 196 { 197 198 kk->kk_type = get_uint16(pp, lenp); 199 get_data(pp, lenp, &kk->kk_key); 200 } 201 202 static void 203 delete_keyblock(struct krb5_keyblock *kk) 204 { 205 if (kk->kk_key.kd_data) 206 bzero(kk->kk_key.kd_data, kk->kk_key.kd_length); 207 delete_data(&kk->kk_key); 208 } 209 210 static void 211 copy_key(struct krb5_keyblock *from, struct krb5_keyblock **to) 212 { 213 214 if (from->kk_key.kd_length) 215 *to = from; 216 else 217 *to = NULL; 218 } 219 220 static void 221 copy_lucid_key(gss_buffer_desc *from, uint32_t type, struct krb5_keyblock *to) 222 { 223 224 to->kk_type = type; 225 to->kk_key.kd_length = from->length; 226 if (from->length > 0) { 227 to->kk_key.kd_data = malloc(from->length, M_GSSAPI, M_WAITOK); 228 memcpy(to->kk_key.kd_data, from->value, from->length); 229 } 230 } 231 232 /* 233 * Return non-zero if we are initiator. 234 */ 235 static __inline int 236 is_initiator(struct krb5_context *kc) 237 { 238 return (kc->kc_more_flags & LOCAL); 239 } 240 241 /* 242 * Return non-zero if we are acceptor. 243 */ 244 static __inline int 245 is_acceptor(struct krb5_context *kc) 246 { 247 return !(kc->kc_more_flags & LOCAL); 248 } 249 250 static void 251 get_initiator_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp) 252 { 253 254 if (is_initiator(kc)) 255 copy_key(&kc->kc_local_subkey, kdp); 256 else 257 copy_key(&kc->kc_remote_subkey, kdp); 258 if (!*kdp) 259 copy_key(&kc->kc_keyblock, kdp); 260 } 261 262 static void 263 get_acceptor_subkey(struct krb5_context *kc, struct krb5_keyblock **kdp) 264 { 265 266 if (is_initiator(kc)) 267 copy_key(&kc->kc_remote_subkey, kdp); 268 else 269 copy_key(&kc->kc_local_subkey, kdp); 270 } 271 272 static OM_uint32 273 get_keys(struct krb5_context *kc) 274 { 275 struct krb5_keyblock *keydata; 276 struct krb5_encryption_class *ec; 277 struct krb5_key_state *key; 278 int etype; 279 280 keydata = NULL; 281 get_acceptor_subkey(kc, &keydata); 282 if (!keydata) 283 if ((kc->kc_more_flags & ACCEPTOR_SUBKEY) == 0) 284 get_initiator_subkey(kc, &keydata); 285 if (!keydata) 286 return (GSS_S_FAILURE); 287 288 /* 289 * GSS-API treats all DES etypes the same and all DES3 etypes 290 * the same. 291 */ 292 switch (keydata->kk_type) { 293 case ETYPE_DES_CBC_CRC: 294 case ETYPE_DES_CBC_MD4: 295 case ETYPE_DES_CBC_MD5: 296 etype = ETYPE_DES_CBC_CRC; 297 break; 298 299 case ETYPE_DES3_CBC_MD5: 300 case ETYPE_DES3_CBC_SHA1: 301 case ETYPE_OLD_DES3_CBC_SHA1: 302 etype = ETYPE_DES3_CBC_SHA1; 303 break; 304 305 default: 306 etype = keydata->kk_type; 307 } 308 309 ec = krb5_find_encryption_class(etype); 310 if (!ec) 311 return (GSS_S_FAILURE); 312 313 key = krb5_create_key(ec); 314 krb5_set_key(key, keydata->kk_key.kd_data); 315 kc->kc_tokenkey = key; 316 317 switch (etype) { 318 case ETYPE_DES_CBC_CRC: 319 case ETYPE_ARCFOUR_HMAC_MD5: 320 case ETYPE_ARCFOUR_HMAC_MD5_56: { 321 /* 322 * Single DES and ARCFOUR uses a 'derived' key (XOR 323 * with 0xf0) for encrypting wrap tokens. The original 324 * key is used for checksums and sequence numbers. 325 */ 326 struct krb5_key_state *ekey; 327 uint8_t *ekp, *kp; 328 int i; 329 330 ekey = krb5_create_key(ec); 331 ekp = ekey->ks_key; 332 kp = key->ks_key; 333 for (i = 0; i < ec->ec_keylen; i++) 334 ekp[i] = kp[i] ^ 0xf0; 335 krb5_set_key(ekey, ekp); 336 kc->kc_encryptkey = ekey; 337 refcount_acquire(&key->ks_refs); 338 kc->kc_checksumkey = key; 339 break; 340 } 341 342 case ETYPE_DES3_CBC_SHA1: 343 /* 344 * Triple DES uses a RFC 3961 style derived key with 345 * usage number KG_USAGE_SIGN for checksums. The 346 * original key is used for encryption and sequence 347 * numbers. 348 */ 349 kc->kc_checksumkey = krb5_get_checksum_key(key, KG_USAGE_SIGN); 350 refcount_acquire(&key->ks_refs); 351 kc->kc_encryptkey = key; 352 break; 353 354 default: 355 /* 356 * We need eight derived keys four for sending and 357 * four for receiving. 358 */ 359 if (is_initiator(kc)) { 360 /* 361 * We are initiator. 362 */ 363 kc->kc_send_seal_Ke = krb5_get_encryption_key(key, 364 KG_USAGE_INITIATOR_SEAL); 365 kc->kc_send_seal_Ki = krb5_get_integrity_key(key, 366 KG_USAGE_INITIATOR_SEAL); 367 kc->kc_send_seal_Kc = krb5_get_checksum_key(key, 368 KG_USAGE_INITIATOR_SEAL); 369 kc->kc_send_sign_Kc = krb5_get_checksum_key(key, 370 KG_USAGE_INITIATOR_SIGN); 371 372 kc->kc_recv_seal_Ke = krb5_get_encryption_key(key, 373 KG_USAGE_ACCEPTOR_SEAL); 374 kc->kc_recv_seal_Ki = krb5_get_integrity_key(key, 375 KG_USAGE_ACCEPTOR_SEAL); 376 kc->kc_recv_seal_Kc = krb5_get_checksum_key(key, 377 KG_USAGE_ACCEPTOR_SEAL); 378 kc->kc_recv_sign_Kc = krb5_get_checksum_key(key, 379 KG_USAGE_ACCEPTOR_SIGN); 380 } else { 381 /* 382 * We are acceptor. 383 */ 384 kc->kc_send_seal_Ke = krb5_get_encryption_key(key, 385 KG_USAGE_ACCEPTOR_SEAL); 386 kc->kc_send_seal_Ki = krb5_get_integrity_key(key, 387 KG_USAGE_ACCEPTOR_SEAL); 388 kc->kc_send_seal_Kc = krb5_get_checksum_key(key, 389 KG_USAGE_ACCEPTOR_SEAL); 390 kc->kc_send_sign_Kc = krb5_get_checksum_key(key, 391 KG_USAGE_ACCEPTOR_SIGN); 392 393 kc->kc_recv_seal_Ke = krb5_get_encryption_key(key, 394 KG_USAGE_INITIATOR_SEAL); 395 kc->kc_recv_seal_Ki = krb5_get_integrity_key(key, 396 KG_USAGE_INITIATOR_SEAL); 397 kc->kc_recv_seal_Kc = krb5_get_checksum_key(key, 398 KG_USAGE_INITIATOR_SEAL); 399 kc->kc_recv_sign_Kc = krb5_get_checksum_key(key, 400 KG_USAGE_INITIATOR_SIGN); 401 } 402 break; 403 } 404 405 return (GSS_S_COMPLETE); 406 } 407 408 static void 409 krb5_init(gss_ctx_id_t ctx) 410 { 411 struct krb5_context *kc = (struct krb5_context *)ctx; 412 413 mtx_init(&kc->kc_lock, "krb5 gss lock", NULL, MTX_DEF); 414 } 415 416 static OM_uint32 417 krb5_lucid_import(gss_ctx_id_t ctx, 418 enum sec_context_format format, 419 const gss_buffer_t context_token) 420 { 421 struct krb5_context *kc = (struct krb5_context *)ctx; 422 kgss_lucid_desc *lctx = (kgss_lucid_desc *)context_token; 423 OM_uint32 res; 424 425 kc->kc_more_flags = 0; 426 if (lctx->protocol == 0) { 427 kc->kc_cksumtype = lctx->rfc_sign; 428 kc->kc_keytype = lctx->rfc_seal; 429 copy_lucid_key(&lctx->ctx_key, lctx->ctx_type, 430 &kc->kc_keyblock); 431 } else if (lctx->protocol == 1) { 432 if (lctx->have_subkey != 0) { 433 if (lctx->initiate != 0) 434 copy_lucid_key(&lctx->subkey_key, 435 lctx->subkey_type, 436 &kc->kc_remote_subkey); 437 else 438 copy_lucid_key(&lctx->subkey_key, 439 lctx->subkey_type, 440 &kc->kc_local_subkey); 441 kc->kc_cksumtype = lctx->subkey_type; 442 kc->kc_keytype = lctx->subkey_type; 443 kc->kc_more_flags |= ACCEPTOR_SUBKEY; 444 } else { 445 if (lctx->initiate != 0) 446 copy_lucid_key(&lctx->ctx_key, 447 lctx->ctx_type, 448 &kc->kc_remote_subkey); 449 else 450 copy_lucid_key(&lctx->ctx_key, 451 lctx->ctx_type, 452 &kc->kc_local_subkey); 453 kc->kc_cksumtype = lctx->ctx_type; 454 kc->kc_keytype = lctx->ctx_type; 455 } 456 } else { 457 return (GSS_S_DEFECTIVE_TOKEN); 458 } 459 kc->kc_local_seqnumber = lctx->send_seq; 460 kc->kc_remote_seqnumber = lctx->recv_seq; 461 if (lctx->initiate != 0) 462 kc->kc_more_flags |= LOCAL; 463 kc->kc_lifetime = lctx->endtime; 464 kc->kc_msg_order.km_flags = 0; 465 466 res = get_keys(kc); 467 if (GSS_ERROR(res)) 468 return (res); 469 470 /* 471 * We don't need these anymore. 472 */ 473 delete_keyblock(&kc->kc_keyblock); 474 delete_keyblock(&kc->kc_local_subkey); 475 delete_keyblock(&kc->kc_remote_subkey); 476 477 return (GSS_S_COMPLETE); 478 } 479 480 static OM_uint32 481 krb5_import(gss_ctx_id_t ctx, 482 enum sec_context_format format, 483 const gss_buffer_t context_token) 484 { 485 struct krb5_context *kc = (struct krb5_context *)ctx; 486 OM_uint32 res; 487 const uint8_t *p = (const uint8_t *) context_token->value; 488 size_t len = context_token->length; 489 uint32_t flags; 490 int i; 491 492 /* For MIT, just call krb5_lucid_import(). */ 493 if (format == MIT_V1) 494 return (krb5_lucid_import(ctx, format, context_token)); 495 496 /* 497 * We support heimdal 0.6 and heimdal 1.1 498 */ 499 if (format != KGSS_HEIMDAL_0_6 && format != KGSS_HEIMDAL_1_1) 500 return (GSS_S_DEFECTIVE_TOKEN); 501 502 #define SC_LOCAL_ADDRESS 1 503 #define SC_REMOTE_ADDRESS 2 504 #define SC_KEYBLOCK 4 505 #define SC_LOCAL_SUBKEY 8 506 #define SC_REMOTE_SUBKEY 16 507 508 /* 509 * Ensure that the token starts with krb5 oid. 510 */ 511 if (p[0] != 0x00 || p[1] != krb5_mech_oid.length 512 || len < krb5_mech_oid.length + 2 513 || bcmp(krb5_mech_oid.elements, p + 2, 514 krb5_mech_oid.length)) 515 return (GSS_S_DEFECTIVE_TOKEN); 516 p += krb5_mech_oid.length + 2; 517 len -= krb5_mech_oid.length + 2; 518 519 flags = get_uint32(&p, &len); 520 kc->kc_ac_flags = get_uint32(&p, &len); 521 if (flags & SC_LOCAL_ADDRESS) 522 get_address(&p, &len, &kc->kc_local_address); 523 if (flags & SC_REMOTE_ADDRESS) 524 get_address(&p, &len, &kc->kc_remote_address); 525 kc->kc_local_port = get_uint16(&p, &len); 526 kc->kc_remote_port = get_uint16(&p, &len); 527 if (flags & SC_KEYBLOCK) 528 get_keyblock(&p, &len, &kc->kc_keyblock); 529 if (flags & SC_LOCAL_SUBKEY) 530 get_keyblock(&p, &len, &kc->kc_local_subkey); 531 if (flags & SC_REMOTE_SUBKEY) 532 get_keyblock(&p, &len, &kc->kc_remote_subkey); 533 kc->kc_local_seqnumber = get_uint32(&p, &len); 534 kc->kc_remote_seqnumber = get_uint32(&p, &len); 535 kc->kc_keytype = get_uint32(&p, &len); 536 kc->kc_cksumtype = get_uint32(&p, &len); 537 get_data(&p, &len, &kc->kc_source_name); 538 get_data(&p, &len, &kc->kc_target_name); 539 kc->kc_ctx_flags = get_uint32(&p, &len); 540 kc->kc_more_flags = get_uint32(&p, &len); 541 kc->kc_lifetime = get_uint32(&p, &len); 542 /* 543 * Heimdal 1.1 adds the message order stuff. 544 */ 545 if (format == KGSS_HEIMDAL_1_1) { 546 kc->kc_msg_order.km_flags = get_uint32(&p, &len); 547 kc->kc_msg_order.km_start = get_uint32(&p, &len); 548 kc->kc_msg_order.km_length = get_uint32(&p, &len); 549 kc->kc_msg_order.km_jitter_window = get_uint32(&p, &len); 550 kc->kc_msg_order.km_first_seq = get_uint32(&p, &len); 551 kc->kc_msg_order.km_elem = 552 malloc(kc->kc_msg_order.km_jitter_window * sizeof(uint32_t), 553 M_GSSAPI, M_WAITOK); 554 for (i = 0; i < kc->kc_msg_order.km_jitter_window; i++) 555 kc->kc_msg_order.km_elem[i] = get_uint32(&p, &len); 556 } else { 557 kc->kc_msg_order.km_flags = 0; 558 } 559 560 res = get_keys(kc); 561 if (GSS_ERROR(res)) 562 return (res); 563 564 /* 565 * We don't need these anymore. 566 */ 567 delete_keyblock(&kc->kc_keyblock); 568 delete_keyblock(&kc->kc_local_subkey); 569 delete_keyblock(&kc->kc_remote_subkey); 570 571 return (GSS_S_COMPLETE); 572 } 573 574 static void 575 krb5_delete(gss_ctx_id_t ctx, gss_buffer_t output_token) 576 { 577 struct krb5_context *kc = (struct krb5_context *)ctx; 578 579 delete_address(&kc->kc_local_address); 580 delete_address(&kc->kc_remote_address); 581 delete_keyblock(&kc->kc_keyblock); 582 delete_keyblock(&kc->kc_local_subkey); 583 delete_keyblock(&kc->kc_remote_subkey); 584 delete_data(&kc->kc_source_name); 585 delete_data(&kc->kc_target_name); 586 if (kc->kc_msg_order.km_elem) 587 free(kc->kc_msg_order.km_elem, M_GSSAPI); 588 if (output_token) { 589 output_token->length = 0; 590 output_token->value = NULL; 591 } 592 if (kc->kc_tokenkey) { 593 krb5_free_key(kc->kc_tokenkey); 594 if (kc->kc_encryptkey) { 595 krb5_free_key(kc->kc_encryptkey); 596 krb5_free_key(kc->kc_checksumkey); 597 } else { 598 krb5_free_key(kc->kc_send_seal_Ke); 599 krb5_free_key(kc->kc_send_seal_Ki); 600 krb5_free_key(kc->kc_send_seal_Kc); 601 krb5_free_key(kc->kc_send_sign_Kc); 602 krb5_free_key(kc->kc_recv_seal_Ke); 603 krb5_free_key(kc->kc_recv_seal_Ki); 604 krb5_free_key(kc->kc_recv_seal_Kc); 605 krb5_free_key(kc->kc_recv_sign_Kc); 606 } 607 } 608 mtx_destroy(&kc->kc_lock); 609 } 610 611 static gss_OID 612 krb5_mech_type(gss_ctx_id_t ctx) 613 { 614 615 return (&krb5_mech_oid); 616 } 617 618 /* 619 * Make a token with the given type and length (the length includes 620 * the TOK_ID), initialising the token header appropriately. Return a 621 * pointer to the TOK_ID of the token. A new mbuf is allocated with 622 * the framing header plus hlen bytes of space. 623 * 624 * Format is as follows: 625 * 626 * 0x60 [APPLICATION 0] SEQUENCE 627 * DER encoded length length of oid + type + inner token length 628 * 0x06 NN <oid data> OID of mechanism type 629 * TT TT TOK_ID 630 * <inner token> data for inner token 631 * 632 * 1: der encoded length 633 */ 634 static void * 635 krb5_make_token(char tok_id[2], size_t hlen, size_t len, struct mbuf **mp) 636 { 637 size_t inside_len, len_len, tlen; 638 gss_OID oid = &krb5_mech_oid; 639 struct mbuf *m; 640 uint8_t *p; 641 642 inside_len = 2 + oid->length + len; 643 if (inside_len < 128) 644 len_len = 1; 645 else if (inside_len < 0x100) 646 len_len = 2; 647 else if (inside_len < 0x10000) 648 len_len = 3; 649 else if (inside_len < 0x1000000) 650 len_len = 4; 651 else 652 len_len = 5; 653 654 tlen = 1 + len_len + 2 + oid->length + hlen; 655 KASSERT(tlen <= MLEN, ("token head too large")); 656 MGET(m, M_WAITOK, MT_DATA); 657 M_ALIGN(m, tlen); 658 m->m_len = tlen; 659 660 p = (uint8_t *) m->m_data; 661 *p++ = 0x60; 662 switch (len_len) { 663 case 1: 664 *p++ = inside_len; 665 break; 666 case 2: 667 *p++ = 0x81; 668 *p++ = inside_len; 669 break; 670 case 3: 671 *p++ = 0x82; 672 *p++ = inside_len >> 8; 673 *p++ = inside_len; 674 break; 675 case 4: 676 *p++ = 0x83; 677 *p++ = inside_len >> 16; 678 *p++ = inside_len >> 8; 679 *p++ = inside_len; 680 break; 681 case 5: 682 *p++ = 0x84; 683 *p++ = inside_len >> 24; 684 *p++ = inside_len >> 16; 685 *p++ = inside_len >> 8; 686 *p++ = inside_len; 687 break; 688 } 689 690 *p++ = 0x06; 691 *p++ = oid->length; 692 bcopy(oid->elements, p, oid->length); 693 p += oid->length; 694 695 p[0] = tok_id[0]; 696 p[1] = tok_id[1]; 697 698 *mp = m; 699 700 return (p); 701 } 702 703 /* 704 * Verify a token, checking the inner token length and mechanism oid. 705 * pointer to the first byte of the TOK_ID. The length of the 706 * encapsulated data is checked to be at least len bytes; the actual 707 * length of the encapsulated data (including TOK_ID) is returned in 708 * *encap_len. 709 * 710 * If can_pullup is TRUE and the token header is fragmented, we will 711 * rearrange it. 712 * 713 * Format is as follows: 714 * 715 * 0x60 [APPLICATION 0] SEQUENCE 716 * DER encoded length length of oid + type + inner token length 717 * 0x06 NN <oid data> OID of mechanism type 718 * TT TT TOK_ID 719 * <inner token> data for inner token 720 * 721 * 1: der encoded length 722 */ 723 static void * 724 krb5_verify_token(char tok_id[2], size_t len, struct mbuf **mp, 725 size_t *encap_len, bool_t can_pullup) 726 { 727 struct mbuf *m; 728 size_t tlen, hlen, len_len, inside_len; 729 gss_OID oid = &krb5_mech_oid; 730 uint8_t *p; 731 732 m = *mp; 733 tlen = m_length(m, NULL); 734 if (tlen < 2) 735 return (NULL); 736 737 /* 738 * Ensure that at least the framing part of the token is 739 * contigous. 740 */ 741 if (m->m_len < 2) { 742 if (can_pullup) 743 *mp = m = m_pullup(m, 2); 744 else 745 return (NULL); 746 } 747 748 p = m->m_data; 749 750 if (*p++ != 0x60) 751 return (NULL); 752 753 if (*p < 0x80) { 754 inside_len = *p++; 755 len_len = 1; 756 } else { 757 /* 758 * Ensure there is enough space for the DER encoded length. 759 */ 760 len_len = (*p & 0x7f) + 1; 761 if (tlen < len_len + 1) 762 return (NULL); 763 if (m->m_len < len_len + 1) { 764 if (can_pullup) 765 *mp = m = m_pullup(m, len_len + 1); 766 else 767 return (NULL); 768 p = m->m_data + 1; 769 } 770 771 switch (*p++) { 772 case 0x81: 773 inside_len = *p++; 774 break; 775 776 case 0x82: 777 inside_len = (p[0] << 8) | p[1]; 778 p += 2; 779 break; 780 781 case 0x83: 782 inside_len = (p[0] << 16) | (p[1] << 8) | p[2]; 783 p += 3; 784 break; 785 786 case 0x84: 787 inside_len = (p[0] << 24) | (p[1] << 16) 788 | (p[2] << 8) | p[3]; 789 p += 4; 790 break; 791 792 default: 793 return (NULL); 794 } 795 } 796 797 if (tlen != inside_len + len_len + 1) 798 return (NULL); 799 if (inside_len < 2 + oid->length + len) 800 return (NULL); 801 802 /* 803 * Now that we know the value of len_len, we can pullup the 804 * whole header. The header is 1 + len_len + 2 + oid->length + 805 * len bytes. 806 */ 807 hlen = 1 + len_len + 2 + oid->length + len; 808 if (m->m_len < hlen) { 809 if (can_pullup) 810 *mp = m = m_pullup(m, hlen); 811 else 812 return (NULL); 813 p = m->m_data + 1 + len_len; 814 } 815 816 if (*p++ != 0x06) 817 return (NULL); 818 if (*p++ != oid->length) 819 return (NULL); 820 if (bcmp(oid->elements, p, oid->length)) 821 return (NULL); 822 p += oid->length; 823 824 if (p[0] != tok_id[0]) 825 return (NULL); 826 827 if (p[1] != tok_id[1]) 828 return (NULL); 829 830 *encap_len = inside_len - 2 - oid->length; 831 832 return (p); 833 } 834 835 static void 836 krb5_insert_seq(struct krb5_msg_order *mo, uint32_t seq, int index) 837 { 838 int i; 839 840 if (mo->km_length < mo->km_jitter_window) 841 mo->km_length++; 842 843 for (i = mo->km_length - 1; i > index; i--) 844 mo->km_elem[i] = mo->km_elem[i - 1]; 845 mo->km_elem[index] = seq; 846 } 847 848 /* 849 * Check sequence numbers according to RFC 2743 section 1.2.3. 850 */ 851 static OM_uint32 852 krb5_sequence_check(struct krb5_context *kc, uint32_t seq) 853 { 854 OM_uint32 res = GSS_S_FAILURE; 855 struct krb5_msg_order *mo = &kc->kc_msg_order; 856 int check_sequence = mo->km_flags & GSS_C_SEQUENCE_FLAG; 857 int check_replay = mo->km_flags & GSS_C_REPLAY_FLAG; 858 int i; 859 860 mtx_lock(&kc->kc_lock); 861 862 /* 863 * Message is in-sequence with no gap. 864 */ 865 if (mo->km_length == 0 || seq == mo->km_elem[0] + 1) { 866 /* 867 * This message is received in-sequence with no gaps. 868 */ 869 krb5_insert_seq(mo, seq, 0); 870 res = GSS_S_COMPLETE; 871 goto out; 872 } 873 874 if (seq > mo->km_elem[0]) { 875 /* 876 * This message is received in-sequence with a gap. 877 */ 878 krb5_insert_seq(mo, seq, 0); 879 if (check_sequence) 880 res = GSS_S_GAP_TOKEN; 881 else 882 res = GSS_S_COMPLETE; 883 goto out; 884 } 885 886 if (seq < mo->km_elem[mo->km_length - 1]) { 887 if (check_replay && !check_sequence) 888 res = GSS_S_OLD_TOKEN; 889 else 890 res = GSS_S_UNSEQ_TOKEN; 891 goto out; 892 } 893 894 for (i = 0; i < mo->km_length; i++) { 895 if (mo->km_elem[i] == seq) { 896 res = GSS_S_DUPLICATE_TOKEN; 897 goto out; 898 } 899 if (mo->km_elem[i] < seq) { 900 /* 901 * We need to insert this seq here, 902 */ 903 krb5_insert_seq(mo, seq, i); 904 if (check_replay && !check_sequence) 905 res = GSS_S_COMPLETE; 906 else 907 res = GSS_S_UNSEQ_TOKEN; 908 goto out; 909 } 910 } 911 912 out: 913 mtx_unlock(&kc->kc_lock); 914 915 return (res); 916 } 917 918 static uint8_t sgn_alg_des_md5[] = { 0x00, 0x00 }; 919 static uint8_t seal_alg_des[] = { 0x00, 0x00 }; 920 static uint8_t sgn_alg_des3_sha1[] = { 0x04, 0x00 }; 921 static uint8_t seal_alg_des3[] = { 0x02, 0x00 }; 922 static uint8_t seal_alg_rc4[] = { 0x10, 0x00 }; 923 static uint8_t sgn_alg_hmac_md5[] = { 0x11, 0x00 }; 924 925 /* 926 * Return the size of the inner token given the use of the key's 927 * encryption class. For wrap tokens, the length of the padded 928 * plaintext will be added to this. 929 */ 930 static size_t 931 token_length(struct krb5_key_state *key) 932 { 933 934 return (16 + key->ks_class->ec_checksumlen); 935 } 936 937 static OM_uint32 938 krb5_get_mic_old(struct krb5_context *kc, struct mbuf *m, 939 struct mbuf **micp, uint8_t sgn_alg[2]) 940 { 941 struct mbuf *mlast, *mic, *tm; 942 uint8_t *p, dir; 943 size_t tlen, mlen, cklen; 944 uint32_t seq; 945 char buf[8]; 946 947 mlen = m_length(m, &mlast); 948 949 tlen = token_length(kc->kc_tokenkey); 950 p = krb5_make_token("\x01\x01", tlen, tlen, &mic); 951 p += 2; /* TOK_ID */ 952 *p++ = sgn_alg[0]; /* SGN_ALG */ 953 *p++ = sgn_alg[1]; 954 955 *p++ = 0xff; /* filler */ 956 *p++ = 0xff; 957 *p++ = 0xff; 958 *p++ = 0xff; 959 960 /* 961 * SGN_CKSUM: 962 * 963 * Calculate the keyed checksum of the token header plus the 964 * message. 965 */ 966 cklen = kc->kc_checksumkey->ks_class->ec_checksumlen; 967 968 mic->m_len = p - (uint8_t *) mic->m_data; 969 mic->m_next = m; 970 MGET(tm, M_WAITOK, MT_DATA); 971 tm->m_len = cklen; 972 mlast->m_next = tm; 973 974 krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8, 975 8 + mlen, cklen); 976 bcopy(tm->m_data, p + 8, cklen); 977 mic->m_next = NULL; 978 mlast->m_next = NULL; 979 m_free(tm); 980 981 /* 982 * SND_SEQ: 983 * 984 * Take the four bytes of the sequence number least 985 * significant first followed by four bytes of direction 986 * marker (zero for initiator and 0xff for acceptor). Encrypt 987 * that data using the SGN_CKSUM as IV. Note: ARC4 wants the 988 * sequence number big-endian. 989 */ 990 seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1); 991 if (sgn_alg[0] == 0x11) { 992 p[0] = (seq >> 24); 993 p[1] = (seq >> 16); 994 p[2] = (seq >> 8); 995 p[3] = (seq >> 0); 996 } else { 997 p[0] = (seq >> 0); 998 p[1] = (seq >> 8); 999 p[2] = (seq >> 16); 1000 p[3] = (seq >> 24); 1001 } 1002 if (is_initiator(kc)) { 1003 dir = 0; 1004 } else { 1005 dir = 0xff; 1006 } 1007 p[4] = dir; 1008 p[5] = dir; 1009 p[6] = dir; 1010 p[7] = dir; 1011 bcopy(p + 8, buf, 8); 1012 1013 /* 1014 * Set the mic buffer to its final size so that the encrypt 1015 * can see the SND_SEQ part. 1016 */ 1017 mic->m_len += 8 + cklen; 1018 krb5_encrypt(kc->kc_tokenkey, mic, mic->m_len - cklen - 8, 8, buf, 8); 1019 1020 *micp = mic; 1021 return (GSS_S_COMPLETE); 1022 } 1023 1024 static OM_uint32 1025 krb5_get_mic_new(struct krb5_context *kc, struct mbuf *m, 1026 struct mbuf **micp) 1027 { 1028 struct krb5_key_state *key = kc->kc_send_sign_Kc; 1029 struct mbuf *mlast, *mic; 1030 uint8_t *p; 1031 int flags; 1032 size_t mlen, cklen; 1033 uint32_t seq; 1034 1035 mlen = m_length(m, &mlast); 1036 cklen = key->ks_class->ec_checksumlen; 1037 1038 KASSERT(16 + cklen <= MLEN, ("checksum too large for an mbuf")); 1039 MGET(mic, M_WAITOK, MT_DATA); 1040 M_ALIGN(mic, 16 + cklen); 1041 mic->m_len = 16 + cklen; 1042 p = mic->m_data; 1043 1044 /* TOK_ID */ 1045 p[0] = 0x04; 1046 p[1] = 0x04; 1047 1048 /* Flags */ 1049 flags = 0; 1050 if (is_acceptor(kc)) 1051 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR; 1052 if (kc->kc_more_flags & ACCEPTOR_SUBKEY) 1053 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY; 1054 p[2] = flags; 1055 1056 /* Filler */ 1057 p[3] = 0xff; 1058 p[4] = 0xff; 1059 p[5] = 0xff; 1060 p[6] = 0xff; 1061 p[7] = 0xff; 1062 1063 /* SND_SEQ */ 1064 p[8] = 0; 1065 p[9] = 0; 1066 p[10] = 0; 1067 p[11] = 0; 1068 seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1); 1069 p[12] = (seq >> 24); 1070 p[13] = (seq >> 16); 1071 p[14] = (seq >> 8); 1072 p[15] = (seq >> 0); 1073 1074 /* 1075 * SGN_CKSUM: 1076 * 1077 * Calculate the keyed checksum of the message plus the first 1078 * 16 bytes of the token header. 1079 */ 1080 mlast->m_next = mic; 1081 krb5_checksum(key, 0, m, 0, mlen + 16, cklen); 1082 mlast->m_next = NULL; 1083 1084 *micp = mic; 1085 return (GSS_S_COMPLETE); 1086 } 1087 1088 static OM_uint32 1089 krb5_get_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status, 1090 gss_qop_t qop_req, struct mbuf *m, struct mbuf **micp) 1091 { 1092 struct krb5_context *kc = (struct krb5_context *)ctx; 1093 1094 *minor_status = 0; 1095 1096 if (qop_req != GSS_C_QOP_DEFAULT) 1097 return (GSS_S_BAD_QOP); 1098 1099 if (time_uptime > kc->kc_lifetime) 1100 return (GSS_S_CONTEXT_EXPIRED); 1101 1102 switch (kc->kc_tokenkey->ks_class->ec_type) { 1103 case ETYPE_DES_CBC_CRC: 1104 return (krb5_get_mic_old(kc, m, micp, sgn_alg_des_md5)); 1105 1106 case ETYPE_DES3_CBC_SHA1: 1107 return (krb5_get_mic_old(kc, m, micp, sgn_alg_des3_sha1)); 1108 1109 case ETYPE_ARCFOUR_HMAC_MD5: 1110 case ETYPE_ARCFOUR_HMAC_MD5_56: 1111 return (krb5_get_mic_old(kc, m, micp, sgn_alg_hmac_md5)); 1112 1113 default: 1114 return (krb5_get_mic_new(kc, m, micp)); 1115 } 1116 1117 return (GSS_S_FAILURE); 1118 } 1119 1120 static OM_uint32 1121 krb5_verify_mic_old(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic, 1122 uint8_t sgn_alg[2]) 1123 { 1124 struct mbuf *mlast, *tm; 1125 uint8_t *p, *tp, dir; 1126 size_t mlen, tlen, elen; 1127 size_t cklen; 1128 uint32_t seq; 1129 1130 mlen = m_length(m, &mlast); 1131 1132 tlen = token_length(kc->kc_tokenkey); 1133 p = krb5_verify_token("\x01\x01", tlen, &mic, &elen, FALSE); 1134 if (!p) 1135 return (GSS_S_DEFECTIVE_TOKEN); 1136 #if 0 1137 /* 1138 * Disable this check - heimdal-1.1 generates DES3 MIC tokens 1139 * that are 2 bytes too big. 1140 */ 1141 if (elen != tlen) 1142 return (GSS_S_DEFECTIVE_TOKEN); 1143 #endif 1144 /* TOK_ID */ 1145 p += 2; 1146 1147 /* SGN_ALG */ 1148 if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1]) 1149 return (GSS_S_DEFECTIVE_TOKEN); 1150 p += 2; 1151 1152 if (p[0] != 0xff || p[1] != 0xff || p[2] != 0xff || p[3] != 0xff) 1153 return (GSS_S_DEFECTIVE_TOKEN); 1154 p += 4; 1155 1156 /* 1157 * SGN_CKSUM: 1158 * 1159 * Calculate the keyed checksum of the token header plus the 1160 * message. 1161 */ 1162 cklen = kc->kc_checksumkey->ks_class->ec_checksumlen; 1163 mic->m_len = p - (uint8_t *) mic->m_data; 1164 mic->m_next = m; 1165 MGET(tm, M_WAITOK, MT_DATA); 1166 tm->m_len = cklen; 1167 mlast->m_next = tm; 1168 1169 krb5_checksum(kc->kc_checksumkey, 15, mic, mic->m_len - 8, 1170 8 + mlen, cklen); 1171 mic->m_next = NULL; 1172 mlast->m_next = NULL; 1173 if (bcmp(tm->m_data, p + 8, cklen)) { 1174 m_free(tm); 1175 return (GSS_S_BAD_SIG); 1176 } 1177 1178 /* 1179 * SND_SEQ: 1180 * 1181 * Take the four bytes of the sequence number least 1182 * significant first followed by four bytes of direction 1183 * marker (zero for initiator and 0xff for acceptor). Encrypt 1184 * that data using the SGN_CKSUM as IV. Note: ARC4 wants the 1185 * sequence number big-endian. 1186 */ 1187 bcopy(p, tm->m_data, 8); 1188 tm->m_len = 8; 1189 krb5_decrypt(kc->kc_tokenkey, tm, 0, 8, p + 8, 8); 1190 1191 tp = tm->m_data; 1192 if (sgn_alg[0] == 0x11) { 1193 seq = tp[3] | (tp[2] << 8) | (tp[1] << 16) | (tp[0] << 24); 1194 } else { 1195 seq = tp[0] | (tp[1] << 8) | (tp[2] << 16) | (tp[3] << 24); 1196 } 1197 1198 if (is_initiator(kc)) { 1199 dir = 0xff; 1200 } else { 1201 dir = 0; 1202 } 1203 if (tp[4] != dir || tp[5] != dir || tp[6] != dir || tp[7] != dir) { 1204 m_free(tm); 1205 return (GSS_S_DEFECTIVE_TOKEN); 1206 } 1207 m_free(tm); 1208 1209 if (kc->kc_msg_order.km_flags & 1210 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) { 1211 return (krb5_sequence_check(kc, seq)); 1212 } 1213 1214 return (GSS_S_COMPLETE); 1215 } 1216 1217 static OM_uint32 1218 krb5_verify_mic_new(struct krb5_context *kc, struct mbuf *m, struct mbuf *mic) 1219 { 1220 OM_uint32 res; 1221 struct krb5_key_state *key = kc->kc_recv_sign_Kc; 1222 struct mbuf *mlast; 1223 uint8_t *p; 1224 int flags; 1225 size_t mlen, cklen; 1226 char buf[32]; 1227 1228 mlen = m_length(m, &mlast); 1229 cklen = key->ks_class->ec_checksumlen; 1230 1231 KASSERT(mic->m_next == NULL, ("MIC should be contiguous")); 1232 if (mic->m_len != 16 + cklen) 1233 return (GSS_S_DEFECTIVE_TOKEN); 1234 p = mic->m_data; 1235 1236 /* TOK_ID */ 1237 if (p[0] != 0x04) 1238 return (GSS_S_DEFECTIVE_TOKEN); 1239 if (p[1] != 0x04) 1240 return (GSS_S_DEFECTIVE_TOKEN); 1241 1242 /* Flags */ 1243 flags = 0; 1244 if (is_initiator(kc)) 1245 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR; 1246 if (kc->kc_more_flags & ACCEPTOR_SUBKEY) 1247 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY; 1248 if (p[2] != flags) 1249 return (GSS_S_DEFECTIVE_TOKEN); 1250 1251 /* Filler */ 1252 if (p[3] != 0xff) 1253 return (GSS_S_DEFECTIVE_TOKEN); 1254 if (p[4] != 0xff) 1255 return (GSS_S_DEFECTIVE_TOKEN); 1256 if (p[5] != 0xff) 1257 return (GSS_S_DEFECTIVE_TOKEN); 1258 if (p[6] != 0xff) 1259 return (GSS_S_DEFECTIVE_TOKEN); 1260 if (p[7] != 0xff) 1261 return (GSS_S_DEFECTIVE_TOKEN); 1262 1263 /* SND_SEQ */ 1264 if (kc->kc_msg_order.km_flags & 1265 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) { 1266 uint32_t seq; 1267 if (p[8] || p[9] || p[10] || p[11]) { 1268 res = GSS_S_UNSEQ_TOKEN; 1269 } else { 1270 seq = (p[12] << 24) | (p[13] << 16) 1271 | (p[14] << 8) | p[15]; 1272 res = krb5_sequence_check(kc, seq); 1273 } 1274 if (GSS_ERROR(res)) 1275 return (res); 1276 } else { 1277 res = GSS_S_COMPLETE; 1278 } 1279 1280 /* 1281 * SGN_CKSUM: 1282 * 1283 * Calculate the keyed checksum of the message plus the first 1284 * 16 bytes of the token header. 1285 */ 1286 m_copydata(mic, 16, cklen, buf); 1287 mlast->m_next = mic; 1288 krb5_checksum(key, 0, m, 0, mlen + 16, cklen); 1289 mlast->m_next = NULL; 1290 if (bcmp(buf, p + 16, cklen)) { 1291 return (GSS_S_BAD_SIG); 1292 } 1293 1294 return (GSS_S_COMPLETE); 1295 } 1296 1297 static OM_uint32 1298 krb5_verify_mic(gss_ctx_id_t ctx, OM_uint32 *minor_status, 1299 struct mbuf *m, struct mbuf *mic, gss_qop_t *qop_state) 1300 { 1301 struct krb5_context *kc = (struct krb5_context *)ctx; 1302 1303 *minor_status = 0; 1304 if (qop_state) 1305 *qop_state = GSS_C_QOP_DEFAULT; 1306 1307 if (time_uptime > kc->kc_lifetime) 1308 return (GSS_S_CONTEXT_EXPIRED); 1309 1310 switch (kc->kc_tokenkey->ks_class->ec_type) { 1311 case ETYPE_DES_CBC_CRC: 1312 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des_md5)); 1313 1314 case ETYPE_ARCFOUR_HMAC_MD5: 1315 case ETYPE_ARCFOUR_HMAC_MD5_56: 1316 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_hmac_md5)); 1317 1318 case ETYPE_DES3_CBC_SHA1: 1319 return (krb5_verify_mic_old(kc, m, mic, sgn_alg_des3_sha1)); 1320 1321 default: 1322 return (krb5_verify_mic_new(kc, m, mic)); 1323 } 1324 1325 return (GSS_S_FAILURE); 1326 } 1327 1328 static OM_uint32 1329 krb5_wrap_old(struct krb5_context *kc, int conf_req_flag, 1330 struct mbuf **mp, int *conf_state, 1331 uint8_t sgn_alg[2], uint8_t seal_alg[2]) 1332 { 1333 struct mbuf *m, *mlast, *tm, *cm, *pm; 1334 size_t mlen, tlen, padlen, datalen; 1335 uint8_t *p, dir; 1336 size_t cklen; 1337 uint8_t buf[8]; 1338 uint32_t seq; 1339 1340 /* 1341 * How many trailing pad bytes do we need? 1342 */ 1343 m = *mp; 1344 mlen = m_length(m, &mlast); 1345 tlen = kc->kc_tokenkey->ks_class->ec_msgblocklen; 1346 padlen = tlen - (mlen % tlen); 1347 1348 /* 1349 * The data part of the token has eight bytes of random 1350 * confounder prepended and followed by up to eight bytes of 1351 * padding bytes each of which is set to the number of padding 1352 * bytes. 1353 */ 1354 datalen = mlen + 8 + padlen; 1355 tlen = token_length(kc->kc_tokenkey); 1356 1357 p = krb5_make_token("\x02\x01", tlen, datalen + tlen, &tm); 1358 p += 2; /* TOK_ID */ 1359 *p++ = sgn_alg[0]; /* SGN_ALG */ 1360 *p++ = sgn_alg[1]; 1361 if (conf_req_flag) { 1362 *p++ = seal_alg[0]; /* SEAL_ALG */ 1363 *p++ = seal_alg[1]; 1364 } else { 1365 *p++ = 0xff; /* SEAL_ALG = none */ 1366 *p++ = 0xff; 1367 } 1368 1369 *p++ = 0xff; /* filler */ 1370 *p++ = 0xff; 1371 1372 /* 1373 * Copy the padded message data. 1374 */ 1375 if (M_LEADINGSPACE(m) >= 8) { 1376 m->m_data -= 8; 1377 m->m_len += 8; 1378 } else { 1379 MGET(cm, M_WAITOK, MT_DATA); 1380 cm->m_len = 8; 1381 cm->m_next = m; 1382 m = cm; 1383 } 1384 arc4rand(m->m_data, 8, 0); 1385 if (M_TRAILINGSPACE(mlast) >= padlen) { 1386 memset(mlast->m_data + mlast->m_len, padlen, padlen); 1387 mlast->m_len += padlen; 1388 } else { 1389 MGET(pm, M_WAITOK, MT_DATA); 1390 memset(pm->m_data, padlen, padlen); 1391 pm->m_len = padlen; 1392 mlast->m_next = pm; 1393 mlast = pm; 1394 } 1395 tm->m_next = m; 1396 1397 /* 1398 * SGN_CKSUM: 1399 * 1400 * Calculate the keyed checksum of the token header plus the 1401 * padded message. Fiddle with tm->m_len so that we only 1402 * checksum the 8 bytes of head that we care about. 1403 */ 1404 cklen = kc->kc_checksumkey->ks_class->ec_checksumlen; 1405 tlen = tm->m_len; 1406 tm->m_len = p - (uint8_t *) tm->m_data; 1407 MGET(cm, M_WAITOK, MT_DATA); 1408 cm->m_len = cklen; 1409 mlast->m_next = cm; 1410 krb5_checksum(kc->kc_checksumkey, 13, tm, tm->m_len - 8, 1411 datalen + 8, cklen); 1412 tm->m_len = tlen; 1413 mlast->m_next = NULL; 1414 bcopy(cm->m_data, p + 8, cklen); 1415 m_free(cm); 1416 1417 /* 1418 * SND_SEQ: 1419 * 1420 * Take the four bytes of the sequence number least 1421 * significant first (most significant first for ARCFOUR) 1422 * followed by four bytes of direction marker (zero for 1423 * initiator and 0xff for acceptor). Encrypt that data using 1424 * the SGN_CKSUM as IV. 1425 */ 1426 seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1); 1427 if (sgn_alg[0] == 0x11) { 1428 p[0] = (seq >> 24); 1429 p[1] = (seq >> 16); 1430 p[2] = (seq >> 8); 1431 p[3] = (seq >> 0); 1432 } else { 1433 p[0] = (seq >> 0); 1434 p[1] = (seq >> 8); 1435 p[2] = (seq >> 16); 1436 p[3] = (seq >> 24); 1437 } 1438 if (is_initiator(kc)) { 1439 dir = 0; 1440 } else { 1441 dir = 0xff; 1442 } 1443 p[4] = dir; 1444 p[5] = dir; 1445 p[6] = dir; 1446 p[7] = dir; 1447 krb5_encrypt(kc->kc_tokenkey, tm, p - (uint8_t *) tm->m_data, 1448 8, p + 8, 8); 1449 1450 if (conf_req_flag) { 1451 /* 1452 * Encrypt the padded message with an IV of zero for 1453 * DES and DES3, or an IV of the sequence number in 1454 * big-endian format for ARCFOUR. 1455 */ 1456 if (seal_alg[0] == 0x10) { 1457 buf[0] = (seq >> 24); 1458 buf[1] = (seq >> 16); 1459 buf[2] = (seq >> 8); 1460 buf[3] = (seq >> 0); 1461 krb5_encrypt(kc->kc_encryptkey, m, 0, datalen, 1462 buf, 4); 1463 } else { 1464 krb5_encrypt(kc->kc_encryptkey, m, 0, datalen, 1465 NULL, 0); 1466 } 1467 } 1468 1469 if (conf_state) 1470 *conf_state = conf_req_flag; 1471 1472 *mp = tm; 1473 return (GSS_S_COMPLETE); 1474 } 1475 1476 static OM_uint32 1477 krb5_wrap_new(struct krb5_context *kc, int conf_req_flag, 1478 struct mbuf **mp, int *conf_state) 1479 { 1480 struct krb5_key_state *Ke = kc->kc_send_seal_Ke; 1481 struct krb5_key_state *Ki = kc->kc_send_seal_Ki; 1482 struct krb5_key_state *Kc = kc->kc_send_seal_Kc; 1483 const struct krb5_encryption_class *ec = Ke->ks_class; 1484 struct mbuf *m, *mlast, *tm; 1485 uint8_t *p; 1486 int flags, EC; 1487 size_t mlen, blen, mblen, cklen, ctlen; 1488 uint32_t seq; 1489 static char zpad[32]; 1490 1491 m = *mp; 1492 mlen = m_length(m, &mlast); 1493 1494 blen = ec->ec_blocklen; 1495 mblen = ec->ec_msgblocklen; 1496 cklen = ec->ec_checksumlen; 1497 1498 if (conf_req_flag) { 1499 /* 1500 * For sealed messages, we need space for 16 bytes of 1501 * header, blen confounder, plaintext, padding, copy 1502 * of header and checksum. 1503 * 1504 * We pad to mblen (which may be different from 1505 * blen). If the encryption class is using CTS, mblen 1506 * will be one (i.e. no padding required). 1507 */ 1508 if (mblen > 1) 1509 EC = mlen % mblen; 1510 else 1511 EC = 0; 1512 ctlen = blen + mlen + EC + 16; 1513 1514 /* 1515 * Put initial header and confounder before the 1516 * message. 1517 */ 1518 M_PREPEND(m, 16 + blen, M_WAITOK); 1519 1520 /* 1521 * Append padding + copy of header and checksum. Try 1522 * to fit this into the end of the original message, 1523 * otherwise allocate a trailer. 1524 */ 1525 if (M_TRAILINGSPACE(mlast) >= EC + 16 + cklen) { 1526 tm = NULL; 1527 mlast->m_len += EC + 16 + cklen; 1528 } else { 1529 MGET(tm, M_WAITOK, MT_DATA); 1530 tm->m_len = EC + 16 + cklen; 1531 mlast->m_next = tm; 1532 } 1533 } else { 1534 /* 1535 * For unsealed messages, we need 16 bytes of header 1536 * plus space for the plaintext and a checksum. EC is 1537 * set to the checksum size. We leave space in tm for 1538 * a copy of the header - this will be trimmed later. 1539 */ 1540 M_PREPEND(m, 16, M_WAITOK); 1541 1542 MGET(tm, M_WAITOK, MT_DATA); 1543 tm->m_len = cklen + 16; 1544 mlast->m_next = tm; 1545 ctlen = 0; 1546 EC = cklen; 1547 } 1548 1549 p = m->m_data; 1550 1551 /* TOK_ID */ 1552 p[0] = 0x05; 1553 p[1] = 0x04; 1554 1555 /* Flags */ 1556 flags = 0; 1557 if (conf_req_flag) 1558 flags = GSS_TOKEN_SEALED; 1559 if (is_acceptor(kc)) 1560 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR; 1561 if (kc->kc_more_flags & ACCEPTOR_SUBKEY) 1562 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY; 1563 p[2] = flags; 1564 1565 /* Filler */ 1566 p[3] = 0xff; 1567 1568 /* EC + RRC - set to zero initially */ 1569 p[4] = 0; 1570 p[5] = 0; 1571 p[6] = 0; 1572 p[7] = 0; 1573 1574 /* SND_SEQ */ 1575 p[8] = 0; 1576 p[9] = 0; 1577 p[10] = 0; 1578 p[11] = 0; 1579 seq = atomic_fetchadd_32(&kc->kc_local_seqnumber, 1); 1580 p[12] = (seq >> 24); 1581 p[13] = (seq >> 16); 1582 p[14] = (seq >> 8); 1583 p[15] = (seq >> 0); 1584 1585 if (conf_req_flag) { 1586 /* 1587 * Encrypt according to RFC 4121 section 4.2 and RFC 1588 * 3961 section 5.3. Note: we don't generate tokens 1589 * with RRC values other than zero. If we did, we 1590 * should zero RRC in the copied header. 1591 */ 1592 arc4rand(p + 16, blen, 0); 1593 if (EC) { 1594 m_copyback(m, 16 + blen + mlen, EC, zpad); 1595 } 1596 m_copyback(m, 16 + blen + mlen + EC, 16, p); 1597 1598 krb5_checksum(Ki, 0, m, 16, ctlen, cklen); 1599 krb5_encrypt(Ke, m, 16, ctlen, NULL, 0); 1600 } else { 1601 /* 1602 * The plaintext message is followed by a checksum of 1603 * the plaintext plus a version of the header where EC 1604 * and RRC are set to zero. Also, the original EC must 1605 * be our checksum size. 1606 */ 1607 bcopy(p, tm->m_data, 16); 1608 krb5_checksum(Kc, 0, m, 16, mlen + 16, cklen); 1609 tm->m_data += 16; 1610 tm->m_len -= 16; 1611 } 1612 1613 /* 1614 * Finally set EC to its actual value 1615 */ 1616 p[4] = EC >> 8; 1617 p[5] = EC; 1618 1619 *mp = m; 1620 return (GSS_S_COMPLETE); 1621 } 1622 1623 static OM_uint32 1624 krb5_wrap(gss_ctx_id_t ctx, OM_uint32 *minor_status, 1625 int conf_req_flag, gss_qop_t qop_req, 1626 struct mbuf **mp, int *conf_state) 1627 { 1628 struct krb5_context *kc = (struct krb5_context *)ctx; 1629 1630 *minor_status = 0; 1631 if (conf_state) 1632 *conf_state = 0; 1633 1634 if (qop_req != GSS_C_QOP_DEFAULT) 1635 return (GSS_S_BAD_QOP); 1636 1637 if (time_uptime > kc->kc_lifetime) 1638 return (GSS_S_CONTEXT_EXPIRED); 1639 1640 switch (kc->kc_tokenkey->ks_class->ec_type) { 1641 case ETYPE_DES_CBC_CRC: 1642 return (krb5_wrap_old(kc, conf_req_flag, 1643 mp, conf_state, sgn_alg_des_md5, seal_alg_des)); 1644 1645 case ETYPE_ARCFOUR_HMAC_MD5: 1646 case ETYPE_ARCFOUR_HMAC_MD5_56: 1647 return (krb5_wrap_old(kc, conf_req_flag, 1648 mp, conf_state, sgn_alg_hmac_md5, seal_alg_rc4)); 1649 1650 case ETYPE_DES3_CBC_SHA1: 1651 return (krb5_wrap_old(kc, conf_req_flag, 1652 mp, conf_state, sgn_alg_des3_sha1, seal_alg_des3)); 1653 1654 default: 1655 return (krb5_wrap_new(kc, conf_req_flag, mp, conf_state)); 1656 } 1657 1658 return (GSS_S_FAILURE); 1659 } 1660 1661 static void 1662 m_trim(struct mbuf *m, int len) 1663 { 1664 struct mbuf *n; 1665 int off; 1666 1667 if (m == NULL) 1668 return; 1669 n = m_getptr(m, len, &off); 1670 if (n) { 1671 n->m_len = off; 1672 if (n->m_next) { 1673 m_freem(n->m_next); 1674 n->m_next = NULL; 1675 } 1676 } 1677 } 1678 1679 static OM_uint32 1680 krb5_unwrap_old(struct krb5_context *kc, struct mbuf **mp, int *conf_state, 1681 uint8_t sgn_alg[2], uint8_t seal_alg[2]) 1682 { 1683 OM_uint32 res; 1684 struct mbuf *m, *mlast, *hm, *cm, *n; 1685 uint8_t *p, dir; 1686 size_t tlen, elen, datalen, padlen; 1687 size_t cklen; 1688 uint8_t buf[32]; 1689 uint32_t seq; 1690 int i, conf; 1691 1692 m = *mp; 1693 m_length(m, &mlast); 1694 1695 tlen = token_length(kc->kc_tokenkey); 1696 cklen = kc->kc_tokenkey->ks_class->ec_checksumlen; 1697 1698 p = krb5_verify_token("\x02\x01", tlen, &m, &elen, TRUE); 1699 *mp = m; 1700 if (!p) 1701 return (GSS_S_DEFECTIVE_TOKEN); 1702 datalen = elen - tlen; 1703 1704 /* 1705 * Trim the framing header first to make life a little easier 1706 * later. 1707 */ 1708 m_adj(m, p - (uint8_t *) m->m_data); 1709 1710 /* TOK_ID */ 1711 p += 2; 1712 1713 /* SGN_ALG */ 1714 if (p[0] != sgn_alg[0] || p[1] != sgn_alg[1]) 1715 return (GSS_S_DEFECTIVE_TOKEN); 1716 p += 2; 1717 1718 /* SEAL_ALG */ 1719 if (p[0] == seal_alg[0] && p[1] == seal_alg[1]) 1720 conf = 1; 1721 else if (p[0] == 0xff && p[1] == 0xff) 1722 conf = 0; 1723 else 1724 return (GSS_S_DEFECTIVE_TOKEN); 1725 p += 2; 1726 1727 if (p[0] != 0xff || p[1] != 0xff) 1728 return (GSS_S_DEFECTIVE_TOKEN); 1729 p += 2; 1730 1731 /* 1732 * SND_SEQ: 1733 * 1734 * Take the four bytes of the sequence number least 1735 * significant first (most significant for ARCFOUR) followed 1736 * by four bytes of direction marker (zero for initiator and 1737 * 0xff for acceptor). Encrypt that data using the SGN_CKSUM 1738 * as IV. 1739 */ 1740 krb5_decrypt(kc->kc_tokenkey, m, 8, 8, p + 8, 8); 1741 if (sgn_alg[0] == 0x11) { 1742 seq = p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24); 1743 } else { 1744 seq = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 1745 } 1746 1747 if (is_initiator(kc)) { 1748 dir = 0xff; 1749 } else { 1750 dir = 0; 1751 } 1752 if (p[4] != dir || p[5] != dir || p[6] != dir || p[7] != dir) 1753 return (GSS_S_DEFECTIVE_TOKEN); 1754 1755 if (kc->kc_msg_order.km_flags & 1756 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) { 1757 res = krb5_sequence_check(kc, seq); 1758 if (GSS_ERROR(res)) 1759 return (res); 1760 } else { 1761 res = GSS_S_COMPLETE; 1762 } 1763 1764 /* 1765 * If the token was encrypted, decode it in-place. 1766 */ 1767 if (conf) { 1768 /* 1769 * Decrypt the padded message with an IV of zero for 1770 * DES and DES3 or an IV of the big-endian encoded 1771 * sequence number for ARCFOUR. 1772 */ 1773 if (seal_alg[0] == 0x10) { 1774 krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen, 1775 datalen, p, 4); 1776 } else { 1777 krb5_decrypt(kc->kc_encryptkey, m, 16 + cklen, 1778 datalen, NULL, 0); 1779 } 1780 } 1781 if (conf_state) 1782 *conf_state = conf; 1783 1784 /* 1785 * Check the trailing pad bytes. 1786 * RFC1964 specifies between 1<->8 bytes, each with a binary value 1787 * equal to the number of bytes. 1788 */ 1789 if (mlast->m_len > 0) 1790 padlen = mlast->m_data[mlast->m_len - 1]; 1791 else { 1792 n = m_getptr(m, tlen + datalen - 1, &i); 1793 /* 1794 * When the position is exactly equal to the # of data bytes 1795 * in the mbuf list, m_getptr() will return the last mbuf in 1796 * the list and an off == m_len for that mbuf, so that case 1797 * needs to be checked as well as a NULL return. 1798 */ 1799 if (n == NULL || n->m_len == i) 1800 return (GSS_S_DEFECTIVE_TOKEN); 1801 padlen = n->m_data[i]; 1802 } 1803 if (padlen < 1 || padlen > 8 || padlen > tlen + datalen) 1804 return (GSS_S_DEFECTIVE_TOKEN); 1805 m_copydata(m, tlen + datalen - padlen, padlen, buf); 1806 for (i = 0; i < padlen; i++) { 1807 if (buf[i] != padlen) { 1808 return (GSS_S_DEFECTIVE_TOKEN); 1809 } 1810 } 1811 1812 /* 1813 * SGN_CKSUM: 1814 * 1815 * Calculate the keyed checksum of the token header plus the 1816 * padded message. We do a little mbuf surgery to trim out the 1817 * parts we don't want to checksum. 1818 */ 1819 hm = m; 1820 *mp = m = m_split(m, 16 + cklen, M_WAITOK); 1821 mlast = m_last(m); 1822 hm->m_len = 8; 1823 hm->m_next = m; 1824 MGET(cm, M_WAITOK, MT_DATA); 1825 cm->m_len = cklen; 1826 mlast->m_next = cm; 1827 1828 krb5_checksum(kc->kc_checksumkey, 13, hm, 0, datalen + 8, cklen); 1829 hm->m_next = NULL; 1830 mlast->m_next = NULL; 1831 1832 if (bcmp(cm->m_data, hm->m_data + 16, cklen)) { 1833 m_freem(hm); 1834 m_free(cm); 1835 return (GSS_S_BAD_SIG); 1836 } 1837 m_freem(hm); 1838 m_free(cm); 1839 1840 /* 1841 * Trim off the confounder and padding. 1842 */ 1843 m_adj(m, 8); 1844 if (mlast->m_len >= padlen) { 1845 mlast->m_len -= padlen; 1846 } else { 1847 m_trim(m, datalen - 8 - padlen); 1848 } 1849 1850 *mp = m; 1851 return (res); 1852 } 1853 1854 static OM_uint32 1855 krb5_unwrap_new(struct krb5_context *kc, struct mbuf **mp, int *conf_state) 1856 { 1857 OM_uint32 res; 1858 struct krb5_key_state *Ke = kc->kc_recv_seal_Ke; 1859 struct krb5_key_state *Ki = kc->kc_recv_seal_Ki; 1860 struct krb5_key_state *Kc = kc->kc_recv_seal_Kc; 1861 const struct krb5_encryption_class *ec = Ke->ks_class; 1862 struct mbuf *m, *mlast, *hm, *cm; 1863 uint8_t *p; 1864 int sealed, flags, EC, RRC; 1865 size_t blen, cklen, ctlen, mlen, plen, tlen; 1866 char buf[32], buf2[32]; 1867 1868 m = *mp; 1869 mlen = m_length(m, &mlast); 1870 1871 if (mlen <= 16) 1872 return (GSS_S_DEFECTIVE_TOKEN); 1873 if (m->m_len < 16) { 1874 m = m_pullup(m, 16); 1875 *mp = m; 1876 } 1877 p = m->m_data; 1878 1879 /* TOK_ID */ 1880 if (p[0] != 0x05) 1881 return (GSS_S_DEFECTIVE_TOKEN); 1882 if (p[1] != 0x04) 1883 return (GSS_S_DEFECTIVE_TOKEN); 1884 1885 /* Flags */ 1886 sealed = p[2] & GSS_TOKEN_SEALED; 1887 flags = sealed; 1888 if (is_initiator(kc)) 1889 flags |= GSS_TOKEN_SENT_BY_ACCEPTOR; 1890 if (kc->kc_more_flags & ACCEPTOR_SUBKEY) 1891 flags |= GSS_TOKEN_ACCEPTOR_SUBKEY; 1892 if (p[2] != flags) 1893 return (GSS_S_DEFECTIVE_TOKEN); 1894 1895 /* Filler */ 1896 if (p[3] != 0xff) 1897 return (GSS_S_DEFECTIVE_TOKEN); 1898 1899 /* EC + RRC */ 1900 EC = (p[4] << 8) + p[5]; 1901 RRC = (p[6] << 8) + p[7]; 1902 1903 /* SND_SEQ */ 1904 if (kc->kc_msg_order.km_flags & 1905 (GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG)) { 1906 uint32_t seq; 1907 if (p[8] || p[9] || p[10] || p[11]) { 1908 res = GSS_S_UNSEQ_TOKEN; 1909 } else { 1910 seq = (p[12] << 24) | (p[13] << 16) 1911 | (p[14] << 8) | p[15]; 1912 res = krb5_sequence_check(kc, seq); 1913 } 1914 if (GSS_ERROR(res)) 1915 return (res); 1916 } else { 1917 res = GSS_S_COMPLETE; 1918 } 1919 1920 /* 1921 * Separate the header before dealing with RRC. We only need 1922 * to keep the header if the message isn't encrypted. 1923 */ 1924 if (sealed) { 1925 hm = NULL; 1926 m_adj(m, 16); 1927 } else { 1928 hm = m; 1929 *mp = m = m_split(m, 16, M_WAITOK); 1930 mlast = m_last(m); 1931 } 1932 1933 /* 1934 * Undo the effects of RRC by rotating left. 1935 */ 1936 if (RRC > 0) { 1937 struct mbuf *rm; 1938 size_t rlen; 1939 1940 rlen = mlen - 16; 1941 if (RRC <= sizeof(buf) && m->m_len >= rlen) { 1942 /* 1943 * Simple case, just rearrange the bytes in m. 1944 */ 1945 bcopy(m->m_data, buf, RRC); 1946 bcopy(m->m_data + RRC, m->m_data, rlen - RRC); 1947 bcopy(buf, m->m_data + rlen - RRC, RRC); 1948 } else { 1949 /* 1950 * More complicated - rearrange the mbuf 1951 * chain. 1952 */ 1953 rm = m; 1954 *mp = m = m_split(m, RRC, M_WAITOK); 1955 m_cat(m, rm); 1956 mlast = rm; 1957 } 1958 } 1959 1960 blen = ec->ec_blocklen; 1961 cklen = ec->ec_checksumlen; 1962 if (sealed) { 1963 /* 1964 * Decrypt according to RFC 4121 section 4.2 and RFC 1965 * 3961 section 5.3. The message must be large enough 1966 * for a blocksize confounder, at least one block of 1967 * cyphertext and a checksum. 1968 */ 1969 if (mlen < 16 + 2*blen + cklen) 1970 return (GSS_S_DEFECTIVE_TOKEN); 1971 1972 ctlen = mlen - 16 - cklen; 1973 krb5_decrypt(Ke, m, 0, ctlen, NULL, 0); 1974 1975 /* 1976 * The size of the plaintext is ctlen minus blocklen 1977 * (for the confounder), 16 (for the copy of the token 1978 * header) and EC (for the filler). The actual 1979 * plaintext starts after the confounder. 1980 */ 1981 plen = ctlen - blen - 16 - EC; 1982 1983 /* 1984 * Checksum the padded plaintext. 1985 */ 1986 m_copydata(m, ctlen, cklen, buf); 1987 krb5_checksum(Ki, 0, m, 0, ctlen, cklen); 1988 m_copydata(m, ctlen, cklen, buf2); 1989 1990 if (bcmp(buf, buf2, cklen)) 1991 return (GSS_S_BAD_SIG); 1992 1993 /* 1994 * Trim the message back to just plaintext. 1995 */ 1996 m_adj(m, blen); 1997 tlen = 16 + EC + cklen; 1998 if (mlast->m_len >= tlen) { 1999 mlast->m_len -= tlen; 2000 } else { 2001 m_trim(m, plen); 2002 } 2003 } else { 2004 /* 2005 * The plaintext message is followed by a checksum of 2006 * the plaintext plus a version of the header where EC 2007 * and RRC are set to zero. Also, the original EC must 2008 * be our checksum size. 2009 */ 2010 if (mlen < 16 + cklen || EC != cklen) 2011 return (GSS_S_DEFECTIVE_TOKEN); 2012 2013 /* 2014 * The size of the plaintext is simply the message 2015 * size less header and checksum. The plaintext starts 2016 * right after the header (which we have saved in hm). 2017 */ 2018 plen = mlen - 16 - cklen; 2019 2020 /* 2021 * Insert a copy of the header (with EC and RRC set to 2022 * zero) between the plaintext message and the 2023 * checksum. 2024 */ 2025 p = hm->m_data; 2026 p[4] = p[5] = p[6] = p[7] = 0; 2027 2028 cm = m_split(m, plen, M_WAITOK); 2029 mlast = m_last(m); 2030 m->m_next = hm; 2031 hm->m_next = cm; 2032 2033 bcopy(cm->m_data, buf, cklen); 2034 krb5_checksum(Kc, 0, m, 0, plen + 16, cklen); 2035 if (bcmp(cm->m_data, buf, cklen)) 2036 return (GSS_S_BAD_SIG); 2037 2038 /* 2039 * The checksum matches, discard all buf the plaintext. 2040 */ 2041 mlast->m_next = NULL; 2042 m_freem(hm); 2043 } 2044 2045 if (conf_state) 2046 *conf_state = (sealed != 0); 2047 2048 return (res); 2049 } 2050 2051 static OM_uint32 2052 krb5_unwrap(gss_ctx_id_t ctx, OM_uint32 *minor_status, 2053 struct mbuf **mp, int *conf_state, gss_qop_t *qop_state) 2054 { 2055 struct krb5_context *kc = (struct krb5_context *)ctx; 2056 OM_uint32 maj_stat; 2057 2058 *minor_status = 0; 2059 if (qop_state) 2060 *qop_state = GSS_C_QOP_DEFAULT; 2061 if (conf_state) 2062 *conf_state = 0; 2063 2064 if (time_uptime > kc->kc_lifetime) 2065 return (GSS_S_CONTEXT_EXPIRED); 2066 2067 switch (kc->kc_tokenkey->ks_class->ec_type) { 2068 case ETYPE_DES_CBC_CRC: 2069 maj_stat = krb5_unwrap_old(kc, mp, conf_state, 2070 sgn_alg_des_md5, seal_alg_des); 2071 break; 2072 2073 case ETYPE_ARCFOUR_HMAC_MD5: 2074 case ETYPE_ARCFOUR_HMAC_MD5_56: 2075 maj_stat = krb5_unwrap_old(kc, mp, conf_state, 2076 sgn_alg_hmac_md5, seal_alg_rc4); 2077 break; 2078 2079 case ETYPE_DES3_CBC_SHA1: 2080 maj_stat = krb5_unwrap_old(kc, mp, conf_state, 2081 sgn_alg_des3_sha1, seal_alg_des3); 2082 break; 2083 2084 default: 2085 maj_stat = krb5_unwrap_new(kc, mp, conf_state); 2086 break; 2087 } 2088 2089 if (GSS_ERROR(maj_stat)) { 2090 m_freem(*mp); 2091 *mp = NULL; 2092 } 2093 2094 return (maj_stat); 2095 } 2096 2097 static OM_uint32 2098 krb5_wrap_size_limit(gss_ctx_id_t ctx, OM_uint32 *minor_status, 2099 int conf_req_flag, gss_qop_t qop_req, OM_uint32 req_output_size, 2100 OM_uint32 *max_input_size) 2101 { 2102 struct krb5_context *kc = (struct krb5_context *)ctx; 2103 const struct krb5_encryption_class *ec; 2104 OM_uint32 overhead; 2105 2106 *minor_status = 0; 2107 *max_input_size = 0; 2108 2109 if (qop_req != GSS_C_QOP_DEFAULT) 2110 return (GSS_S_BAD_QOP); 2111 2112 ec = kc->kc_tokenkey->ks_class; 2113 switch (ec->ec_type) { 2114 case ETYPE_DES_CBC_CRC: 2115 case ETYPE_DES3_CBC_SHA1: 2116 case ETYPE_ARCFOUR_HMAC_MD5: 2117 case ETYPE_ARCFOUR_HMAC_MD5_56: 2118 /* 2119 * up to 5 bytes for [APPLICATION 0] SEQUENCE 2120 * 2 + krb5 oid length 2121 * 8 bytes of header 2122 * 8 bytes of confounder 2123 * maximum of 8 bytes of padding 2124 * checksum 2125 */ 2126 overhead = 5 + 2 + krb5_mech_oid.length; 2127 overhead += 8 + 8 + ec->ec_msgblocklen; 2128 overhead += ec->ec_checksumlen; 2129 break; 2130 2131 default: 2132 if (conf_req_flag) { 2133 /* 2134 * 16 byts of header 2135 * blocklen bytes of confounder 2136 * up to msgblocklen - 1 bytes of padding 2137 * 16 bytes for copy of header 2138 * checksum 2139 */ 2140 overhead = 16 + ec->ec_blocklen; 2141 overhead += ec->ec_msgblocklen - 1; 2142 overhead += 16; 2143 overhead += ec->ec_checksumlen; 2144 } else { 2145 /* 2146 * 16 bytes of header plus checksum. 2147 */ 2148 overhead = 16 + ec->ec_checksumlen; 2149 } 2150 } 2151 2152 *max_input_size = req_output_size - overhead; 2153 2154 return (GSS_S_COMPLETE); 2155 } 2156 2157 static kobj_method_t krb5_methods[] = { 2158 KOBJMETHOD(kgss_init, krb5_init), 2159 KOBJMETHOD(kgss_import, krb5_import), 2160 KOBJMETHOD(kgss_delete, krb5_delete), 2161 KOBJMETHOD(kgss_mech_type, krb5_mech_type), 2162 KOBJMETHOD(kgss_get_mic, krb5_get_mic), 2163 KOBJMETHOD(kgss_verify_mic, krb5_verify_mic), 2164 KOBJMETHOD(kgss_wrap, krb5_wrap), 2165 KOBJMETHOD(kgss_unwrap, krb5_unwrap), 2166 KOBJMETHOD(kgss_wrap_size_limit, krb5_wrap_size_limit), 2167 { 0, 0 } 2168 }; 2169 2170 static struct kobj_class krb5_class = { 2171 "kerberosv5", 2172 krb5_methods, 2173 sizeof(struct krb5_context) 2174 }; 2175 2176 /* 2177 * Kernel module glue 2178 */ 2179 static int 2180 kgssapi_krb5_modevent(module_t mod, int type, void *data) 2181 { 2182 2183 switch (type) { 2184 case MOD_LOAD: 2185 kgss_install_mech(&krb5_mech_oid, "kerberosv5", &krb5_class); 2186 break; 2187 2188 case MOD_UNLOAD: 2189 kgss_uninstall_mech(&krb5_mech_oid); 2190 break; 2191 } 2192 2193 return (0); 2194 } 2195 static moduledata_t kgssapi_krb5_mod = { 2196 "kgssapi_krb5", 2197 kgssapi_krb5_modevent, 2198 NULL, 2199 }; 2200 DECLARE_MODULE(kgssapi_krb5, kgssapi_krb5_mod, SI_SUB_VFS, SI_ORDER_ANY); 2201 MODULE_DEPEND(kgssapi_krb5, kgssapi, 1, 1, 1); 2202 MODULE_DEPEND(kgssapi_krb5, crypto, 1, 1, 1); 2203 MODULE_DEPEND(kgssapi_krb5, rc4, 1, 1, 1); 2204 MODULE_VERSION(kgssapi_krb5, 1); 2205