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