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