crypto.c revision 55682
1/*
2 * Copyright (c) 1997, 1998, 1999 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#include "krb5_locl.h"
35RCSID("$Id: crypto.c,v 1.28 2000/01/06 20:21:13 assar Exp $");
36
37#undef CRYPTO_DEBUG
38#ifdef CRYPTO_DEBUG
39static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
40#endif
41
42
43struct key_data {
44    krb5_keyblock *key;
45    krb5_data *schedule;
46};
47
48struct key_usage {
49    unsigned usage;
50    struct key_data key;
51};
52
53struct krb5_crypto_data {
54    struct encryption_type *et;
55    struct key_data key;
56    int num_key_usage;
57    struct key_usage *key_usage;
58};
59
60#define CRYPTO_ETYPE(C) ((C)->et->type)
61
62/* bits for `flags' below */
63#define F_KEYED		 1	/* checksum is keyed */
64#define F_CPROOF	 2	/* checksum is collision proof */
65#define F_DERIVED	 4	/* uses derived keys */
66#define F_VARIANT	 8	/* uses `variant' keys (6.4.3) */
67#define F_PSEUDO	16	/* not a real protocol type */
68
69struct salt_type {
70    krb5_salttype type;
71    const char *name;
72    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
73				     krb5_salt, krb5_keyblock*);
74};
75
76struct key_type {
77    krb5_keytype type; /* XXX */
78    const char *name;
79    size_t bits;
80    size_t size;
81    size_t schedule_size;
82#if 0
83    krb5_enctype best_etype;
84#endif
85    void (*random_key)(krb5_context, krb5_keyblock*);
86    void (*schedule)(krb5_context, struct key_data *);
87    struct salt_type *string_to_key;
88};
89
90struct checksum_type {
91    krb5_cksumtype type;
92    const char *name;
93    size_t blocksize;
94    size_t checksumsize;
95    unsigned flags;
96    void (*checksum)(krb5_context, struct key_data*, void*, size_t, Checksum*);
97    krb5_error_code (*verify)(krb5_context, struct key_data*,
98			      void*, size_t, Checksum*);
99};
100
101struct encryption_type {
102    krb5_enctype type;
103    const char *name;
104    size_t blocksize;
105    size_t confoundersize;
106    struct key_type *keytype;
107    struct checksum_type *cksumtype;
108    struct checksum_type *keyed_checksum;
109    unsigned flags;
110    void (*encrypt)(struct key_data *, void *, size_t, int);
111};
112
113#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
114#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
115#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
116
117static struct checksum_type *_find_checksum(krb5_cksumtype type);
118static struct encryption_type *_find_enctype(krb5_enctype type);
119static struct key_type *_find_keytype(krb5_keytype type);
120static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
121					unsigned, struct key_data**);
122static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
123
124/************************************************************
125 *                                                          *
126 ************************************************************/
127
128static void
129DES_random_key(krb5_context context,
130	       krb5_keyblock *key)
131{
132    des_cblock *k = key->keyvalue.data;
133    do {
134	krb5_generate_random_block(k, sizeof(des_cblock));
135	des_set_odd_parity(k);
136    } while(des_is_weak_key(k));
137}
138
139static void
140DES_schedule(krb5_context context,
141	     struct key_data *key)
142{
143    des_set_key(key->key->keyvalue.data, key->schedule->data);
144}
145
146static krb5_error_code
147DES_string_to_key(krb5_context context,
148		  krb5_enctype enctype,
149		  krb5_data password,
150		  krb5_salt salt,
151		  krb5_keyblock *key)
152{
153    char *s;
154    size_t len;
155    des_cblock tmp;
156
157    len = password.length + salt.saltvalue.length + 1;
158    s = malloc(len);
159    if(s == NULL)
160	return ENOMEM;
161    memcpy(s, password.data, password.length);
162    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
163    s[len - 1] = '\0';
164    des_string_to_key(s, &tmp);
165    key->keytype = enctype;
166    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
167    memset(&tmp, 0, sizeof(tmp));
168    memset(s, 0, len);
169    free(s);
170    return 0;
171}
172
173/* This defines the Andrew string_to_key function.  It accepts a password
174 * string as input and converts its via a one-way encryption algorithm to a DES
175 * encryption key.  It is compatible with the original Andrew authentication
176 * service password database.
177 */
178
179/*
180 * Short passwords, i.e 8 characters or less.
181 */
182static void
183DES_AFS3_CMU_string_to_key (krb5_data pw,
184			    krb5_data cell,
185			    des_cblock *key)
186{
187    char  password[8+1];	/* crypt is limited to 8 chars anyway */
188    int   i;
189
190    for(i = 0; i < 8; i++) {
191	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
192		 ((i < cell.length) ? ((char*)cell.data)[i] : 0);
193	password[i] = c ? c : 'X';
194    }
195    password[8] = '\0';
196
197    memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
198
199    /* parity is inserted into the LSB so left shift each byte up one
200       bit. This allows ascii characters with a zero MSB to retain as
201       much significance as possible. */
202    for (i = 0; i < sizeof(des_cblock); i++)
203	((unsigned char*)key)[i] <<= 1;
204    des_set_odd_parity (key);
205}
206
207/*
208 * Long passwords, i.e 9 characters or more.
209 */
210static void
211DES_AFS3_Transarc_string_to_key (krb5_data pw,
212				 krb5_data cell,
213				 des_cblock *key)
214{
215    des_key_schedule schedule;
216    des_cblock temp_key;
217    des_cblock ivec;
218    char password[512];
219    size_t passlen;
220
221    memcpy(password, pw.data, min(pw.length, sizeof(password)));
222    if(pw.length < sizeof(password))
223	memcpy(password + pw.length,
224	       cell.data, min(cell.length,
225			      sizeof(password) - pw.length));
226    passlen = min(sizeof(password), pw.length + cell.length);
227    memcpy(&ivec, "kerberos", 8);
228    memcpy(&temp_key, "kerberos", 8);
229    des_set_odd_parity (&temp_key);
230    des_set_key (&temp_key, schedule);
231    des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
232
233    memcpy(&temp_key, &ivec, 8);
234    des_set_odd_parity (&temp_key);
235    des_set_key (&temp_key, schedule);
236    des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
237    memset(&schedule, 0, sizeof(schedule));
238    memset(&temp_key, 0, sizeof(temp_key));
239    memset(&ivec, 0, sizeof(ivec));
240    memset(password, 0, sizeof(password));
241
242    des_set_odd_parity (key);
243}
244
245static krb5_error_code
246DES_AFS3_string_to_key(krb5_context context,
247		       krb5_enctype enctype,
248		       krb5_data password,
249		       krb5_salt salt,
250		       krb5_keyblock *key)
251{
252    des_cblock tmp;
253    if(password.length > 8)
254	DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
255    else
256	DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
257    key->keytype = enctype;
258    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
259    memset(&key, 0, sizeof(key));
260    return 0;
261}
262
263static void
264DES3_random_key(krb5_context context,
265		krb5_keyblock *key)
266{
267    des_cblock *k = key->keyvalue.data;
268    do {
269	krb5_generate_random_block(k, 3 * sizeof(des_cblock));
270	des_set_odd_parity(&k[0]);
271	des_set_odd_parity(&k[1]);
272	des_set_odd_parity(&k[2]);
273    } while(des_is_weak_key(&k[0]) ||
274	    des_is_weak_key(&k[1]) ||
275	    des_is_weak_key(&k[2]));
276}
277
278static void
279DES3_schedule(krb5_context context,
280	      struct key_data *key)
281{
282    des_cblock *k = key->key->keyvalue.data;
283    des_key_schedule *s = key->schedule->data;
284    des_set_key(&k[0], s[0]);
285    des_set_key(&k[1], s[1]);
286    des_set_key(&k[2], s[2]);
287}
288
289/*
290 * A = A xor B. A & B are 8 bytes.
291 */
292
293static void
294xor (des_cblock *key, const unsigned char *b)
295{
296    unsigned char *a = (unsigned char*)key;
297    a[0] ^= b[0];
298    a[1] ^= b[1];
299    a[2] ^= b[2];
300    a[3] ^= b[3];
301    a[4] ^= b[4];
302    a[5] ^= b[5];
303    a[6] ^= b[6];
304    a[7] ^= b[7];
305}
306
307static krb5_error_code
308DES3_string_to_key(krb5_context context,
309		   krb5_enctype enctype,
310		   krb5_data password,
311		   krb5_salt salt,
312		   krb5_keyblock *key)
313{
314    char *str;
315    size_t len;
316    unsigned char tmp[24];
317    des_cblock keys[3];
318
319    len = password.length + salt.saltvalue.length;
320    str = malloc(len);
321    if(len != 0 && str == NULL)
322	return ENOMEM;
323    memcpy(str, password.data, password.length);
324    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
325    {
326	des_cblock ivec;
327	des_key_schedule s[3];
328	int i;
329
330	_krb5_n_fold(str, len, tmp, 24);
331
332	for(i = 0; i < 3; i++){
333	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
334	    des_set_odd_parity(keys + i);
335	    if(des_is_weak_key(keys + i))
336		xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
337	    des_set_key(keys + i, s[i]);
338	}
339	memset(&ivec, 0, sizeof(ivec));
340	des_ede3_cbc_encrypt((void*)tmp, (void*)tmp, sizeof(tmp),
341			     s[0], s[1], s[2], &ivec, DES_ENCRYPT);
342	memset(s, 0, sizeof(s));
343	memset(&ivec, 0, sizeof(ivec));
344	for(i = 0; i < 3; i++){
345	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
346	    des_set_odd_parity(keys + i);
347	    if(des_is_weak_key(keys + i))
348		xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
349	}
350	memset(tmp, 0, sizeof(tmp));
351    }
352    key->keytype = enctype;
353    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
354    memset(keys, 0, sizeof(keys));
355    memset(str, 0, len);
356    free(str);
357    return 0;
358}
359
360static krb5_error_code
361DES3_string_to_key_derived(krb5_context context,
362			   krb5_enctype enctype,
363			   krb5_data password,
364			   krb5_salt salt,
365			   krb5_keyblock *key)
366{
367    krb5_error_code ret;
368    size_t len = password.length + salt.saltvalue.length;
369    char *s;
370
371    s = malloc(len);
372    if(len != 0 && s == NULL)
373	return ENOMEM;
374    memcpy(s, password.data, password.length);
375    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
376    ret = krb5_string_to_key_derived(context,
377				     s,
378				     len,
379				     enctype,
380				     key);
381    memset(s, 0, len);
382    free(s);
383    return ret;
384}
385
386/*
387 * ARCFOUR
388 */
389
390static void
391ARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
392{
393    krb5_generate_random_block (key->keyvalue.data,
394				key->keyvalue.length);
395}
396
397static void
398ARCFOUR_schedule(krb5_context context, struct key_data *kd)
399{
400    RC4_set_key (kd->schedule->data,
401		 kd->key->keyvalue.length, kd->key->keyvalue.data);
402}
403
404static krb5_error_code
405ARCFOUR_string_to_key(krb5_context context,
406		  krb5_enctype enctype,
407		  krb5_data password,
408		  krb5_salt salt,
409		  krb5_keyblock *key)
410{
411    char *s, *p;
412    size_t len;
413    int i;
414    struct md4 m;
415
416    len = 2 * (password.length + salt.saltvalue.length);
417    s = malloc (len);
418    if (len != 0 && s == NULL)
419	return ENOMEM;
420    for (p = s, i = 0; i < password.length; ++i) {
421	*p++ = ((char *)password.data)[i];
422	*p++ = 0;
423    }
424    for (i = 0; i < salt.saltvalue.length; ++i) {
425	*p++ = ((char *)salt.saltvalue.data)[i];
426	*p++ = 0;
427    }
428    md4_init(&m);
429    md4_update(&m, s, len);
430    key->keytype = enctype;
431    krb5_data_alloc (&key->keyvalue, 16);
432    md4_finito(&m, key->keyvalue.data);
433    memset (s, 0, len);
434    free (s);
435    return 0;
436}
437
438extern struct salt_type des_salt[],
439    des3_salt[], des3_salt_derived[], arcfour_salt[];
440
441struct key_type keytype_null = {
442    KEYTYPE_NULL,
443    "null",
444    0,
445    0,
446    0,
447    NULL,
448    NULL,
449    NULL
450};
451
452struct key_type keytype_des = {
453    KEYTYPE_DES,
454    "des",
455    56,
456    sizeof(des_cblock),
457    sizeof(des_key_schedule),
458    DES_random_key,
459    DES_schedule,
460    des_salt
461};
462
463struct key_type keytype_des3 = {
464    KEYTYPE_DES3,
465    "des3",
466    168,
467    3 * sizeof(des_cblock),
468    3 * sizeof(des_key_schedule),
469    DES3_random_key,
470    DES3_schedule,
471    des3_salt
472};
473
474struct key_type keytype_des3_derived = {
475    KEYTYPE_DES3,
476    "des3",
477    168,
478    3 * sizeof(des_cblock),
479    3 * sizeof(des_key_schedule),
480    DES3_random_key,
481    DES3_schedule,
482    des3_salt_derived
483};
484
485struct key_type keytype_arcfour = {
486    KEYTYPE_ARCFOUR,
487    "arcfour",
488    128,
489    16,
490    sizeof(RC4_KEY),
491    ARCFOUR_random_key,
492    ARCFOUR_schedule,
493    arcfour_salt
494};
495
496struct key_type *keytypes[] = {
497    &keytype_null,
498    &keytype_des,
499    &keytype_des3_derived,
500    &keytype_des3,
501    &keytype_arcfour
502};
503
504static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
505
506static struct key_type *
507_find_keytype(krb5_keytype type)
508{
509    int i;
510    for(i = 0; i < num_keytypes; i++)
511	if(keytypes[i]->type == type)
512	    return keytypes[i];
513    return NULL;
514}
515
516
517struct salt_type des_salt[] = {
518    {
519	KRB5_PW_SALT,
520	"pw-salt",
521	DES_string_to_key
522    },
523    {
524	KRB5_AFS3_SALT,
525	"afs3-salt",
526	DES_AFS3_string_to_key
527    },
528    { 0 }
529};
530
531struct salt_type des3_salt[] = {
532    {
533	KRB5_PW_SALT,
534	"pw-salt",
535	DES3_string_to_key
536    },
537    { 0 }
538};
539
540struct salt_type des3_salt_derived[] = {
541    {
542	KRB5_PW_SALT,
543	"pw-salt",
544	DES3_string_to_key_derived
545    },
546    { 0 }
547};
548
549struct salt_type arcfour_salt[] = {
550    {
551	KRB5_PW_SALT,
552	"pw-salt",
553	ARCFOUR_string_to_key
554    },
555    { 0 }
556};
557
558krb5_error_code
559krb5_salttype_to_string (krb5_context context,
560			 krb5_enctype etype,
561			 krb5_salttype stype,
562			 char **string)
563{
564    struct encryption_type *e;
565    struct salt_type *st;
566
567    e = _find_enctype (etype);
568    if (e == NULL)
569	return KRB5_PROG_ETYPE_NOSUPP;
570    for (st = e->keytype->string_to_key; st && st->type; st++) {
571	if (st->type == stype) {
572	    *string = strdup (st->name);
573	    if (*string == NULL)
574		return ENOMEM;
575	    return 0;
576	}
577    }
578    return HEIM_ERR_SALTTYPE_NOSUPP;
579}
580
581krb5_error_code
582krb5_string_to_salttype (krb5_context context,
583			 krb5_enctype etype,
584			 const char *string,
585			 krb5_salttype *salttype)
586{
587    struct encryption_type *e;
588    struct salt_type *st;
589
590    e = _find_enctype (etype);
591    if (e == NULL)
592	return KRB5_PROG_ETYPE_NOSUPP;
593    for (st = e->keytype->string_to_key; st && st->type; st++) {
594	if (strcasecmp (st->name, string) == 0) {
595	    *salttype = st->type;
596	    return 0;
597	}
598    }
599    return HEIM_ERR_SALTTYPE_NOSUPP;
600}
601
602krb5_error_code
603krb5_get_pw_salt(krb5_context context,
604		 krb5_const_principal principal,
605		 krb5_salt *salt)
606{
607    size_t len;
608    int i;
609    krb5_error_code ret;
610    char *p;
611
612    salt->salttype = KRB5_PW_SALT;
613    len = strlen(principal->realm);
614    for (i = 0; i < principal->name.name_string.len; ++i)
615	len += strlen(principal->name.name_string.val[i]);
616    ret = krb5_data_alloc (&salt->saltvalue, len);
617    if (ret)
618	return ret;
619    p = salt->saltvalue.data;
620    memcpy (p, principal->realm, strlen(principal->realm));
621    p += strlen(principal->realm);
622    for (i = 0; i < principal->name.name_string.len; ++i) {
623	memcpy (p,
624		principal->name.name_string.val[i],
625		strlen(principal->name.name_string.val[i]));
626	p += strlen(principal->name.name_string.val[i]);
627    }
628    return 0;
629}
630
631krb5_error_code
632krb5_free_salt(krb5_context context,
633	       krb5_salt salt)
634{
635    krb5_data_free(&salt.saltvalue);
636    return 0;
637}
638
639krb5_error_code
640krb5_string_to_key_data (krb5_context context,
641			 krb5_enctype enctype,
642			 krb5_data password,
643			 krb5_principal principal,
644			 krb5_keyblock *key)
645{
646    krb5_error_code ret;
647    krb5_salt salt;
648
649    ret = krb5_get_pw_salt(context, principal, &salt);
650    if(ret)
651	return ret;
652    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
653    krb5_free_salt(context, salt);
654    return ret;
655}
656
657krb5_error_code
658krb5_string_to_key (krb5_context context,
659		    krb5_enctype enctype,
660		    const char *password,
661		    krb5_principal principal,
662		    krb5_keyblock *key)
663{
664    krb5_data pw;
665    pw.data = (void*)password;
666    pw.length = strlen(password);
667    return krb5_string_to_key_data(context, enctype, pw, principal, key);
668}
669
670krb5_error_code
671krb5_string_to_key_data_salt (krb5_context context,
672			      krb5_enctype enctype,
673			      krb5_data password,
674			      krb5_salt salt,
675			      krb5_keyblock *key)
676{
677    struct encryption_type *et =_find_enctype(enctype);
678    struct salt_type *st;
679    if(et == NULL)
680	return KRB5_PROG_ETYPE_NOSUPP;
681    for(st = et->keytype->string_to_key; st && st->type; st++)
682	if(st->type == salt.salttype)
683	    return (*st->string_to_key)(context, enctype, password, salt, key);
684    return HEIM_ERR_SALTTYPE_NOSUPP;
685}
686
687krb5_error_code
688krb5_string_to_key_salt (krb5_context context,
689			 krb5_enctype enctype,
690			 const char *password,
691			 krb5_salt salt,
692			 krb5_keyblock *key)
693{
694    krb5_data pw;
695    pw.data = (void*)password;
696    pw.length = strlen(password);
697    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
698}
699
700krb5_error_code
701krb5_keytype_to_string(krb5_context context,
702		       krb5_keytype keytype,
703		       char **string)
704{
705    struct key_type *kt = _find_keytype(keytype);
706    if(kt == NULL)
707	return KRB5_PROG_KEYTYPE_NOSUPP;
708    *string = strdup(kt->name);
709    if(*string == NULL)
710	return ENOMEM;
711    return 0;
712}
713
714krb5_error_code
715krb5_string_to_keytype(krb5_context context,
716		       const char *string,
717		       krb5_keytype *keytype)
718{
719    int i;
720    for(i = 0; i < num_keytypes; i++)
721	if(strcasecmp(keytypes[i]->name, string) == 0){
722	    *keytype = keytypes[i]->type;
723	    return 0;
724	}
725    return KRB5_PROG_KEYTYPE_NOSUPP;
726}
727
728krb5_error_code
729krb5_generate_random_keyblock(krb5_context context,
730			      krb5_enctype type,
731			      krb5_keyblock *key)
732{
733    krb5_error_code ret;
734    struct encryption_type *et = _find_enctype(type);
735    if(et == NULL)
736	return KRB5_PROG_ETYPE_NOSUPP;
737    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
738    if(ret)
739	return ret;
740    key->keytype = type;
741    if(et->keytype->random_key)
742	(*et->keytype->random_key)(context, key);
743    else
744	krb5_generate_random_block(key->keyvalue.data,
745				   key->keyvalue.length);
746    return 0;
747}
748
749static krb5_error_code
750_key_schedule(krb5_context context,
751	      struct key_data *key)
752{
753    krb5_error_code ret;
754    struct encryption_type *et = _find_enctype(key->key->keytype);
755    struct key_type *kt = et->keytype;
756
757    if(kt->schedule == NULL)
758	return 0;
759    ALLOC(key->schedule, 1);
760    if(key->schedule == NULL)
761	return ENOMEM;
762    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
763    if(ret) {
764	free(key->schedule);
765	key->schedule = NULL;
766	return ret;
767    }
768    (*kt->schedule)(context, key);
769    return 0;
770}
771
772/************************************************************
773 *                                                          *
774 ************************************************************/
775
776static void
777NONE_checksum(krb5_context context,
778	      struct key_data *key,
779	      void *data,
780	      size_t len,
781	      Checksum *C)
782{
783}
784
785static void
786CRC32_checksum(krb5_context context,
787	       struct key_data *key,
788	       void *data,
789	       size_t len,
790	       Checksum *C)
791{
792    u_int32_t crc;
793    unsigned char *r = C->checksum.data;
794    _krb5_crc_init_table ();
795    crc = _krb5_crc_update (data, len, 0);
796    r[0] = crc & 0xff;
797    r[1] = (crc >> 8)  & 0xff;
798    r[2] = (crc >> 16) & 0xff;
799    r[3] = (crc >> 24) & 0xff;
800}
801
802static void
803RSA_MD4_checksum(krb5_context context,
804		 struct key_data *key,
805		 void *data,
806		 size_t len,
807		 Checksum *C)
808{
809    struct md4 m;
810    md4_init(&m);
811    md4_update(&m, data, len);
812    md4_finito(&m, C->checksum.data);
813}
814
815static void
816RSA_MD4_DES_checksum(krb5_context context,
817		     struct key_data *key,
818		     void *data,
819		     size_t len,
820		     Checksum *cksum)
821{
822    struct md4 md4;
823    des_cblock ivec;
824    unsigned char *p = cksum->checksum.data;
825
826    krb5_generate_random_block(p, 8);
827    md4_init(&md4);
828    md4_update(&md4, p, 8);
829    md4_update(&md4, data, len);
830    md4_finito(&md4, p + 8);
831    memset (&ivec, 0, sizeof(ivec));
832    des_cbc_encrypt((des_cblock*)p,
833		    (des_cblock*)p,
834		    24,
835		    key->schedule->data,
836		    &ivec,
837		    DES_ENCRYPT);
838}
839
840static krb5_error_code
841RSA_MD4_DES_verify(krb5_context context,
842		   struct key_data *key,
843		   void *data,
844		   size_t len,
845		   Checksum *C)
846{
847    struct md4 md4;
848    unsigned char tmp[24];
849    unsigned char res[16];
850    des_cblock ivec;
851    krb5_error_code ret = 0;
852
853    memset(&ivec, 0, sizeof(ivec));
854    des_cbc_encrypt(C->checksum.data,
855		    (void*)tmp,
856		    C->checksum.length,
857		    key->schedule->data,
858		    &ivec,
859		    DES_DECRYPT);
860    md4_init(&md4);
861    md4_update(&md4, tmp, 8); /* confounder */
862    md4_update(&md4, data, len);
863    md4_finito(&md4, res);
864    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
865	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
866    memset(tmp, 0, sizeof(tmp));
867    memset(res, 0, sizeof(res));
868    return ret;
869}
870
871static void
872RSA_MD5_checksum(krb5_context context,
873		 struct key_data *key,
874		 void *data,
875		 size_t len,
876		 Checksum *C)
877{
878    struct md5 m;
879    md5_init(&m);
880    md5_update(&m, data, len);
881    md5_finito(&m, C->checksum.data);
882}
883
884static void
885RSA_MD5_DES_checksum(krb5_context context,
886		     struct key_data *key,
887		     void *data,
888		     size_t len,
889		     Checksum *C)
890{
891    struct md5 md5;
892    des_cblock ivec;
893    unsigned char *p = C->checksum.data;
894
895    krb5_generate_random_block(p, 8);
896    md5_init(&md5);
897    md5_update(&md5, p, 8);
898    md5_update(&md5, data, len);
899    md5_finito(&md5, p + 8);
900    memset (&ivec, 0, sizeof(ivec));
901    des_cbc_encrypt((des_cblock*)p,
902		    (des_cblock*)p,
903		    24,
904		    key->schedule->data,
905		    &ivec,
906		    DES_ENCRYPT);
907}
908
909static krb5_error_code
910RSA_MD5_DES_verify(krb5_context context,
911		   struct key_data *key,
912		   void *data,
913		   size_t len,
914		   Checksum *C)
915{
916    struct md5 md5;
917    unsigned char tmp[24];
918    unsigned char res[16];
919    des_cblock ivec;
920    des_key_schedule *sched = key->schedule->data;
921    krb5_error_code ret = 0;
922
923    memset(&ivec, 0, sizeof(ivec));
924    des_cbc_encrypt(C->checksum.data,
925		    (void*)tmp,
926		    C->checksum.length,
927		    sched[0],
928		    &ivec,
929		    DES_DECRYPT);
930    md5_init(&md5);
931    md5_update(&md5, tmp, 8); /* confounder */
932    md5_update(&md5, data, len);
933    md5_finito(&md5, res);
934    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
935	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
936    memset(tmp, 0, sizeof(tmp));
937    memset(res, 0, sizeof(res));
938    return ret;
939}
940
941static void
942RSA_MD5_DES3_checksum(krb5_context context,
943		      struct key_data *key,
944		      void *data,
945		      size_t len,
946		      Checksum *C)
947{
948    struct md5 md5;
949    des_cblock ivec;
950    unsigned char *p = C->checksum.data;
951    des_key_schedule *sched = key->schedule->data;
952
953    krb5_generate_random_block(p, 8);
954    md5_init(&md5);
955    md5_update(&md5, p, 8);
956    md5_update(&md5, data, len);
957    md5_finito(&md5, p + 8);
958    memset (&ivec, 0, sizeof(ivec));
959    des_ede3_cbc_encrypt((des_cblock*)p,
960			 (des_cblock*)p,
961			 24,
962			 sched[0], sched[1], sched[2],
963			 &ivec,
964			 DES_ENCRYPT);
965}
966
967static krb5_error_code
968RSA_MD5_DES3_verify(krb5_context context,
969		    struct key_data *key,
970		    void *data,
971		    size_t len,
972		    Checksum *C)
973{
974    struct md5 md5;
975    unsigned char tmp[24];
976    unsigned char res[16];
977    des_cblock ivec;
978    des_key_schedule *sched = key->schedule->data;
979    krb5_error_code ret = 0;
980
981    memset(&ivec, 0, sizeof(ivec));
982    des_ede3_cbc_encrypt(C->checksum.data,
983			 (void*)tmp,
984			 C->checksum.length,
985			 sched[0], sched[1], sched[2],
986			 &ivec,
987			 DES_DECRYPT);
988    md5_init(&md5);
989    md5_update(&md5, tmp, 8); /* confounder */
990    md5_update(&md5, data, len);
991    md5_finito(&md5, res);
992    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
993	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
994    memset(tmp, 0, sizeof(tmp));
995    memset(res, 0, sizeof(res));
996    return ret;
997}
998
999static void
1000SHA1_checksum(krb5_context context,
1001	      struct key_data *key,
1002	      void *data,
1003	      size_t len,
1004	      Checksum *C)
1005{
1006    struct sha m;
1007    sha_init(&m);
1008    sha_update(&m, data, len);
1009    sha_finito(&m, C->checksum.data);
1010}
1011
1012/* HMAC according to RFC2104 */
1013static void
1014hmac(krb5_context context,
1015     struct checksum_type *cm,
1016     void *data,
1017     size_t len,
1018     struct key_data *keyblock,
1019     Checksum *result)
1020{
1021    unsigned char *ipad, *opad;
1022    unsigned char *key;
1023    size_t key_len;
1024    int i;
1025
1026    if(keyblock->key->keyvalue.length > cm->blocksize){
1027	(*cm->checksum)(context,
1028			keyblock,
1029			keyblock->key->keyvalue.data,
1030			keyblock->key->keyvalue.length,
1031			result);
1032	key = result->checksum.data;
1033	key_len = result->checksum.length;
1034    } else {
1035	key = keyblock->key->keyvalue.data;
1036	key_len = keyblock->key->keyvalue.length;
1037    }
1038    ipad = malloc(cm->blocksize + len);
1039    opad = malloc(cm->blocksize + cm->checksumsize);
1040    memset(ipad, 0x36, cm->blocksize);
1041    memset(opad, 0x5c, cm->blocksize);
1042    for(i = 0; i < key_len; i++){
1043	ipad[i] ^= key[i];
1044	opad[i] ^= key[i];
1045    }
1046    memcpy(ipad + cm->blocksize, data, len);
1047    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, result);
1048    memcpy(opad + cm->blocksize, result->checksum.data,
1049	   result->checksum.length);
1050    (*cm->checksum)(context, keyblock, opad,
1051		    cm->blocksize + cm->checksumsize, result);
1052    memset(ipad, 0, cm->blocksize + len);
1053    free(ipad);
1054    memset(opad, 0, cm->blocksize + cm->checksumsize);
1055    free(opad);
1056}
1057
1058static void
1059HMAC_SHA1_DES3_checksum(krb5_context context,
1060			struct key_data *key,
1061			void *data,
1062			size_t len,
1063			Checksum *result)
1064{
1065    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1066
1067    hmac(context, c, data, len, key, result);
1068}
1069
1070struct checksum_type checksum_none = {
1071    CKSUMTYPE_NONE,
1072    "none",
1073    1,
1074    0,
1075    0,
1076    NONE_checksum,
1077    NULL
1078};
1079struct checksum_type checksum_crc32 = {
1080    CKSUMTYPE_CRC32,
1081    "crc32",
1082    1,
1083    4,
1084    0,
1085    CRC32_checksum,
1086    NULL
1087};
1088struct checksum_type checksum_rsa_md4 = {
1089    CKSUMTYPE_RSA_MD4,
1090    "rsa-md4",
1091    64,
1092    16,
1093    F_CPROOF,
1094    RSA_MD4_checksum,
1095    NULL
1096};
1097struct checksum_type checksum_rsa_md4_des = {
1098    CKSUMTYPE_RSA_MD4_DES,
1099    "rsa-md4-des",
1100    64,
1101    24,
1102    F_KEYED | F_CPROOF | F_VARIANT,
1103    RSA_MD4_DES_checksum,
1104    RSA_MD4_DES_verify
1105};
1106#if 0
1107struct checksum_type checksum_des_mac = {
1108    CKSUMTYPE_DES_MAC,
1109    "des-mac",
1110    0,
1111    0,
1112    0,
1113    DES_MAC_checksum,
1114};
1115struct checksum_type checksum_des_mac_k = {
1116    CKSUMTYPE_DES_MAC_K,
1117    "des-mac-k",
1118    0,
1119    0,
1120    0,
1121    DES_MAC_K_checksum,
1122};
1123struct checksum_type checksum_rsa_md4_des_k = {
1124    CKSUMTYPE_RSA_MD4_DES_K,
1125    "rsa-md4-des-k",
1126    0,
1127    0,
1128    0,
1129    RSA_MD4_DES_K_checksum,
1130    RSA_MD4_DES_K_verify,
1131};
1132#endif
1133struct checksum_type checksum_rsa_md5 = {
1134    CKSUMTYPE_RSA_MD5,
1135    "rsa-md5",
1136    64,
1137    16,
1138    F_CPROOF,
1139    RSA_MD5_checksum,
1140    NULL
1141};
1142struct checksum_type checksum_rsa_md5_des = {
1143    CKSUMTYPE_RSA_MD5_DES,
1144    "rsa-md5-des",
1145    64,
1146    24,
1147    F_KEYED | F_CPROOF | F_VARIANT,
1148    RSA_MD5_DES_checksum,
1149    RSA_MD5_DES_verify,
1150};
1151struct checksum_type checksum_rsa_md5_des3 = {
1152    CKSUMTYPE_RSA_MD5_DES3,
1153    "rsa-md5-des3",
1154    64,
1155    24,
1156    F_KEYED | F_CPROOF | F_VARIANT,
1157    RSA_MD5_DES3_checksum,
1158    RSA_MD5_DES3_verify,
1159};
1160struct checksum_type checksum_sha1 = {
1161    CKSUMTYPE_SHA1,
1162    "sha1",
1163    64,
1164    20,
1165    F_CPROOF,
1166    SHA1_checksum,
1167    NULL
1168};
1169struct checksum_type checksum_hmac_sha1_des3 = {
1170    CKSUMTYPE_HMAC_SHA1_DES3,
1171    "hmac-sha1-des3",
1172    64,
1173    20,
1174    F_KEYED | F_CPROOF | F_DERIVED,
1175    HMAC_SHA1_DES3_checksum,
1176    NULL
1177};
1178
1179struct checksum_type *checksum_types[] = {
1180    &checksum_none,
1181    &checksum_crc32,
1182    &checksum_rsa_md4,
1183    &checksum_rsa_md4_des,
1184#if 0
1185    &checksum_des_mac,
1186    &checksum_des_mac_k,
1187    &checksum_rsa_md4_des_k,
1188#endif
1189    &checksum_rsa_md5,
1190    &checksum_rsa_md5_des,
1191    &checksum_rsa_md5_des3,
1192    &checksum_sha1,
1193    &checksum_hmac_sha1_des3
1194};
1195
1196static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1197
1198static struct checksum_type *
1199_find_checksum(krb5_cksumtype type)
1200{
1201    int i;
1202    for(i = 0; i < num_checksums; i++)
1203	if(checksum_types[i]->type == type)
1204	    return checksum_types[i];
1205    return NULL;
1206}
1207
1208static krb5_error_code
1209get_checksum_key(krb5_context context,
1210		 krb5_crypto crypto,
1211		 unsigned usage,  /* not krb5_key_usage */
1212		 struct checksum_type *ct,
1213		 struct key_data **key)
1214{
1215    krb5_error_code ret = 0;
1216
1217    if(ct->flags & F_DERIVED)
1218	ret = _get_derived_key(context, crypto, usage, key);
1219    else if(ct->flags & F_VARIANT) {
1220	int i;
1221
1222	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1223	if(*key == NULL)
1224	    return ENOMEM;
1225	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1226	if(ret)
1227	    return ret;
1228	for(i = 0; i < (*key)->key->keyvalue.length; i++)
1229	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1230    } else {
1231	*key = &crypto->key;
1232    }
1233    if(ret == 0)
1234	ret = _key_schedule(context, *key);
1235    return ret;
1236}
1237
1238static krb5_error_code
1239do_checksum (krb5_context context,
1240	     struct checksum_type *ct,
1241	     krb5_crypto crypto,
1242	     unsigned usage,
1243	     void *data,
1244	     size_t len,
1245	     Checksum *result)
1246{
1247    krb5_error_code ret;
1248    struct key_data *dkey;
1249    int keyed_checksum;
1250
1251    keyed_checksum = (ct->flags & F_KEYED) != 0;
1252    if(keyed_checksum && crypto == NULL)
1253	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1254    if(keyed_checksum)
1255	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1256    else
1257	dkey = NULL;
1258    result->cksumtype = ct->type;
1259    krb5_data_alloc(&result->checksum, ct->checksumsize);
1260    (*ct->checksum)(context, dkey, data, len, result);
1261    return 0;
1262}
1263
1264static krb5_error_code
1265create_checksum(krb5_context context,
1266		krb5_crypto crypto,
1267		unsigned usage, /* not krb5_key_usage */
1268		krb5_cksumtype type, /* if crypto == NULL */
1269		void *data,
1270		size_t len,
1271		Checksum *result)
1272{
1273    struct checksum_type *ct;
1274
1275    if(crypto) {
1276	ct = crypto->et->keyed_checksum;
1277	if(ct == NULL)
1278	    ct = crypto->et->cksumtype;
1279    } else
1280	ct = _find_checksum(type);
1281    if(ct == NULL)
1282	return KRB5_PROG_SUMTYPE_NOSUPP;
1283    return do_checksum (context, ct, crypto, usage, data, len, result);
1284}
1285
1286krb5_error_code
1287krb5_create_checksum(krb5_context context,
1288		     krb5_crypto crypto,
1289		     unsigned usage_or_type,
1290		     void *data,
1291		     size_t len,
1292		     Checksum *result)
1293{
1294    return create_checksum(context, crypto,
1295			   CHECKSUM_USAGE(usage_or_type),
1296			   usage_or_type, data, len, result);
1297}
1298
1299static krb5_error_code
1300verify_checksum(krb5_context context,
1301		krb5_crypto crypto,
1302		unsigned usage, /* not krb5_key_usage */
1303		void *data,
1304		size_t len,
1305		Checksum *cksum)
1306{
1307    krb5_error_code ret;
1308    struct key_data *dkey;
1309    int keyed_checksum;
1310    Checksum c;
1311    struct checksum_type *ct;
1312
1313    ct = _find_checksum(cksum->cksumtype);
1314    if(ct == NULL)
1315	return KRB5_PROG_SUMTYPE_NOSUPP;
1316    if(ct->checksumsize != cksum->checksum.length)
1317	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1318    keyed_checksum = (ct->flags & F_KEYED) != 0;
1319    if(keyed_checksum && crypto == NULL)
1320	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1321    if(keyed_checksum)
1322	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1323    else
1324	dkey = NULL;
1325    if(ct->verify)
1326	return (*ct->verify)(context, dkey, data, len, cksum);
1327
1328    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1329    if (ret)
1330	return ret;
1331
1332    (*ct->checksum)(context, dkey, data, len, &c);
1333
1334    if(c.checksum.length != cksum->checksum.length ||
1335       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length))
1336	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1337    else
1338	ret = 0;
1339    krb5_data_free (&c.checksum);
1340    return ret;
1341}
1342
1343krb5_error_code
1344krb5_verify_checksum(krb5_context context,
1345		     krb5_crypto crypto,
1346		     krb5_key_usage usage,
1347		     void *data,
1348		     size_t len,
1349		     Checksum *cksum)
1350{
1351    return verify_checksum(context, crypto,
1352			   CHECKSUM_USAGE(usage), data, len, cksum);
1353}
1354
1355krb5_error_code
1356krb5_checksumsize(krb5_context context,
1357		  krb5_cksumtype type,
1358		  size_t *size)
1359{
1360    struct checksum_type *ct = _find_checksum(type);
1361    if(ct == NULL)
1362	return KRB5_PROG_SUMTYPE_NOSUPP;
1363    *size = ct->checksumsize;
1364    return 0;
1365}
1366
1367krb5_boolean
1368krb5_checksum_is_keyed(krb5_context context,
1369		       krb5_cksumtype type)
1370{
1371    struct checksum_type *ct = _find_checksum(type);
1372    if(ct == NULL)
1373	return KRB5_PROG_SUMTYPE_NOSUPP;
1374    return ct->flags & F_KEYED;
1375}
1376
1377krb5_boolean
1378krb5_checksum_is_collision_proof(krb5_context context,
1379				 krb5_cksumtype type)
1380{
1381    struct checksum_type *ct = _find_checksum(type);
1382    if(ct == NULL)
1383	return KRB5_PROG_SUMTYPE_NOSUPP;
1384    return ct->flags & F_CPROOF;
1385}
1386
1387/************************************************************
1388 *                                                          *
1389 ************************************************************/
1390
1391static void
1392NULL_encrypt(struct key_data *key,
1393	     void *data,
1394	     size_t len,
1395	     krb5_boolean encrypt)
1396{
1397}
1398
1399static void
1400DES_CBC_encrypt_null_ivec(struct key_data *key,
1401			  void *data,
1402			  size_t len,
1403			  krb5_boolean encrypt)
1404{
1405    des_cblock ivec;
1406    des_key_schedule *s = key->schedule->data;
1407    memset(&ivec, 0, sizeof(ivec));
1408    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1409}
1410
1411static void
1412DES_CBC_encrypt_key_ivec(struct key_data *key,
1413			 void *data,
1414			 size_t len,
1415			 krb5_boolean encrypt)
1416{
1417    des_cblock ivec;
1418    des_key_schedule *s = key->schedule->data;
1419    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1420    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1421}
1422
1423static void
1424DES3_CBC_encrypt(struct key_data *key,
1425		 void *data,
1426		 size_t len,
1427		 krb5_boolean encrypt)
1428{
1429    des_cblock ivec;
1430    des_key_schedule *s = key->schedule->data;
1431    memset(&ivec, 0, sizeof(ivec));
1432    des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], &ivec, encrypt);
1433}
1434
1435static void
1436ARCFOUR_encrypt(struct key_data *key,
1437		void *data,
1438		size_t len,
1439		krb5_boolean encrypt)
1440{
1441
1442}
1443
1444/*
1445 * these should currently be in reverse preference order.
1446 */
1447
1448static struct encryption_type etypes[] = {
1449    {
1450	ETYPE_NULL,
1451	"null",
1452	1,
1453	0,
1454	&keytype_null,
1455	&checksum_none,
1456	NULL,
1457	0,
1458	NULL_encrypt,
1459    },
1460    {
1461	ETYPE_DES_CBC_CRC,
1462	"des-cbc-crc",
1463	8,
1464	8,
1465	&keytype_des,
1466	&checksum_crc32,
1467	NULL,
1468	0,
1469	DES_CBC_encrypt_key_ivec,
1470    },
1471    {
1472	ETYPE_DES_CBC_MD4,
1473	"des-cbc-md4",
1474	8,
1475	8,
1476	&keytype_des,
1477	&checksum_rsa_md4,
1478	&checksum_rsa_md4_des,
1479	0,
1480	DES_CBC_encrypt_null_ivec,
1481    },
1482    {
1483	ETYPE_DES_CBC_MD5,
1484	"des-cbc-md5",
1485	8,
1486	8,
1487	&keytype_des,
1488	&checksum_rsa_md5,
1489	&checksum_rsa_md5_des,
1490	0,
1491	DES_CBC_encrypt_null_ivec,
1492    },
1493    {
1494	ETYPE_DES3_CBC_MD5,
1495	"des3-cbc-md5",
1496	8,
1497	8,
1498	&keytype_des3,
1499	&checksum_rsa_md5,
1500	&checksum_rsa_md5_des3,
1501	0,
1502 	DES3_CBC_encrypt,
1503    },
1504    {
1505	ETYPE_DES3_CBC_SHA1,
1506	"des3-cbc-sha1",
1507	8,
1508	8,
1509	&keytype_des3_derived,
1510	&checksum_sha1,
1511	&checksum_hmac_sha1_des3,
1512	F_DERIVED,
1513 	DES3_CBC_encrypt,
1514    },
1515    {
1516	ETYPE_OLD_DES3_CBC_SHA1,
1517	"old-des3-cbc-sha1",
1518	8,
1519	8,
1520	&keytype_des3,
1521	&checksum_sha1,
1522	&checksum_hmac_sha1_des3,
1523	0,
1524 	DES3_CBC_encrypt,
1525    },
1526    {
1527	ETYPE_DES_CBC_NONE,
1528	"des-cbc-none",
1529	8,
1530	0,
1531	&keytype_des,
1532	&checksum_none,
1533	NULL,
1534	F_PSEUDO,
1535	DES_CBC_encrypt_null_ivec,
1536    },
1537    {
1538	ETYPE_DES3_CBC_NONE,
1539	"des3-cbc-none",
1540	8,
1541	0,
1542	&keytype_des3_derived,
1543	&checksum_none,
1544	NULL,
1545	F_PSEUDO,
1546	DES_CBC_encrypt_null_ivec,
1547    },
1548};
1549
1550static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
1551
1552
1553static struct encryption_type *
1554_find_enctype(krb5_enctype type)
1555{
1556    int i;
1557    for(i = 0; i < num_etypes; i++)
1558	if(etypes[i].type == type)
1559	    return &etypes[i];
1560    return NULL;
1561}
1562
1563
1564krb5_error_code
1565krb5_enctype_to_string(krb5_context context,
1566		       krb5_enctype etype,
1567		       char **string)
1568{
1569    struct encryption_type *e;
1570    e = _find_enctype(etype);
1571    if(e == NULL)
1572	return KRB5_PROG_ETYPE_NOSUPP;
1573    *string = strdup(e->name);
1574    if(*string == NULL)
1575	return ENOMEM;
1576    return 0;
1577}
1578
1579krb5_error_code
1580krb5_string_to_enctype(krb5_context context,
1581		       const char *string,
1582		       krb5_enctype *etype)
1583{
1584    int i;
1585    for(i = 0; i < num_etypes; i++)
1586	if(strcasecmp(etypes[i].name, string) == 0){
1587	    *etype = etypes[i].type;
1588	    return 0;
1589	}
1590    return KRB5_PROG_ETYPE_NOSUPP;
1591}
1592
1593krb5_error_code
1594krb5_enctype_to_keytype(krb5_context context,
1595			krb5_enctype etype,
1596			krb5_keytype *keytype)
1597{
1598    struct encryption_type *e = _find_enctype(etype);
1599    if(e == NULL)
1600	return KRB5_PROG_ETYPE_NOSUPP;
1601    *keytype = e->keytype->type; /* XXX */
1602    return 0;
1603}
1604
1605#if 0
1606krb5_error_code
1607krb5_keytype_to_enctype(krb5_context context,
1608			krb5_keytype keytype,
1609			krb5_enctype *etype)
1610{
1611    struct key_type *kt = _find_keytype(keytype);
1612    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
1613    if(kt == NULL)
1614	return KRB5_PROG_KEYTYPE_NOSUPP;
1615    *etype = kt->best_etype;
1616    return 0;
1617}
1618#endif
1619
1620krb5_error_code
1621krb5_keytype_to_enctypes (krb5_context context,
1622			  krb5_keytype keytype,
1623			  unsigned *len,
1624			  int **val)
1625{
1626    int i;
1627    unsigned n = 0;
1628    int *ret;
1629
1630    for (i = num_etypes - 1; i >= 0; --i) {
1631	if (etypes[i].keytype->type == keytype
1632	    && !(etypes[i].flags & F_PSEUDO))
1633	    ++n;
1634    }
1635    ret = malloc(n * sizeof(int));
1636    if (ret == NULL && n != 0)
1637	return ENOMEM;
1638    n = 0;
1639    for (i = num_etypes - 1; i >= 0; --i) {
1640	if (etypes[i].keytype->type == keytype
1641	    && !(etypes[i].flags & F_PSEUDO))
1642	    ret[n++] = etypes[i].type;
1643    }
1644    *len = n;
1645    *val = ret;
1646    return 0;
1647}
1648
1649/*
1650 * First take the configured list of etypes for `keytype' if available,
1651 * else, do `krb5_keytype_to_enctypes'.
1652 */
1653
1654krb5_error_code
1655krb5_keytype_to_enctypes_default (krb5_context context,
1656				  krb5_keytype keytype,
1657				  unsigned *len,
1658				  int **val)
1659{
1660    int i, n;
1661    int *ret;
1662
1663    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
1664	return krb5_keytype_to_enctypes (context, keytype, len, val);
1665
1666    for (n = 0; context->etypes_des[n]; ++n)
1667	;
1668    ret = malloc (n * sizeof(*ret));
1669    if (ret == NULL && n != 0)
1670	return ENOMEM;
1671    for (i = 0; i < n; ++i)
1672	ret[i] = context->etypes_des[i];
1673    *len = n;
1674    *val = ret;
1675    return 0;
1676}
1677
1678krb5_error_code
1679krb5_enctype_valid(krb5_context context,
1680		 krb5_enctype etype)
1681{
1682    return _find_enctype(etype) != NULL;
1683}
1684
1685/* if two enctypes have compatible keys */
1686krb5_boolean
1687krb5_enctypes_compatible_keys(krb5_context context,
1688			      krb5_enctype etype1,
1689			      krb5_enctype etype2)
1690{
1691    struct encryption_type *e1 = _find_enctype(etype1);
1692    struct encryption_type *e2 = _find_enctype(etype2);
1693    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
1694}
1695
1696static krb5_boolean
1697derived_crypto(krb5_context context,
1698	       krb5_crypto crypto)
1699{
1700    return (crypto->et->flags & F_DERIVED) != 0;
1701}
1702
1703
1704#define CHECKSUMSIZE(C) ((C)->checksumsize)
1705#define CHECKSUMTYPE(C) ((C)->type)
1706
1707static krb5_error_code
1708encrypt_internal_derived(krb5_context context,
1709			 krb5_crypto crypto,
1710			 unsigned usage,
1711			 void *data,
1712			 size_t len,
1713			 krb5_data *result)
1714{
1715    size_t sz, block_sz, checksum_sz;
1716    Checksum cksum;
1717    unsigned char *p, *q;
1718    krb5_error_code ret;
1719    struct key_data *dkey;
1720    struct encryption_type *et = crypto->et;
1721
1722    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1723
1724    sz = et->confoundersize + /* 4 - length */ len;
1725    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1726    p = calloc(1, block_sz + checksum_sz);
1727    if(p == NULL)
1728	return ENOMEM;
1729
1730    q = p;
1731    krb5_generate_random_block(q, et->confoundersize); /* XXX */
1732    q += et->confoundersize;
1733    memcpy(q, data, len);
1734
1735    ret = create_checksum(context,
1736			  crypto,
1737			  INTEGRITY_USAGE(usage),
1738			  0,
1739			  p,
1740			  block_sz,
1741			  &cksum);
1742    if(ret == 0 && cksum.checksum.length != checksum_sz)
1743	ret =  KRB5_CRYPTO_INTERNAL;
1744    if(ret) {
1745	memset(p, 0, block_sz + checksum_sz);
1746	free(p);
1747	return ret;
1748    }
1749    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1750    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1751    if(ret) {
1752	memset(p, 0, block_sz + checksum_sz);
1753	free(p);
1754	return ret;
1755    }
1756    ret = _key_schedule(context, dkey);
1757    if(ret) {
1758	memset(p, 0, block_sz);
1759	free(p);
1760	return ret;
1761    }
1762#ifdef CRYPTO_DEBUG
1763    krb5_crypto_debug(context, 1, block_sz, dkey->key);
1764#endif
1765    (*et->encrypt)(dkey, p, block_sz, 1);
1766    result->data = p;
1767    result->length = block_sz + checksum_sz;
1768    return 0;
1769}
1770
1771static krb5_error_code
1772encrypt_internal(krb5_context context,
1773		 krb5_crypto crypto,
1774		 void *data,
1775		 size_t len,
1776		 krb5_data *result)
1777{
1778    size_t sz, block_sz, checksum_sz;
1779    Checksum cksum;
1780    unsigned char *p, *q;
1781    krb5_error_code ret;
1782    struct encryption_type *et = crypto->et;
1783
1784    checksum_sz = CHECKSUMSIZE(et->cksumtype);
1785
1786    sz = et->confoundersize + checksum_sz + len;
1787    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
1788    p = calloc(1, block_sz);
1789    if(p == NULL)
1790	return ENOMEM;
1791
1792    q = p;
1793    krb5_generate_random_block(q, et->confoundersize); /* XXX */
1794    q += et->confoundersize;
1795    memset(q, 0, checksum_sz);
1796    q += checksum_sz;
1797    memcpy(q, data, len);
1798
1799    ret = create_checksum(context,
1800			  NULL,
1801			  0,
1802			  CHECKSUMTYPE(et->cksumtype),
1803			  p,
1804			  block_sz,
1805			  &cksum);
1806    if(ret == 0 && cksum.checksum.length != checksum_sz) {
1807	free_Checksum (&cksum);
1808	ret = KRB5_CRYPTO_INTERNAL;
1809    }
1810    if(ret) {
1811	memset(p, 0, block_sz);
1812	free(p);
1813	free_Checksum(&cksum);
1814	return ret;
1815    }
1816    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
1817    free_Checksum(&cksum);
1818    ret = _key_schedule(context, &crypto->key);
1819    if(ret) {
1820	memset(p, 0, block_sz);
1821	free(p);
1822	return ret;
1823    }
1824#ifdef CRYPTO_DEBUG
1825    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
1826#endif
1827    (*et->encrypt)(&crypto->key, p, block_sz, 1);
1828    result->data = p;
1829    result->length = block_sz;
1830    return 0;
1831}
1832
1833static krb5_error_code
1834decrypt_internal_derived(krb5_context context,
1835			 krb5_crypto crypto,
1836			 unsigned usage,
1837			 void *data,
1838			 size_t len,
1839			 krb5_data *result)
1840{
1841    size_t checksum_sz;
1842    Checksum cksum;
1843    unsigned char *p;
1844    krb5_error_code ret;
1845    struct key_data *dkey;
1846    struct encryption_type *et = crypto->et;
1847    unsigned long l;
1848
1849    p = malloc(len);
1850    if(len != 0 && p == NULL)
1851	return ENOMEM;
1852    memcpy(p, data, len);
1853
1854    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1855    len -= checksum_sz;
1856
1857    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1858    if(ret) {
1859	free(p);
1860	return ret;
1861    }
1862    ret = _key_schedule(context, dkey);
1863    if(ret) {
1864	free(p);
1865	return ret;
1866    }
1867#ifdef CRYPTO_DEBUG
1868    krb5_crypto_debug(context, 0, len, dkey->key);
1869#endif
1870    (*et->encrypt)(dkey, p, len, 0);
1871
1872    cksum.checksum.data   = p + len;
1873    cksum.checksum.length = checksum_sz;
1874    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
1875
1876    ret = verify_checksum(context,
1877			  crypto,
1878			  INTEGRITY_USAGE(usage),
1879			  p,
1880			  len,
1881			  &cksum);
1882    if(ret) {
1883	free(p);
1884	return ret;
1885    }
1886    l = len - et->confoundersize;
1887    memmove(p, p + et->confoundersize, l);
1888    result->data = realloc(p, l);
1889    if(p == NULL) {
1890	free(p);
1891	return ENOMEM;
1892    }
1893    result->length = l;
1894    return 0;
1895}
1896
1897static krb5_error_code
1898decrypt_internal(krb5_context context,
1899		 krb5_crypto crypto,
1900		 void *data,
1901		 size_t len,
1902		 krb5_data *result)
1903{
1904    krb5_error_code ret;
1905    unsigned char *p;
1906    Checksum cksum;
1907    size_t checksum_sz, l;
1908    struct encryption_type *et = crypto->et;
1909
1910    checksum_sz = CHECKSUMSIZE(et->cksumtype);
1911    p = malloc(len);
1912    if(len != 0 && p == NULL)
1913	return ENOMEM;
1914    memcpy(p, data, len);
1915
1916    ret = _key_schedule(context, &crypto->key);
1917    if(ret) {
1918	free(p);
1919	return ret;
1920    }
1921#ifdef CRYPTO_DEBUG
1922    krb5_crypto_debug(context, 0, len, crypto->key.key);
1923#endif
1924    (*et->encrypt)(&crypto->key, p, len, 0);
1925    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1926    if(ret) {
1927	free(p);
1928	return ret;
1929    }
1930    memset(p + et->confoundersize, 0, checksum_sz);
1931    cksum.cksumtype = CHECKSUMTYPE(et->cksumtype);
1932    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1933    free_Checksum(&cksum);
1934    if(ret) {
1935	free(p);
1936	return ret;
1937    }
1938    l = len - et->confoundersize - checksum_sz;
1939    memmove(p, p + et->confoundersize + checksum_sz, l);
1940    result->data = realloc(p, l);
1941    if(result->data == NULL) {
1942	free(p);
1943	return ENOMEM;
1944    }
1945    result->length = l;
1946    return 0;
1947}
1948
1949krb5_error_code
1950krb5_encrypt(krb5_context context,
1951	     krb5_crypto crypto,
1952	     unsigned usage,
1953	     void *data,
1954	     size_t len,
1955	     krb5_data *result)
1956{
1957    if(derived_crypto(context, crypto))
1958	return encrypt_internal_derived(context, crypto, usage,
1959					data, len, result);
1960    else
1961	return encrypt_internal(context, crypto, data, len, result);
1962}
1963
1964krb5_error_code
1965krb5_encrypt_EncryptedData(krb5_context context,
1966			   krb5_crypto crypto,
1967			   unsigned usage,
1968			   void *data,
1969			   size_t len,
1970			   int kvno,
1971			   EncryptedData *result)
1972{
1973    result->etype = CRYPTO_ETYPE(crypto);
1974    if(kvno){
1975	ALLOC(result->kvno, 1);
1976	*result->kvno = kvno;
1977    }else
1978	result->kvno = NULL;
1979    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1980}
1981
1982krb5_error_code
1983krb5_decrypt(krb5_context context,
1984	     krb5_crypto crypto,
1985	     unsigned usage,
1986	     void *data,
1987	     size_t len,
1988	     krb5_data *result)
1989{
1990    if(derived_crypto(context, crypto))
1991	return decrypt_internal_derived(context, crypto, usage,
1992					data, len, result);
1993    else
1994	return decrypt_internal(context, crypto, data, len, result);
1995}
1996
1997krb5_error_code
1998krb5_decrypt_EncryptedData(krb5_context context,
1999			   krb5_crypto crypto,
2000			   unsigned usage,
2001			   EncryptedData *e,
2002			   krb5_data *result)
2003{
2004    return krb5_decrypt(context, crypto, usage,
2005			e->cipher.data, e->cipher.length, result);
2006}
2007
2008/************************************************************
2009 *                                                          *
2010 ************************************************************/
2011
2012void
2013krb5_generate_random_block(void *buf, size_t len)
2014{
2015    des_cblock key, out;
2016    static des_cblock counter;
2017    static des_key_schedule schedule;
2018    int i;
2019    static int initialized = 0;
2020
2021    if(!initialized) {
2022	des_new_random_key(&key);
2023	des_set_key(&key, schedule);
2024	memset(&key, 0, sizeof(key));
2025	des_new_random_key(&counter);
2026    }
2027    while(len > 0) {
2028	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
2029	for(i = 7; i >=0; i--)
2030	    if(counter[i]++)
2031		break;
2032	memcpy(buf, out, min(len, sizeof(out)));
2033	len -= min(len, sizeof(out));
2034	buf = (char*)buf + sizeof(out);
2035    }
2036}
2037
2038static void
2039DES3_postproc(krb5_context context,
2040	      unsigned char *k, size_t len, struct key_data *key)
2041{
2042    unsigned char x[24];
2043    int i, j;
2044
2045    memset(x, 0, sizeof(x));
2046    for (i = 0; i < 3; ++i) {
2047	unsigned char foo;
2048
2049	for (j = 0; j < 7; ++j) {
2050	    unsigned char b = k[7 * i + j];
2051
2052	    x[8 * i + j] = b;
2053	}
2054	foo = 0;
2055	for (j = 6; j >= 0; --j) {
2056	    foo |= k[7 * i + j] & 1;
2057	    foo <<= 1;
2058	}
2059	x[8 * i + 7] = foo;
2060    }
2061    k = key->key->keyvalue.data;
2062    memcpy(k, x, 24);
2063    memset(x, 0, sizeof(x));
2064    if (key->schedule) {
2065	krb5_free_data(context, key->schedule);
2066	key->schedule = NULL;
2067    }
2068    des_set_odd_parity((des_cblock*)k);
2069    des_set_odd_parity((des_cblock*)(k + 8));
2070    des_set_odd_parity((des_cblock*)(k + 16));
2071}
2072
2073static krb5_error_code
2074derive_key(krb5_context context,
2075	   struct encryption_type *et,
2076	   struct key_data *key,
2077	   void *constant,
2078	   size_t len)
2079{
2080    unsigned char *k;
2081    unsigned int nblocks = 0, i;
2082    krb5_error_code ret = 0;
2083
2084    struct key_type *kt = et->keytype;
2085    ret = _key_schedule(context, key);
2086    if(ret)
2087	return ret;
2088    if(et->blocksize * 8 < kt->bits ||
2089       len != et->blocksize) {
2090	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2091	k = malloc(nblocks * et->blocksize);
2092	if(k == NULL)
2093	    return ENOMEM;
2094	_krb5_n_fold(constant, len, k, et->blocksize);
2095	for(i = 0; i < nblocks; i++) {
2096	    if(i > 0)
2097		memcpy(k + i * et->blocksize,
2098		       k + (i - 1) * et->blocksize,
2099		       et->blocksize);
2100	    (*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1);
2101	}
2102    } else {
2103	void *c = malloc(len);
2104	size_t res_len = (kt->bits + 7) / 8;
2105
2106	if(len != 0 && c == NULL)
2107	    return ENOMEM;
2108	memcpy(c, constant, len);
2109	(*et->encrypt)(key, c, len, 1);
2110	k = malloc(res_len);
2111	if(res_len != 0 && k == NULL)
2112	    return ENOMEM;
2113	_krb5_n_fold(c, len, k, res_len);
2114	free(c);
2115    }
2116
2117    /* XXX keytype dependent post-processing */
2118    switch(kt->type) {
2119    case KEYTYPE_DES3:
2120	DES3_postproc(context, k, nblocks * et->blocksize, key);
2121	break;
2122    default:
2123	krb5_warnx(context, "derive_key() called with unknown keytype (%u)",
2124		   kt->type);
2125	ret = KRB5_CRYPTO_INTERNAL;
2126	break;
2127    }
2128    memset(k, 0, nblocks * et->blocksize);
2129    free(k);
2130    return ret;
2131}
2132
2133static struct key_data *
2134_new_derived_key(krb5_crypto crypto, unsigned usage)
2135{
2136    struct key_usage *d = crypto->key_usage;
2137    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2138    if(d == NULL)
2139	return NULL;
2140    crypto->key_usage = d;
2141    d += crypto->num_key_usage++;
2142    memset(d, 0, sizeof(*d));
2143    d->usage = usage;
2144    return &d->key;
2145}
2146
2147static krb5_error_code
2148_get_derived_key(krb5_context context,
2149		 krb5_crypto crypto,
2150		 unsigned usage,
2151		 struct key_data **key)
2152{
2153    int i;
2154    struct key_data *d;
2155    unsigned char constant[5];
2156
2157    for(i = 0; i < crypto->num_key_usage; i++)
2158	if(crypto->key_usage[i].usage == usage) {
2159	    *key = &crypto->key_usage[i].key;
2160	    return 0;
2161	}
2162    d = _new_derived_key(crypto, usage);
2163    if(d == NULL)
2164	return ENOMEM;
2165    krb5_copy_keyblock(context, crypto->key.key, &d->key);
2166    _krb5_put_int(constant, usage, 5);
2167    derive_key(context, crypto->et, d, constant, sizeof(constant));
2168    *key = d;
2169    return 0;
2170}
2171
2172
2173krb5_error_code
2174krb5_crypto_init(krb5_context context,
2175		 krb5_keyblock *key,
2176		 krb5_enctype etype,
2177		 krb5_crypto *crypto)
2178{
2179    krb5_error_code ret;
2180    ALLOC(*crypto, 1);
2181    if(*crypto == NULL)
2182	return ENOMEM;
2183    if(etype == ETYPE_NULL)
2184	etype = key->keytype;
2185    (*crypto)->et = _find_enctype(etype);
2186    if((*crypto)->et == NULL) {
2187	free(*crypto);
2188	return KRB5_PROG_ETYPE_NOSUPP;
2189    }
2190    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2191    if(ret) {
2192	free(*crypto);
2193	return ret;
2194    }
2195    (*crypto)->key.schedule = NULL;
2196    (*crypto)->num_key_usage = 0;
2197    (*crypto)->key_usage = NULL;
2198    return 0;
2199}
2200
2201static void
2202free_key_data(krb5_context context, struct key_data *key)
2203{
2204    krb5_free_keyblock(context, key->key);
2205    if(key->schedule) {
2206	memset(key->schedule->data, 0, key->schedule->length);
2207	krb5_free_data(context, key->schedule);
2208    }
2209}
2210
2211static void
2212free_key_usage(krb5_context context, struct key_usage *ku)
2213{
2214    free_key_data(context, &ku->key);
2215}
2216
2217krb5_error_code
2218krb5_crypto_destroy(krb5_context context,
2219		    krb5_crypto crypto)
2220{
2221    int i;
2222
2223    for(i = 0; i < crypto->num_key_usage; i++)
2224	free_key_usage(context, &crypto->key_usage[i]);
2225    free(crypto->key_usage);
2226    free_key_data(context, &crypto->key);
2227    free (crypto);
2228    return 0;
2229}
2230
2231krb5_error_code
2232krb5_string_to_key_derived(krb5_context context,
2233			   const void *str,
2234			   size_t len,
2235			   krb5_enctype etype,
2236			   krb5_keyblock *key)
2237{
2238    struct encryption_type *et = _find_enctype(etype);
2239    krb5_error_code ret;
2240    struct key_data kd;
2241    u_char *tmp;
2242
2243    if(et == NULL)
2244	return KRB5_PROG_ETYPE_NOSUPP;
2245    ALLOC(kd.key, 1);
2246    kd.key->keytype = etype;
2247    tmp = malloc (et->keytype->bits / 8);
2248    _krb5_n_fold(str, len, tmp, et->keytype->bits / 8);
2249    krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
2250    kd.schedule = NULL;
2251    DES3_postproc (context, tmp, et->keytype->bits / 8, &kd); /* XXX */
2252    ret = derive_key(context,
2253		     et,
2254		     &kd,
2255		     "kerberos", /* XXX well known constant */
2256		     strlen("kerberos"));
2257    ret = krb5_copy_keyblock_contents(context, kd.key, key);
2258    free_key_data(context, &kd);
2259    return ret;
2260}
2261
2262/*
2263 * Return the size of an encrypted packet of length `data_len'
2264 */
2265
2266size_t
2267krb5_get_wrapped_length (krb5_context context,
2268			 krb5_crypto  crypto,
2269			 size_t       data_len)
2270{
2271    struct encryption_type *et = crypto->et;
2272    size_t blocksize = et->blocksize;
2273    size_t res;
2274
2275    res = (data_len + blocksize - 1) / blocksize * blocksize;
2276    res = res + et->confoundersize + et->cksumtype->checksumsize;
2277    return res;
2278}
2279
2280#ifdef CRYPTO_DEBUG
2281
2282static krb5_error_code
2283krb5_get_keyid(krb5_context context,
2284	       krb5_keyblock *key,
2285	       u_int32_t *keyid)
2286{
2287    struct md5 md5;
2288    unsigned char tmp[16];
2289    md5_init(&md5);
2290    md5_update(&md5, key->keyvalue.data, key->keyvalue.length);
2291    md5_finito(&md5, tmp);
2292    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
2293    return 0;
2294}
2295
2296static void
2297krb5_crypto_debug(krb5_context context,
2298		  int encrypt,
2299		  size_t len,
2300		  krb5_keyblock *key)
2301{
2302    u_int32_t keyid;
2303    char *kt;
2304    krb5_get_keyid(context, key, &keyid);
2305    krb5_enctype_to_string(context, key->keytype, &kt);
2306    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
2307	       encrypt ? "encrypting" : "decrypting",
2308	       (unsigned long)len,
2309	       keyid,
2310	       kt);
2311    free(kt);
2312}
2313
2314#endif /* CRYPTO_DEBUG */
2315