2 * Copyright (c) 1995, 1996, 1997, 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * 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.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright 1992, 2002 by the Massachusetts Institute of Technology.
35 * All Rights Reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
57 #include <afsconfig.h>
58 #include <afs/param.h>
63 #ifdef IGNORE_SOME_GCC_WARNINGS
64 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
70 #define HC_DEPRECATED_CRYPTO
71 #include <hcrypto/md4.h>
72 #include <hcrypto/md5.h>
73 #include <hcrypto/des.h>
74 #include <hcrypto/hmac.h>
76 #include "lifetimes.h"
78 #include "rxkad_convert.h"
80 #include "v5gen-rewrite.h"
84 #if defined(IGNORE_SOME_GCC_WARNINGS) && !defined(_clang) && __GNUC__ >= 7
85 # pragma GCC diagnostic push
86 # pragma GCC diagnostic warning "-Wformat-truncation"
89 #if defined(IGNORE_SOME_GCC_WARNINGS) && !defined(__clang__) && __GNUC__ >= 7
90 # pragma GCC diagnostic pop
95 #define RFC3961_NO_ENUMS
96 #define RFC3961_NO_CKSUM
97 #include <afs/rfc3961.h>
100 * Principal conversion Taken from src/lib/krb5/krb/conv_princ from MIT Kerberos. If you
101 * find a need to change the services here, please consider opening a
102 * bug with MIT by sending mail to krb5-bugs@mit.edu.
112 #define DO_REALM_CONVERSION 0x00000001
115 * Kadmin doesn't do realm conversion because it's currently
116 * kadmin/REALM.NAME. Zephyr doesn't because it's just zephyr/zephyr.
118 * "Realm conversion" is a bit of a misnomer; really, the v5 name is
119 * using a FQDN or something that looks like it, where the v4 name is
120 * just using the first label. Sometimes that second principal name
121 * component is a hostname, sometimes the realm name, sometimes it's
124 * This list should probably be more configurable, and more than
125 * likely on a per-realm basis, so locally-defined services can be
128 static const struct krb_convert sconv_list[] = {
129 /* Realm conversion, Change service name */
130 #define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 }
131 /* Realm conversion */
132 #define R(NAME) { NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 }
133 /* No Realm conversion */
134 #define NR(NAME) { NAME, NAME, 0, sizeof(NAME)-1 }
185 krb5_des_decrypt(struct ktc_encryptionKey *, int, void *, size_t, void *,
187 static int rxkad_derive_des_key(const void *, size_t,
188 struct ktc_encryptionKey *);
189 static int compress_parity_bits(void *, size_t *);
192 tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len,
193 int (*get_key) (void *, int, struct ktc_encryptionKey *),
194 rxkad_get_key_enctype_func get_key_enctype,
195 char *get_key_rock, int serv_kvno, char *name, char *inst,
196 char *cell, struct ktc_encryptionKey *session_key, afs_int32 * host,
197 afs_uint32 * start, afs_uint32 * end, afs_int32 disableCheckdot)
199 char plain[MAXKRB5TICKETLEN];
200 struct ktc_encryptionKey serv_key;
202 size_t keysize, allocsiz;
203 krb5_context context;
207 Ticket t5; /* Must free */
208 EncTicketPart decr_part; /* Must free */
210 size_t siz, plainsiz = 0;
212 char *v5_comp0, *v5_comp1, *c;
213 const struct krb_convert *p;
215 memset(&t5, 0, sizeof(t5));
216 memset(&decr_part, 0, sizeof(decr_part));
221 return RXKADBADTICKET; /* no ticket */
223 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) {
224 code = decode_Ticket((unsigned char *)ticket, ticket_len, &t5, &siz);
231 code = decode_EncryptedData((unsigned char *)ticket, ticket_len, &t5.enc_part, &siz);
236 /* If kvno is null, it's probably not included because it was kvno==0
238 if (t5.enc_part.kvno == NULL) {
241 v5_serv_kvno = *t5.enc_part.kvno;
244 /* Check that the key type really fit into 8 bytes */
245 switch (t5.enc_part.etype) {
246 case KRB5_ENCTYPE_DES_CBC_CRC:
247 case KRB5_ENCTYPE_DES_CBC_MD4:
248 case KRB5_ENCTYPE_DES_CBC_MD5:
250 if (t5.enc_part.cipher.length > sizeof(plain)
251 || t5.enc_part.cipher.length % 8 != 0)
254 code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key);
258 /* Decrypt data here, save in plain, assume it will shrink */
260 krb5_des_decrypt(&serv_key, t5.enc_part.etype,
261 t5.enc_part.cipher.data, t5.enc_part.cipher.length,
265 if (get_key_enctype == NULL)
267 code = krb5_init_context(&context);
270 code = krb5_enctype_valid(context, t5.enc_part.etype);
272 krb5_free_context(context);
275 code = krb5_enctype_keybits(context, t5.enc_part.etype, &keysize);
277 krb5_free_context(context);
280 keysize = keysize / 8;
282 keybuf = rxi_Alloc(allocsiz);
283 /* this is not quite a hole for afsconf_GetKeyByTypes. A wrapper
284 that calls afsconf_GetKeyByTypes and afsconf_typedKey_values
286 code = get_key_enctype(get_key_rock, v5_serv_kvno, t5.enc_part.etype,
289 rxi_Free(keybuf, allocsiz);
290 krb5_free_context(context);
293 code = krb5_keyblock_init(context, t5.enc_part.etype,
294 keybuf, keysize, &k);
295 rxi_Free(keybuf, allocsiz);
297 krb5_free_context(context);
300 code = krb5_crypto_init(context, &k, t5.enc_part.etype, &cr);
301 krb5_free_keyblock_contents(context, &k);
303 krb5_free_context(context);
306 #ifndef KRB5_KU_TICKET
307 #define KRB5_KU_TICKET 2
309 code = krb5_decrypt(context, cr, KRB5_KU_TICKET, t5.enc_part.cipher.data,
310 t5.enc_part.cipher.length, &plaindata);
311 krb5_crypto_destroy(context, cr);
313 if (plaindata.length > MAXKRB5TICKETLEN) {
314 krb5_data_free(&plaindata);
315 krb5_free_context(context);
318 memcpy(plain, plaindata.data, plaindata.length);
319 plainsiz = plaindata.length;
320 krb5_data_free(&plaindata);
322 krb5_free_context(context);
329 code = decode_EncTicketPart((unsigned char *)plain, plainsiz, &decr_part, &siz);
333 /* Extract realm and principal */
334 strncpy(cell, decr_part.crealm, MAXKTCNAMELEN);
335 cell[MAXKTCNAMELEN - 1] = '\0';
337 switch (decr_part.cname.name_string.len) {
339 v5_comp0 = decr_part.cname.name_string.val[0];
340 v5_comp1 = decr_part.cname.name_string.val[1];
343 if (strcmp(p->v5_str, v5_comp0) == 0) {
345 * It is, so set the new name now, and chop off
346 * instance's domain name if requested.
348 strncpy(name, p->v4_str, MAXKTCNAMELEN);
349 name[MAXKTCNAMELEN - 1] = '\0';
350 if (p->flags & DO_REALM_CONVERSION) {
351 c = strchr(v5_comp1, '.');
352 if (!c || (c - v5_comp1) >= MAXKTCNAMELEN - 1)
354 strncpy(inst, v5_comp1, c - v5_comp1);
355 inst[c - v5_comp1] = '\0';
363 strncpy(inst, decr_part.cname.name_string.val[1], MAXKTCNAMELEN);
364 inst[MAXKTCNAMELEN - 1] = '\0';
365 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
366 name[MAXKTCNAMELEN - 1] = '\0';
370 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
371 name[MAXKTCNAMELEN - 1] = '\0';
377 if (!disableCheckdot) {
379 * If the first part of the name_string contains a dot, punt since
380 * then we can't see the diffrence between the kerberos 5
381 * principals foo.root and foo/root later in the fileserver.
383 if (strchr(decr_part.cname.name_string.val[0], '.') != NULL)
387 /* Verify that decr_part.key is of right type */
388 if (tkt_DeriveDesKey(decr_part.key.keytype, decr_part.key.keyvalue.data,
389 decr_part.key.keyvalue.length, session_key) != 0)
391 /* Check lifetimes and host addresses, flags etc */
393 time_t now = time(0); /* Use fast time package instead??? */
394 *start = decr_part.authtime;
395 if (decr_part.starttime)
396 *start = *decr_part.starttime;
398 if (*start - now > CLOCK_SKEW || decr_part.flags.invalid)
401 if (decr_part.flags.invalid)
404 if (now > decr_part.endtime)
406 *end = decr_part.endtime;
410 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
413 free_EncryptedData(&t5.enc_part);
414 free_EncTicketPart(&decr_part);
415 memset(&serv_key, 0, sizeof(serv_key));
419 code = RXKADUNKNOWNKEY;
428 code = RXKADBADTICKET;
434 verify_checksum_md4(void *data, size_t len,
435 void *cksum, size_t cksumsz,
436 struct ktc_encryptionKey *key)
439 unsigned char tmp[16];
442 MD4_Update(&md4, data, len);
443 MD4_Final(tmp, &md4);
445 if (memcmp(tmp, cksum, cksumsz) != 0)
451 verify_checksum_md5(void *data, size_t len,
452 void *cksum, size_t cksumsz,
453 struct ktc_encryptionKey *key)
456 unsigned char tmp[16];
459 MD5_Update(&md5, data, len);
460 MD5_Final(tmp, &md5);
462 if (memcmp(tmp, cksum, cksumsz) != 0)
468 verify_checksum_crc(void *data, size_t len, void *cksum, size_t cksumsz,
469 struct ktc_encryptionKey *key)
474 _rxkad_crc_init_table();
475 crc = _rxkad_crc_update(data, len, 0);
477 r[1] = (crc >> 8) & 0xff;
478 r[2] = (crc >> 16) & 0xff;
479 r[3] = (crc >> 24) & 0xff;
481 if (memcmp(cksum, r, 4) != 0)
488 krb5_des_decrypt(struct ktc_encryptionKey *key, int etype, void *in,
489 size_t insz, void *out, size_t * outsz)
491 int (*cksum_func) (void *, size_t, void *, size_t,
492 struct ktc_encryptionKey *);
497 int ret = 1; /* failure */
501 DES_key_sched(ktc_to_cblock(key), &s);
503 #define CONFOUNDERSZ 8
506 case KRB5_ENCTYPE_DES_CBC_CRC:
507 memcpy(&ivec, key, sizeof(ivec));
509 cksum_func = verify_checksum_crc;
511 case KRB5_ENCTYPE_DES_CBC_MD4:
512 memset(&ivec, 0, sizeof(ivec));
514 cksum_func = verify_checksum_md4;
516 case KRB5_ENCTYPE_DES_CBC_MD5:
517 memset(&ivec, 0, sizeof(ivec));
519 cksum_func = verify_checksum_md5;
525 DES_cbc_encrypt(in, out, insz, &s, &ivec, 0);
527 memcpy(cksum, (char *)out + CONFOUNDERSZ, cksumsz);
528 memset((char *)out + CONFOUNDERSZ, 0, cksumsz);
531 ret = (*cksum_func) (out, insz, cksum, cksumsz, key);
533 *outsz = insz - CONFOUNDERSZ - cksumsz;
534 memmove(out, (char *)out + CONFOUNDERSZ + cksumsz, *outsz);
540 tkt_MakeTicket5(char *ticket, int *ticketLen, int enctype, int *kvno,
541 void *key, size_t keylen,
542 char *name, char *inst, char *cell, afs_uint32 start,
543 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
544 char *sname, char *sinst)
547 EncryptedData encdata;
548 unsigned char *buf, *encodebuf;
549 size_t encodelen, allocsiz;
550 heim_general_string carray[2];
552 krb5_context context;
558 memset(&encrypted, 0, sizeof(encrypted));
562 memset(&kb, 0, sizeof(kb));
563 memset(&data, 0, sizeof(data));
565 data.flags.transited_policy_checked = 1;
566 data.key.keytype=KRB5_ENCTYPE_DES_CBC_CRC;
567 data.key.keyvalue.data=sessionKey->data;
568 data.key.keyvalue.length=8;
572 data.cname.name_type=KRB5_NT_PRINCIPAL;
573 data.cname.name_string.val=carray;
574 data.cname.name_string.len=inst[0]?2:1;
578 allocsiz = length_EncTicketPart(&data);
579 buf = rxi_Alloc(allocsiz);
580 encodelen = allocsiz;
581 /* encode function wants pointer to end of buffer */
582 encodebuf = buf + allocsiz - 1;
583 code = encode_EncTicketPart(encodebuf, allocsiz, &data, &encodelen);
587 code = krb5_init_context(&context);
590 code = krb5_keyblock_init(context, enctype, key, keylen, &kb);
593 code = krb5_crypto_init(context, &kb, enctype, &cr);
596 code = krb5_encrypt(context, cr, KRB5_KU_TICKET, buf,
597 encodelen, &encrypted);
600 memset(&encdata, 0, sizeof(encdata));
601 encdata.etype=enctype;
603 encdata.cipher.data=encrypted.data;
604 encdata.cipher.length=encrypted.length;
606 if (length_EncryptedData(&encdata) > *ticketLen) {
607 code = RXKADTICKETLEN;
611 code = encode_EncryptedData((unsigned char *)ticket + *ticketLen - 1, *ticketLen, &encdata, &tl);
613 *kvno=RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY;
615 * encode function fills in from the end. move data to
616 * beginning of buffer
618 memmove(ticket, ticket + *ticketLen - tl, tl);
623 krb5_data_free(&encrypted);
625 krb5_crypto_destroy(context, cr);
626 krb5_free_keyblock_contents(context, &kb);
627 if (context != NULL) {
628 krb5_free_context(context);
630 rxi_Free(buf, allocsiz);
631 if ((code & 0xFFFFFF00) == ERROR_TABLE_BASE_asn1)
632 return RXKADINCONSISTENCY;
637 * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
638 * des key from another type of key.
640 * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
641 * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
642 * properly should be 1. However, we apply a slight variation due to the
643 * possibility of producing a weak des key. If the output key is weak, do NOT
644 * simply correct it, instead, the counter is advanced and the next output
645 * used. As such, we code so as to have n be the full 255 permitted by our
646 * encoding of the counter i in an 8-bit field. L itself is encoded as a
647 * 32-bit field, big-endian. We use the constant string "rxkad" as a label
648 * for this key derivation, the standard NUL byte separator, and omit a
649 * key-derivation context. The input key is unique to the krb5 service ticket,
650 * which is unlikely to be used in an other location. If it is used in such
651 * a fashion, both locations will derive the same des key from the PRF, but
652 * this is no different from if a krb5 des key had been used in the same way,
653 * as traditional krb5 rxkad uses the ticket session key directly as the token
657 rxkad_derive_des_key(const void *in, size_t insize,
658 struct ktc_encryptionKey *out)
661 char Lbuf[4]; /* bits of output, as 32 bit word, MSB first */
662 char tmp[64]; /* only needs to be 16 for md5, but lets be sure it fits */
672 /* stop when 8 bit counter wraps to 0 */
673 for (i = 1; i; i++) {
674 HMAC_CTX_init(&mctx);
675 HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL);
676 HMAC_Update(&mctx, &i, 1);
677 HMAC_Update(&mctx, "rxkad", strlen("rxkad") + 1); /* includes label and separator */
678 HMAC_Update(&mctx, Lbuf, 4);
679 mdsize = sizeof(tmp);
680 HMAC_Final(&mctx, tmp, &mdsize);
681 memcpy(ktmp, tmp, 8);
682 DES_set_odd_parity(&ktmp);
683 if (!DES_is_weak_key(&ktmp)) {
684 memcpy(out->data, ktmp, 8);
692 * This is the inverse of the random-to-key for 3des specified in
693 * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing
694 * the bits of each 8th byte as the lsb of the previous 7 bytes.
697 compress_parity_bits(void *buffer, size_t *bufsiz)
699 unsigned char *cb, tmp;
702 if (*bufsiz % 8 != 0)
704 cb = (unsigned char *)buffer;
706 for (i = 0; i < nk; i++) {
707 tmp = cb[8 * i + 7] >> 1;
708 for (j = 0; j < 7; j++) {
709 cb[8 * i + j] &= 0xfe;
710 cb[8 * i + j] |= tmp & 0x1;
714 for (i = 1; i < nk; i++)
715 memmove(cb + 7 * i, cb + 8 * i, 7);
721 * Enctype-specific knowledge about how to derive a des key from a given
722 * key. If given a des key, use it directly; otherwise, perform any
723 * parity fixup that may be needed and pass through to the hmad-md5 bits.
726 tkt_DeriveDesKey(int enctype, void *keydata, size_t keylen,
727 struct ktc_encryptionKey *output)
730 case KRB5_ENCTYPE_DES_CBC_CRC:
731 case KRB5_ENCTYPE_DES_CBC_MD4:
732 case KRB5_ENCTYPE_DES_CBC_MD5:
736 /* Extract session key */
737 memcpy(output, keydata, 8);
739 case KRB5_ENCTYPE_NULL:
751 /*In order to become a "Cryptographic Key" as specified in
752 * SP800-108, it must be indistinguishable from a random bitstring. */
753 case KRB5_ENCTYPE_DES3_CBC_MD5:
754 case KRB5_ENCTYPE_OLD_DES3_CBC_SHA1:
755 case KRB5_ENCTYPE_DES3_CBC_SHA1:
756 if (compress_parity_bits(keydata, &keylen))
764 if (rxkad_derive_des_key(keydata, keylen, output) != 0)