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