xref: /freebsd/crypto/heimdal/lib/krb5/crypto.c (revision b528cefc6b8f9670b31a865051741d946cb37085)
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"
35 RCSID("$Id: crypto.c,v 1.28 2000/01/06 20:21:13 assar Exp $");
36 
37 #undef CRYPTO_DEBUG
38 #ifdef CRYPTO_DEBUG
39 static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
40 #endif
41 
42 
43 struct key_data {
44     krb5_keyblock *key;
45     krb5_data *schedule;
46 };
47 
48 struct key_usage {
49     unsigned usage;
50     struct key_data key;
51 };
52 
53 struct 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 
69 struct 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 
76 struct 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 
90 struct 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 
101 struct 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 
117 static struct checksum_type *_find_checksum(krb5_cksumtype type);
118 static struct encryption_type *_find_enctype(krb5_enctype type);
119 static struct key_type *_find_keytype(krb5_keytype type);
120 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
121 					unsigned, struct key_data**);
122 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
123 
124 /************************************************************
125  *                                                          *
126  ************************************************************/
127 
128 static void
129 DES_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 
139 static void
140 DES_schedule(krb5_context context,
141 	     struct key_data *key)
142 {
143     des_set_key(key->key->keyvalue.data, key->schedule->data);
144 }
145 
146 static krb5_error_code
147 DES_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  */
182 static void
183 DES_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  */
210 static void
211 DES_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 
245 static krb5_error_code
246 DES_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 
263 static void
264 DES3_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 
278 static void
279 DES3_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 
293 static void
294 xor (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 
307 static krb5_error_code
308 DES3_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 
360 static krb5_error_code
361 DES3_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 
390 static void
391 ARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
392 {
393     krb5_generate_random_block (key->keyvalue.data,
394 				key->keyvalue.length);
395 }
396 
397 static void
398 ARCFOUR_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 
404 static krb5_error_code
405 ARCFOUR_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 
438 extern struct salt_type des_salt[],
439     des3_salt[], des3_salt_derived[], arcfour_salt[];
440 
441 struct key_type keytype_null = {
442     KEYTYPE_NULL,
443     "null",
444     0,
445     0,
446     0,
447     NULL,
448     NULL,
449     NULL
450 };
451 
452 struct 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 
463 struct 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 
474 struct 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 
485 struct 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 
496 struct key_type *keytypes[] = {
497     &keytype_null,
498     &keytype_des,
499     &keytype_des3_derived,
500     &keytype_des3,
501     &keytype_arcfour
502 };
503 
504 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
505 
506 static 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 
517 struct 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 
531 struct salt_type des3_salt[] = {
532     {
533 	KRB5_PW_SALT,
534 	"pw-salt",
535 	DES3_string_to_key
536     },
537     { 0 }
538 };
539 
540 struct salt_type des3_salt_derived[] = {
541     {
542 	KRB5_PW_SALT,
543 	"pw-salt",
544 	DES3_string_to_key_derived
545     },
546     { 0 }
547 };
548 
549 struct salt_type arcfour_salt[] = {
550     {
551 	KRB5_PW_SALT,
552 	"pw-salt",
553 	ARCFOUR_string_to_key
554     },
555     { 0 }
556 };
557 
558 krb5_error_code
559 krb5_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 
581 krb5_error_code
582 krb5_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 
602 krb5_error_code
603 krb5_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 
631 krb5_error_code
632 krb5_free_salt(krb5_context context,
633 	       krb5_salt salt)
634 {
635     krb5_data_free(&salt.saltvalue);
636     return 0;
637 }
638 
639 krb5_error_code
640 krb5_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 
657 krb5_error_code
658 krb5_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 
670 krb5_error_code
671 krb5_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 
687 krb5_error_code
688 krb5_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 
700 krb5_error_code
701 krb5_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 
714 krb5_error_code
715 krb5_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 
728 krb5_error_code
729 krb5_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 
749 static 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 
776 static void
777 NONE_checksum(krb5_context context,
778 	      struct key_data *key,
779 	      void *data,
780 	      size_t len,
781 	      Checksum *C)
782 {
783 }
784 
785 static void
786 CRC32_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 
802 static void
803 RSA_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 
815 static void
816 RSA_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 
840 static krb5_error_code
841 RSA_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 
871 static void
872 RSA_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 
884 static void
885 RSA_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 
909 static krb5_error_code
910 RSA_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 
941 static void
942 RSA_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 
967 static krb5_error_code
968 RSA_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 
999 static void
1000 SHA1_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 */
1013 static void
1014 hmac(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 
1058 static void
1059 HMAC_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 
1070 struct checksum_type checksum_none = {
1071     CKSUMTYPE_NONE,
1072     "none",
1073     1,
1074     0,
1075     0,
1076     NONE_checksum,
1077     NULL
1078 };
1079 struct checksum_type checksum_crc32 = {
1080     CKSUMTYPE_CRC32,
1081     "crc32",
1082     1,
1083     4,
1084     0,
1085     CRC32_checksum,
1086     NULL
1087 };
1088 struct 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 };
1097 struct 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
1107 struct checksum_type checksum_des_mac = {
1108     CKSUMTYPE_DES_MAC,
1109     "des-mac",
1110     0,
1111     0,
1112     0,
1113     DES_MAC_checksum,
1114 };
1115 struct 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 };
1123 struct 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
1133 struct 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 };
1142 struct 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 };
1151 struct 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 };
1160 struct checksum_type checksum_sha1 = {
1161     CKSUMTYPE_SHA1,
1162     "sha1",
1163     64,
1164     20,
1165     F_CPROOF,
1166     SHA1_checksum,
1167     NULL
1168 };
1169 struct 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 
1179 struct 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 
1196 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1197 
1198 static 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 
1208 static krb5_error_code
1209 get_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 
1238 static krb5_error_code
1239 do_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 
1264 static krb5_error_code
1265 create_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 
1286 krb5_error_code
1287 krb5_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 
1299 static krb5_error_code
1300 verify_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 
1343 krb5_error_code
1344 krb5_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 
1355 krb5_error_code
1356 krb5_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 
1367 krb5_boolean
1368 krb5_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 
1377 krb5_boolean
1378 krb5_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 
1391 static void
1392 NULL_encrypt(struct key_data *key,
1393 	     void *data,
1394 	     size_t len,
1395 	     krb5_boolean encrypt)
1396 {
1397 }
1398 
1399 static void
1400 DES_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 
1411 static void
1412 DES_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 
1423 static void
1424 DES3_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 
1435 static void
1436 ARCFOUR_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 
1448 static 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 
1550 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
1551 
1552 
1553 static 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 
1564 krb5_error_code
1565 krb5_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 
1579 krb5_error_code
1580 krb5_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 
1593 krb5_error_code
1594 krb5_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
1606 krb5_error_code
1607 krb5_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 
1620 krb5_error_code
1621 krb5_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 
1654 krb5_error_code
1655 krb5_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 
1678 krb5_error_code
1679 krb5_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 */
1686 krb5_boolean
1687 krb5_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 
1696 static krb5_boolean
1697 derived_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 
1707 static krb5_error_code
1708 encrypt_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 
1771 static krb5_error_code
1772 encrypt_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 
1833 static krb5_error_code
1834 decrypt_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 
1897 static krb5_error_code
1898 decrypt_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 
1949 krb5_error_code
1950 krb5_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 
1964 krb5_error_code
1965 krb5_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 
1982 krb5_error_code
1983 krb5_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 
1997 krb5_error_code
1998 krb5_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 
2012 void
2013 krb5_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 
2038 static void
2039 DES3_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 
2073 static krb5_error_code
2074 derive_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 
2133 static 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 
2147 static 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 
2173 krb5_error_code
2174 krb5_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 
2201 static void
2202 free_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 
2211 static void
2212 free_key_usage(krb5_context context, struct key_usage *ku)
2213 {
2214     free_key_data(context, &ku->key);
2215 }
2216 
2217 krb5_error_code
2218 krb5_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 
2231 krb5_error_code
2232 krb5_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 
2266 size_t
2267 krb5_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 
2282 static krb5_error_code
2283 krb5_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 
2296 static void
2297 krb5_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