af3ee333803f5ba6ea6c3ebf5c27a5ab6d10e6b0
[openafs.git] / src / rxkad / ticket5.c
1 /*
2  * Copyright (c) 1995, 1996, 1997, 2002 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
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  * 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.
20  *
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
31  * SUCH DAMAGE.
32  */
33 /*
34  * Copyright 1992, 2002 by the Massachusetts Institute of Technology.
35  * All Rights Reserved.
36  *
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.
41  *
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.
55  */
56
57 #include <afsconfig.h>
58 #include <afs/param.h>
59 #include <afs/stds.h>
60
61 #include <roken.h>
62
63 #ifdef IGNORE_SOME_GCC_WARNINGS
64 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
65 #endif
66
67 #include <rx/xdr.h>
68 #include <rx/rx.h>
69
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>
75
76 #include "lifetimes.h"
77 #include "rxkad.h"
78 #include "rxkad_convert.h"
79
80 #include "v5gen-rewrite.h"
81 #include "v5gen.h"
82 #include "der.h"
83 #include "v5der.c"
84 #include "v5gen.c"
85
86 #define RFC3961_NO_ENUMS
87 #define RFC3961_NO_CKSUM
88 #include <afs/rfc3961.h>
89
90 /*
91  * Principal conversion Taken from src/lib/krb5/krb/conv_princ from MIT Kerberos.  If you
92  * find a need to change the services here, please consider opening a
93  * bug with MIT by sending mail to krb5-bugs@mit.edu.
94  */
95
96 struct krb_convert {
97     char *v4_str;
98     char *v5_str;
99     unsigned int flags;
100     unsigned int len;
101 };
102
103 #define DO_REALM_CONVERSION 0x00000001
104
105 /*
106  * Kadmin doesn't do realm conversion because it's currently
107  * kadmin/REALM.NAME.  Zephyr doesn't because it's just zephyr/zephyr.
108  *
109  * "Realm conversion" is a bit of a misnomer; really, the v5 name is
110  * using a FQDN or something that looks like it, where the v4 name is
111  * just using the first label.  Sometimes that second principal name
112  * component is a hostname, sometimes the realm name, sometimes it's
113  * neither.
114  *
115  * This list should probably be more configurable, and more than
116  * likely on a per-realm basis, so locally-defined services can be
117  * added, or not.
118  */
119 static const struct krb_convert sconv_list[] = {
120     /* Realm conversion, Change service name */
121 #define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 }
122     /* Realm conversion */
123 #define R(NAME)         { NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 }
124     /* No Realm conversion */
125 #define NR(NAME)        { NAME, NAME, 0, sizeof(NAME)-1 }
126
127     NR("kadmin"),
128     RC("rcmd", "host"),
129     R("discuss"),
130     R("rvdsrv"),
131     R("sample"),
132     R("olc"),
133     R("pop"),
134     R("sis"),
135     R("rfs"),
136     R("imap"),
137     R("ftp"),
138     R("ecat"),
139     R("daemon"),
140     R("gnats"),
141     R("moira"),
142     R("prms"),
143     R("mandarin"),
144     R("register"),
145     R("changepw"),
146     R("sms"),
147     R("afpserver"),
148     R("gdss"),
149     R("news"),
150     R("abs"),
151     R("nfs"),
152     R("tftp"),
153     NR("zephyr"),
154     R("http"),
155     R("khttp"),
156     R("pgpsigner"),
157     R("irc"),
158     R("mandarin-agent"),
159     R("write"),
160     R("palladium"),
161     R("imap"),
162     R("smtp"),
163     R("lmtp"),
164     R("ldap"),
165     R("acap"),
166     R("argus"),
167     R("mupdate"),
168     R("argus"),
169     {0, 0, 0, 0},
170 #undef R
171 #undef RC
172 #undef NR
173 };
174
175 static int
176   krb5_des_decrypt(struct ktc_encryptionKey *, int, void *, size_t, void *,
177                    size_t *);
178 static int rxkad_derive_des_key(const void *, size_t,
179                                 struct ktc_encryptionKey *);
180 static int compress_parity_bits(void *, size_t *);
181
182 int
183 tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len,
184                   int (*get_key) (void *, int, struct ktc_encryptionKey *),
185                   rxkad_get_key_enctype_func get_key_enctype,
186                   char *get_key_rock, int serv_kvno, char *name, char *inst,
187                   char *cell, struct ktc_encryptionKey *session_key, afs_int32 * host,
188                   afs_uint32 * start, afs_uint32 * end, afs_int32 disableCheckdot)
189 {
190     char plain[MAXKRB5TICKETLEN];
191     struct ktc_encryptionKey serv_key;
192     void *keybuf;
193     size_t keysize, allocsiz;
194     krb5_context context;
195     krb5_keyblock k;
196     krb5_crypto cr;
197     krb5_data plaindata;
198     Ticket t5;                  /* Must free */
199     EncTicketPart decr_part;    /* Must free */
200     int code;
201     size_t siz, plainsiz = 0;
202     int v5_serv_kvno;
203     char *v5_comp0, *v5_comp1, *c;
204     const struct krb_convert *p;
205
206     memset(&t5, 0, sizeof(t5));
207     memset(&decr_part, 0, sizeof(decr_part));
208
209     *host = 0;
210
211     if (ticket_len == 0)
212         return RXKADBADTICKET;  /* no ticket */
213
214     if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) {
215         code = decode_Ticket((unsigned char *)ticket, ticket_len, &t5, &siz);
216         if (code != 0)
217             goto cleanup;
218
219         if (t5.tkt_vno != 5)
220             goto bad_ticket;
221     } else {
222         code = decode_EncryptedData((unsigned char *)ticket, ticket_len, &t5.enc_part, &siz);
223         if (code != 0)
224             goto cleanup;
225     }
226
227     /* If kvno is null, it's probably not included because it was kvno==0
228      * in the ticket */
229     if (t5.enc_part.kvno == NULL) {
230         v5_serv_kvno = 0;
231     } else {
232         v5_serv_kvno = *t5.enc_part.kvno;
233     }
234
235     /* Check that the key type really fit into 8 bytes */
236     switch (t5.enc_part.etype) {
237     case ETYPE_DES_CBC_CRC:
238     case ETYPE_DES_CBC_MD4:
239     case ETYPE_DES_CBC_MD5:
240         /* check ticket */
241         if (t5.enc_part.cipher.length > sizeof(plain)
242             || t5.enc_part.cipher.length % 8 != 0)
243             goto bad_ticket;
244
245         code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key);
246         if (code)
247             goto unknown_key;
248
249         /* Decrypt data here, save in plain, assume it will shrink */
250         code =
251             krb5_des_decrypt(&serv_key, t5.enc_part.etype,
252                              t5.enc_part.cipher.data, t5.enc_part.cipher.length,
253                              plain, &plainsiz);
254         break;
255     default:
256         if (get_key_enctype == NULL)
257             goto unknown_key;
258         code = krb5_init_context(&context);
259         if (code != 0)
260             goto unknown_key;
261         code = krb5_enctype_valid(context, t5.enc_part.etype);
262         if (code != 0) {
263             krb5_free_context(context);
264             goto unknown_key;
265         }
266         code = krb5_enctype_keybits(context,  t5.enc_part.etype, &keysize);
267         if (code != 0) {
268             krb5_free_context(context);
269             goto unknown_key;
270         }
271         keysize = keysize / 8;
272         allocsiz = keysize;
273         keybuf = rxi_Alloc(allocsiz);
274         /* this is not quite a hole for afsconf_GetKeyByTypes. A wrapper
275            that calls afsconf_GetKeyByTypes and afsconf_typedKey_values
276            is needed */
277         code = get_key_enctype(get_key_rock, v5_serv_kvno, t5.enc_part.etype,
278                                keybuf, &keysize);
279         if (code) {
280             rxi_Free(keybuf, allocsiz);
281             krb5_free_context(context);
282             goto unknown_key;
283         }
284         code = krb5_keyblock_init(context, t5.enc_part.etype,
285                                   keybuf, keysize, &k);
286         rxi_Free(keybuf, allocsiz);
287         if (code != 0) {
288             krb5_free_context(context);
289             goto unknown_key;
290         }
291         code = krb5_crypto_init(context, &k, t5.enc_part.etype, &cr);
292         krb5_free_keyblock_contents(context, &k);
293         if (code != 0) {
294             krb5_free_context(context);
295             goto unknown_key;
296         }
297 #ifndef KRB5_KU_TICKET
298 #define KRB5_KU_TICKET 2
299 #endif
300         code = krb5_decrypt(context, cr, KRB5_KU_TICKET, t5.enc_part.cipher.data,
301                             t5.enc_part.cipher.length, &plaindata);
302         krb5_crypto_destroy(context, cr);
303         if (code == 0) {
304             if (plaindata.length > MAXKRB5TICKETLEN) {
305                 krb5_data_free(&plaindata);
306                 krb5_free_context(context);
307                 goto bad_ticket;
308             }
309             memcpy(plain, plaindata.data, plaindata.length);
310             plainsiz = plaindata.length;
311             krb5_data_free(&plaindata);
312         }
313         krb5_free_context(context);
314     }
315
316     if (code != 0)
317         goto bad_ticket;
318
319     /* Decode ticket */
320     code = decode_EncTicketPart((unsigned char *)plain, plainsiz, &decr_part, &siz);
321     if (code != 0)
322         goto bad_ticket;
323
324     /* Extract realm and principal */
325     strncpy(cell, decr_part.crealm, MAXKTCNAMELEN);
326     cell[MAXKTCNAMELEN - 1] = '\0';
327     inst[0] = '\0';
328     switch (decr_part.cname.name_string.len) {
329     case 2:
330         v5_comp0 = decr_part.cname.name_string.val[0];
331         v5_comp1 = decr_part.cname.name_string.val[1];
332         p = sconv_list;
333         while (p->v4_str) {
334             if (strcmp(p->v5_str, v5_comp0) == 0) {
335                 /*
336                  * It is, so set the new name now, and chop off
337                  * instance's domain name if requested.
338                  */
339                 strncpy(name, p->v4_str, MAXKTCNAMELEN);
340                 name[MAXKTCNAMELEN - 1] = '\0';
341                 if (p->flags & DO_REALM_CONVERSION) {
342                     c = strchr(v5_comp1, '.');
343                     if (!c || (c - v5_comp1) >= MAXKTCNAMELEN - 1)
344                         goto bad_ticket;
345                     strncpy(inst, v5_comp1, c - v5_comp1);
346                     inst[c - v5_comp1] = '\0';
347                 }
348                 break;
349             }
350             p++;
351         }
352
353         if (!p->v4_str) {
354             strncpy(inst, decr_part.cname.name_string.val[1], MAXKTCNAMELEN);
355             inst[MAXKTCNAMELEN - 1] = '\0';
356             strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
357             name[MAXKTCNAMELEN - 1] = '\0';
358         }
359         break;
360     case 1:
361         strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
362         name[MAXKTCNAMELEN - 1] = '\0';
363         break;
364     default:
365         goto bad_ticket;
366     }
367
368     if (!disableCheckdot) {
369         /*
370          * If the first part of the name_string contains a dot, punt since
371          * then we can't see the diffrence between the kerberos 5
372          * principals foo.root and foo/root later in the fileserver.
373          */
374         if (strchr(decr_part.cname.name_string.val[0], '.') != NULL)
375             goto bad_ticket;
376     }
377
378     /* Verify that decr_part.key is of right type */
379     if (tkt_DeriveDesKey(decr_part.key.keytype, decr_part.key.keyvalue.data,
380                          decr_part.key.keyvalue.length, session_key) != 0)
381         goto bad_ticket;
382     /* Check lifetimes and host addresses, flags etc */
383     {
384         time_t now = time(0);   /* Use fast time package instead??? */
385         *start = decr_part.authtime;
386         if (decr_part.starttime)
387             *start = *decr_part.starttime;
388 #if 0
389         if (*start - now > CLOCK_SKEW || decr_part.flags.invalid)
390             goto no_auth;
391 #else
392         if (decr_part.flags.invalid)
393             goto no_auth;
394 #endif
395         if (now > decr_part.endtime)
396             goto tkt_expired;
397         *end = decr_part.endtime;
398     }
399
400   cleanup:
401     if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
402         free_Ticket(&t5);
403     else
404         free_EncryptedData(&t5.enc_part);
405     free_EncTicketPart(&decr_part);
406     memset(&serv_key, 0, sizeof(serv_key));
407     return code;
408
409   unknown_key:
410     code = RXKADUNKNOWNKEY;
411     goto cleanup;
412   no_auth:
413     code = RXKADNOAUTH;
414     goto cleanup;
415   tkt_expired:
416     code = RXKADEXPIRED;
417     goto cleanup;
418   bad_ticket:
419     code = RXKADBADTICKET;
420     goto cleanup;
421
422 }
423
424 static int
425 verify_checksum_md4(void *data, size_t len,
426                     void *cksum, size_t cksumsz,
427                     struct ktc_encryptionKey *key)
428 {
429     MD4_CTX md4;
430     unsigned char tmp[16];
431
432     MD4_Init(&md4);
433     MD4_Update(&md4, data, len);
434     MD4_Final(tmp, &md4);
435
436     if (memcmp(tmp, cksum, cksumsz) != 0)
437         return 1;
438     return 0;
439 }
440
441 static int
442 verify_checksum_md5(void *data, size_t len,
443                     void *cksum, size_t cksumsz,
444                     struct ktc_encryptionKey *key)
445 {
446     MD5_CTX md5;
447     unsigned char tmp[16];
448
449     MD5_Init(&md5);
450     MD5_Update(&md5, data, len);
451     MD5_Final(tmp, &md5);
452
453     if (memcmp(tmp, cksum, cksumsz) != 0)
454         return 1;
455     return 0;
456 }
457
458 static int
459 verify_checksum_crc(void *data, size_t len, void *cksum, size_t cksumsz,
460                     struct ktc_encryptionKey *key)
461 {
462     afs_uint32 crc;
463     char r[4];
464
465     _rxkad_crc_init_table();
466     crc = _rxkad_crc_update(data, len, 0);
467     r[0] = crc & 0xff;
468     r[1] = (crc >> 8) & 0xff;
469     r[2] = (crc >> 16) & 0xff;
470     r[3] = (crc >> 24) & 0xff;
471
472     if (memcmp(cksum, r, 4) != 0)
473         return 1;
474     return 0;
475 }
476
477
478 static int
479 krb5_des_decrypt(struct ktc_encryptionKey *key, int etype, void *in,
480                  size_t insz, void *out, size_t * outsz)
481 {
482     int (*cksum_func) (void *, size_t, void *, size_t,
483                        struct ktc_encryptionKey *);
484     DES_cblock ivec;
485     DES_key_schedule s;
486     char cksum[24];
487     size_t cksumsz;
488     int ret = 1;                /* failure */
489
490     cksum_func = NULL;
491
492     DES_key_sched(ktc_to_cblock(key), &s);
493
494 #define CONFOUNDERSZ 8
495
496     switch (etype) {
497     case ETYPE_DES_CBC_CRC:
498         memcpy(&ivec, key, sizeof(ivec));
499         cksumsz = 4;
500         cksum_func = verify_checksum_crc;
501         break;
502     case ETYPE_DES_CBC_MD4:
503         memset(&ivec, 0, sizeof(ivec));
504         cksumsz = 16;
505         cksum_func = verify_checksum_md4;
506         break;
507     case ETYPE_DES_CBC_MD5:
508         memset(&ivec, 0, sizeof(ivec));
509         cksumsz = 16;
510         cksum_func = verify_checksum_md5;
511         break;
512     default:
513         abort();
514     }
515
516     DES_cbc_encrypt(in, out, insz, &s, &ivec, 0);
517
518     memcpy(cksum, (char *)out + CONFOUNDERSZ, cksumsz);
519     memset((char *)out + CONFOUNDERSZ, 0, cksumsz);
520
521     if (cksum_func)
522         ret = (*cksum_func) (out, insz, cksum, cksumsz, key);
523
524     *outsz = insz - CONFOUNDERSZ - cksumsz;
525     memmove(out, (char *)out + CONFOUNDERSZ + cksumsz, *outsz);
526
527     return ret;
528 }
529
530 int
531 tkt_MakeTicket5(char *ticket, int *ticketLen, int enctype, int *kvno,
532                 void *key, size_t keylen,
533                 char *name, char *inst, char *cell, afs_uint32 start,
534                 afs_uint32 end, struct ktc_encryptionKey *sessionKey,
535                 char *sname, char *sinst)
536 {
537     EncTicketPart data;
538     EncryptedData encdata;
539     unsigned char *buf, *encodebuf;
540     size_t encodelen, allocsiz;
541     heim_general_string carray[2];
542     int code;
543     krb5_context context;
544     krb5_keyblock kb;
545     krb5_crypto cr;
546     krb5_data encrypted;
547     size_t tl;
548
549     memset(&encrypted, 0, sizeof(encrypted));
550     cr = NULL;
551     context = NULL;
552     buf = NULL;
553     memset(&kb, 0, sizeof(kb));
554     memset(&data, 0, sizeof(data));
555
556     data.flags.transited_policy_checked = 1;
557     data.key.keytype=ETYPE_DES_CBC_CRC;
558     data.key.keyvalue.data=sessionKey->data;
559     data.key.keyvalue.length=8;
560     data.crealm=cell;
561     carray[0]=name;
562     carray[1]=inst;
563     data.cname.name_type=KRB5_NT_PRINCIPAL;
564     data.cname.name_string.val=carray;
565     data.cname.name_string.len=inst[0]?2:1;
566     data.authtime=start;
567     data.endtime=end;
568
569     allocsiz = length_EncTicketPart(&data);
570     buf = rxi_Alloc(allocsiz);
571     encodelen = allocsiz;
572     /* encode function wants pointer to end of buffer */
573     encodebuf = buf + allocsiz - 1;
574     code = encode_EncTicketPart(encodebuf, allocsiz, &data, &encodelen);
575
576     if (code)
577         goto cleanup;
578     code = krb5_init_context(&context);
579     if (code)
580         goto cleanup;
581     code = krb5_keyblock_init(context, enctype, key, keylen, &kb);
582     if (code)
583         goto cleanup;
584     code = krb5_crypto_init(context, &kb, enctype, &cr);
585     if (code)
586         goto cleanup;
587     code = krb5_encrypt(context, cr, KRB5_KU_TICKET, buf,
588                         encodelen, &encrypted);
589     if (code)
590         goto cleanup;
591     memset(&encdata, 0, sizeof(encdata));
592     encdata.etype=enctype;
593     encdata.kvno=kvno;
594     encdata.cipher.data=encrypted.data;
595     encdata.cipher.length=encrypted.length;
596
597     if (length_EncryptedData(&encdata) > *ticketLen) {
598         code = RXKADTICKETLEN;
599         goto cleanup;
600     }
601     tl=*ticketLen;
602     code = encode_EncryptedData((unsigned char *)ticket + *ticketLen - 1, *ticketLen, &encdata, &tl);
603     if (code == 0) {
604         *kvno=RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY;
605         /*
606          * encode function fills in from the end. move data to
607          * beginning of buffer
608          */
609         memmove(ticket, ticket + *ticketLen - tl, tl);
610         *ticketLen=tl;
611     }
612
613 cleanup:
614     krb5_data_free(&encrypted);
615     if (cr != NULL)
616         krb5_crypto_destroy(context, cr);
617     krb5_free_keyblock_contents(context, &kb);
618     if (context != NULL) {
619         krb5_free_context(context);
620     }
621     rxi_Free(buf, allocsiz);
622     if ((code & 0xFFFFFF00) == ERROR_TABLE_BASE_asn1)
623         return RXKADINCONSISTENCY;
624     return code;
625 }
626
627 /*
628  * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
629  * des key from another type of key.
630  *
631  * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
632  * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
633  * properly should be 1.  However, we apply a slight variation due to the
634  * possibility of producing a weak des key.  If the output key is weak, do NOT
635  * simply correct it, instead, the counter is advanced and the next output
636  * used.  As such, we code so as to have n be the full 255 permitted by our
637  * encoding of the counter i in an 8-bit field.  L itself is encoded as a
638  * 32-bit field, big-endian.  We use the constant string "rxkad" as a label
639  * for this key derivation, the standard NUL byte separator, and omit a
640  * key-derivation context.  The input key is unique to the krb5 service ticket,
641  * which is unlikely to be used in an other location.  If it is used in such
642  * a fashion, both locations will derive the same des key from the PRF, but
643  * this is no different from if a krb5 des key had been used in the same way,
644  * as traditional krb5 rxkad uses the ticket session key directly as the token
645  * key.
646  */
647 static int
648 rxkad_derive_des_key(const void *in, size_t insize,
649                      struct ktc_encryptionKey *out)
650 {
651     unsigned char i;
652     char Lbuf[4];               /* bits of output, as 32 bit word, MSB first */
653     char tmp[64];               /* only needs to be 16 for md5, but lets be sure it fits */
654     unsigned int mdsize;
655     DES_cblock ktmp;
656     HMAC_CTX mctx;
657
658     Lbuf[0] = 0;
659     Lbuf[1] = 0;
660     Lbuf[2] = 0;
661     Lbuf[3] = 64;
662
663     /* stop when 8 bit counter wraps to 0 */
664     for (i = 1; i; i++) {
665         HMAC_CTX_init(&mctx);
666         HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL);
667         HMAC_Update(&mctx, &i, 1);
668         HMAC_Update(&mctx, "rxkad", strlen("rxkad") + 1);   /* includes label and separator */
669         HMAC_Update(&mctx, Lbuf, 4);
670         mdsize = sizeof(tmp);
671         HMAC_Final(&mctx, tmp, &mdsize);
672         memcpy(ktmp, tmp, 8);
673         DES_set_odd_parity(&ktmp);
674         if (!DES_is_weak_key(&ktmp)) {
675             memcpy(out->data, ktmp, 8);
676             return 0;
677         }
678     }
679     return -1;
680 }
681
682 /*
683  * This is the inverse of the random-to-key for 3des specified in
684  * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing
685  * the bits of each 8th byte as the lsb of the previous 7 bytes.
686  */
687 static int
688 compress_parity_bits(void *buffer, size_t *bufsiz)
689 {
690     unsigned char *cb, tmp;
691     int i, j, nk;
692
693     if (*bufsiz % 8 != 0)
694         return 1;
695     cb = (unsigned char *)buffer;
696     nk = *bufsiz / 8;
697     for (i = 0; i < nk; i++) {
698         tmp = cb[8 * i + 7] >> 1;
699         for (j = 0; j < 7; j++) {
700             cb[8 * i + j] &= 0xfe;
701             cb[8 * i + j] |= tmp & 0x1;
702             tmp >>= 1;
703         }
704     }
705     for (i = 1; i < nk; i++)
706         memmove(cb + 7 * i, cb + 8 * i, 7);
707     *bufsiz = 7 * nk;
708     return 0;
709 }
710
711 /*
712  * Enctype-specific knowledge about how to derive a des key from a given
713  * key.  If given a des key, use it directly; otherwise, perform any
714  * parity fixup that may be needed and pass through to the hmad-md5 bits.
715  */
716 int
717 tkt_DeriveDesKey(int enctype, void *keydata, size_t keylen,
718                  struct ktc_encryptionKey *output)
719 {
720     switch (enctype) {
721     case ETYPE_DES_CBC_CRC:
722     case ETYPE_DES_CBC_MD4:
723     case ETYPE_DES_CBC_MD5:
724         if (keylen != 8)
725             return 1;
726
727         /* Extract session key */
728         memcpy(output, keydata, 8);
729         break;
730     case ETYPE_NULL:
731     case 4:
732     case 6:
733     case 8:
734     case 9:
735     case 10:
736     case 11:
737     case 12:
738     case 13:
739     case 14:
740     case 15:
741         return 1;
742         /*In order to become a "Cryptographic Key" as specified in
743          * SP800-108, it must be indistinguishable from a random bitstring. */
744     case ETYPE_DES3_CBC_MD5:
745     case ETYPE_OLD_DES3_CBC_SHA1:
746     case ETYPE_DES3_CBC_SHA1:
747         if (compress_parity_bits(keydata, &keylen))
748             return 1;
749         /* FALLTHROUGH */
750     default:
751         if (enctype < 0)
752             return 1;
753         if (keylen < 7)
754             return 1;
755         if (rxkad_derive_des_key(keydata, keylen, output) != 0)
756             return 1;
757     }
758     return 0;
759 }