xref: /freebsd/crypto/heimdal/lib/krb5/crypto.c (revision 51a9219f5780e61e1437d25220bf8750d9df7f8b)
1 /*
2  * Copyright (c) 1997 - 2002 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "krb5_locl.h"
35 RCSID("$Id: crypto.c,v 1.66 2002/09/03 19:58:15 joda 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 #define F_SPECIAL	32	/* backwards */
70 
71 struct salt_type {
72     krb5_salttype type;
73     const char *name;
74     krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
75 				     krb5_salt, krb5_keyblock*);
76 };
77 
78 struct key_type {
79     krb5_keytype type; /* XXX */
80     const char *name;
81     size_t bits;
82     size_t size;
83     size_t schedule_size;
84 #if 0
85     krb5_enctype best_etype;
86 #endif
87     void (*random_key)(krb5_context, krb5_keyblock*);
88     void (*schedule)(krb5_context, struct key_data *);
89     struct salt_type *string_to_key;
90 };
91 
92 struct checksum_type {
93     krb5_cksumtype type;
94     const char *name;
95     size_t blocksize;
96     size_t checksumsize;
97     unsigned flags;
98     void (*checksum)(krb5_context context,
99 		     struct key_data *key,
100 		     const void *buf, size_t len,
101 		     unsigned usage,
102 		     Checksum *csum);
103     krb5_error_code (*verify)(krb5_context context,
104 			      struct key_data *key,
105 			      const void *buf, size_t len,
106 			      unsigned usage,
107 			      Checksum *csum);
108 };
109 
110 struct encryption_type {
111     krb5_enctype type;
112     const char *name;
113     size_t blocksize;
114     size_t confoundersize;
115     struct key_type *keytype;
116     struct checksum_type *checksum;
117     struct checksum_type *keyed_checksum;
118     unsigned flags;
119     krb5_error_code (*encrypt)(krb5_context context,
120 			       struct key_data *key,
121 			       void *data, size_t len,
122 			       krb5_boolean encrypt,
123 			       int usage,
124 			       void *ivec);
125 };
126 
127 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
128 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
129 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
130 
131 static struct checksum_type *_find_checksum(krb5_cksumtype type);
132 static struct encryption_type *_find_enctype(krb5_enctype type);
133 static struct key_type *_find_keytype(krb5_keytype type);
134 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
135 					unsigned, struct key_data**);
136 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
137 
138 /************************************************************
139  *                                                          *
140  ************************************************************/
141 
142 static void
143 krb5_DES_random_key(krb5_context context,
144 	       krb5_keyblock *key)
145 {
146     des_cblock *k = key->keyvalue.data;
147     do {
148 	krb5_generate_random_block(k, sizeof(des_cblock));
149 	des_set_odd_parity(k);
150     } while(des_is_weak_key(k));
151 }
152 
153 static void
154 krb5_DES_schedule(krb5_context context,
155 	     struct key_data *key)
156 {
157     des_set_key(key->key->keyvalue.data, key->schedule->data);
158 }
159 
160 static void
161 DES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key)
162 {
163     des_key_schedule schedule;
164     int i;
165     int reverse = 0;
166     unsigned char *p;
167 
168     unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
169 			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
170     memset(key, 0, 8);
171 
172     p = (unsigned char*)key;
173     for (i = 0; i < length; i++) {
174 	unsigned char tmp = data[i];
175 	if (!reverse)
176 	    *p++ ^= (tmp << 1);
177 	else
178 	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
179 	if((i % 8) == 7)
180 	    reverse = !reverse;
181     }
182     des_set_odd_parity(key);
183     if(des_is_weak_key(key))
184 	(*key)[7] ^= 0xF0;
185     des_set_key(key, schedule);
186     des_cbc_cksum((void*)data, key, length, schedule, key);
187     memset(schedule, 0, sizeof(schedule));
188     des_set_odd_parity(key);
189 }
190 
191 static krb5_error_code
192 krb5_DES_string_to_key(krb5_context context,
193 		  krb5_enctype enctype,
194 		  krb5_data password,
195 		  krb5_salt salt,
196 		  krb5_keyblock *key)
197 {
198     unsigned char *s;
199     size_t len;
200     des_cblock tmp;
201 
202     len = password.length + salt.saltvalue.length;
203     s = malloc(len);
204     if(len > 0 && s == NULL) {
205 	krb5_set_error_string(context, "malloc: out of memory");
206 	return ENOMEM;
207     }
208     memcpy(s, password.data, password.length);
209     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
210     DES_string_to_key_int(s, len, &tmp);
211     key->keytype = enctype;
212     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
213     memset(&tmp, 0, sizeof(tmp));
214     memset(s, 0, len);
215     free(s);
216     return 0;
217 }
218 
219 /* This defines the Andrew string_to_key function.  It accepts a password
220  * string as input and converts its via a one-way encryption algorithm to a DES
221  * encryption key.  It is compatible with the original Andrew authentication
222  * service password database.
223  */
224 
225 /*
226  * Short passwords, i.e 8 characters or less.
227  */
228 static void
229 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
230 			    krb5_data cell,
231 			    des_cblock *key)
232 {
233     char  password[8+1];	/* crypt is limited to 8 chars anyway */
234     int   i;
235 
236     for(i = 0; i < 8; i++) {
237 	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
238 		 ((i < cell.length) ?
239 		  tolower(((unsigned char*)cell.data)[i]) : 0);
240 	password[i] = c ? c : 'X';
241     }
242     password[8] = '\0';
243 
244     memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
245 
246     /* parity is inserted into the LSB so left shift each byte up one
247        bit. This allows ascii characters with a zero MSB to retain as
248        much significance as possible. */
249     for (i = 0; i < sizeof(des_cblock); i++)
250 	((unsigned char*)key)[i] <<= 1;
251     des_set_odd_parity (key);
252 }
253 
254 /*
255  * Long passwords, i.e 9 characters or more.
256  */
257 static void
258 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
259 				 krb5_data cell,
260 				 des_cblock *key)
261 {
262     des_key_schedule schedule;
263     des_cblock temp_key;
264     des_cblock ivec;
265     char password[512];
266     size_t passlen;
267 
268     memcpy(password, pw.data, min(pw.length, sizeof(password)));
269     if(pw.length < sizeof(password)) {
270 	int len = min(cell.length, sizeof(password) - pw.length);
271 	int i;
272 
273 	memcpy(password + pw.length, cell.data, len);
274 	for (i = pw.length; i < pw.length + len; ++i)
275 	    password[i] = tolower((unsigned char)password[i]);
276     }
277     passlen = min(sizeof(password), pw.length + cell.length);
278     memcpy(&ivec, "kerberos", 8);
279     memcpy(&temp_key, "kerberos", 8);
280     des_set_odd_parity (&temp_key);
281     des_set_key (&temp_key, schedule);
282     des_cbc_cksum (password, &ivec, passlen, schedule, &ivec);
283 
284     memcpy(&temp_key, &ivec, 8);
285     des_set_odd_parity (&temp_key);
286     des_set_key (&temp_key, schedule);
287     des_cbc_cksum (password, key, passlen, schedule, &ivec);
288     memset(&schedule, 0, sizeof(schedule));
289     memset(&temp_key, 0, sizeof(temp_key));
290     memset(&ivec, 0, sizeof(ivec));
291     memset(password, 0, sizeof(password));
292 
293     des_set_odd_parity (key);
294 }
295 
296 static krb5_error_code
297 DES_AFS3_string_to_key(krb5_context context,
298 		       krb5_enctype enctype,
299 		       krb5_data password,
300 		       krb5_salt salt,
301 		       krb5_keyblock *key)
302 {
303     des_cblock tmp;
304     if(password.length > 8)
305 	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
306     else
307 	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
308     key->keytype = enctype;
309     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
310     memset(&key, 0, sizeof(key));
311     return 0;
312 }
313 
314 static void
315 DES3_random_key(krb5_context context,
316 		krb5_keyblock *key)
317 {
318     des_cblock *k = key->keyvalue.data;
319     do {
320 	krb5_generate_random_block(k, 3 * sizeof(des_cblock));
321 	des_set_odd_parity(&k[0]);
322 	des_set_odd_parity(&k[1]);
323 	des_set_odd_parity(&k[2]);
324     } while(des_is_weak_key(&k[0]) ||
325 	    des_is_weak_key(&k[1]) ||
326 	    des_is_weak_key(&k[2]));
327 }
328 
329 static void
330 DES3_schedule(krb5_context context,
331 	      struct key_data *key)
332 {
333     des_cblock *k = key->key->keyvalue.data;
334     des_key_schedule *s = key->schedule->data;
335     des_set_key(&k[0], s[0]);
336     des_set_key(&k[1], s[1]);
337     des_set_key(&k[2], s[2]);
338 }
339 
340 /*
341  * A = A xor B. A & B are 8 bytes.
342  */
343 
344 static void
345 xor (des_cblock *key, const unsigned char *b)
346 {
347     unsigned char *a = (unsigned char*)key;
348     a[0] ^= b[0];
349     a[1] ^= b[1];
350     a[2] ^= b[2];
351     a[3] ^= b[3];
352     a[4] ^= b[4];
353     a[5] ^= b[5];
354     a[6] ^= b[6];
355     a[7] ^= b[7];
356 }
357 
358 static krb5_error_code
359 DES3_string_to_key(krb5_context context,
360 		   krb5_enctype enctype,
361 		   krb5_data password,
362 		   krb5_salt salt,
363 		   krb5_keyblock *key)
364 {
365     char *str;
366     size_t len;
367     unsigned char tmp[24];
368     des_cblock keys[3];
369 
370     len = password.length + salt.saltvalue.length;
371     str = malloc(len);
372     if(len != 0 && str == NULL) {
373 	krb5_set_error_string(context, "malloc: out of memory");
374 	return ENOMEM;
375     }
376     memcpy(str, password.data, password.length);
377     memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
378     {
379 	des_cblock ivec;
380 	des_key_schedule s[3];
381 	int i;
382 
383 	_krb5_n_fold(str, len, tmp, 24);
384 
385 	for(i = 0; i < 3; i++){
386 	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
387 	    des_set_odd_parity(keys + i);
388 	    if(des_is_weak_key(keys + i))
389 		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
390 	    des_set_key(keys + i, s[i]);
391 	}
392 	memset(&ivec, 0, sizeof(ivec));
393 	des_ede3_cbc_encrypt(tmp,
394 			     tmp, sizeof(tmp),
395 			     s[0], s[1], s[2], &ivec, DES_ENCRYPT);
396 	memset(s, 0, sizeof(s));
397 	memset(&ivec, 0, sizeof(ivec));
398 	for(i = 0; i < 3; i++){
399 	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
400 	    des_set_odd_parity(keys + i);
401 	    if(des_is_weak_key(keys + i))
402 		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
403 	}
404 	memset(tmp, 0, sizeof(tmp));
405     }
406     key->keytype = enctype;
407     krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
408     memset(keys, 0, sizeof(keys));
409     memset(str, 0, len);
410     free(str);
411     return 0;
412 }
413 
414 static krb5_error_code
415 DES3_string_to_key_derived(krb5_context context,
416 			   krb5_enctype enctype,
417 			   krb5_data password,
418 			   krb5_salt salt,
419 			   krb5_keyblock *key)
420 {
421     krb5_error_code ret;
422     size_t len = password.length + salt.saltvalue.length;
423     char *s;
424 
425     s = malloc(len);
426     if(len != 0 && s == NULL) {
427 	krb5_set_error_string(context, "malloc: out of memory");
428 	return ENOMEM;
429     }
430     memcpy(s, password.data, password.length);
431     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
432     ret = krb5_string_to_key_derived(context,
433 				     s,
434 				     len,
435 				     enctype,
436 				     key);
437     memset(s, 0, len);
438     free(s);
439     return ret;
440 }
441 
442 /*
443  * ARCFOUR
444  */
445 
446 static void
447 ARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
448 {
449     krb5_generate_random_block (key->keyvalue.data,
450 				key->keyvalue.length);
451 }
452 
453 static void
454 ARCFOUR_schedule(krb5_context context, struct key_data *kd)
455 {
456     RC4_set_key (kd->schedule->data,
457 		 kd->key->keyvalue.length, kd->key->keyvalue.data);
458 }
459 
460 static krb5_error_code
461 ARCFOUR_string_to_key(krb5_context context,
462 		  krb5_enctype enctype,
463 		  krb5_data password,
464 		  krb5_salt salt,
465 		  krb5_keyblock *key)
466 {
467     char *s, *p;
468     size_t len;
469     int i;
470     MD4_CTX m;
471 
472     len = 2 * password.length;
473     s = malloc (len);
474     if (len != 0 && s == NULL) {
475 	krb5_set_error_string(context, "malloc: out of memory");
476 	return ENOMEM;
477     }
478     for (p = s, i = 0; i < password.length; ++i) {
479 	*p++ = ((char *)password.data)[i];
480 	*p++ = 0;
481     }
482     MD4_Init (&m);
483     MD4_Update (&m, s, len);
484     key->keytype = enctype;
485     krb5_data_alloc (&key->keyvalue, 16);
486     MD4_Final (key->keyvalue.data, &m);
487     memset (s, 0, len);
488     free (s);
489     return 0;
490 }
491 
492 extern struct salt_type des_salt[],
493     des3_salt[], des3_salt_derived[], arcfour_salt[];
494 
495 struct key_type keytype_null = {
496     KEYTYPE_NULL,
497     "null",
498     0,
499     0,
500     0,
501     NULL,
502     NULL,
503     NULL
504 };
505 
506 struct key_type keytype_des = {
507     KEYTYPE_DES,
508     "des",
509     56,
510     sizeof(des_cblock),
511     sizeof(des_key_schedule),
512     krb5_DES_random_key,
513     krb5_DES_schedule,
514     des_salt
515 };
516 
517 struct key_type keytype_des3 = {
518     KEYTYPE_DES3,
519     "des3",
520     168,
521     3 * sizeof(des_cblock),
522     3 * sizeof(des_key_schedule),
523     DES3_random_key,
524     DES3_schedule,
525     des3_salt
526 };
527 
528 struct key_type keytype_des3_derived = {
529     KEYTYPE_DES3,
530     "des3",
531     168,
532     3 * sizeof(des_cblock),
533     3 * sizeof(des_key_schedule),
534     DES3_random_key,
535     DES3_schedule,
536     des3_salt_derived
537 };
538 
539 struct key_type keytype_arcfour = {
540     KEYTYPE_ARCFOUR,
541     "arcfour",
542     128,
543     16,
544     sizeof(RC4_KEY),
545     ARCFOUR_random_key,
546     ARCFOUR_schedule,
547     arcfour_salt
548 };
549 
550 struct key_type *keytypes[] = {
551     &keytype_null,
552     &keytype_des,
553     &keytype_des3_derived,
554     &keytype_des3,
555     &keytype_arcfour
556 };
557 
558 static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
559 
560 static struct key_type *
561 _find_keytype(krb5_keytype type)
562 {
563     int i;
564     for(i = 0; i < num_keytypes; i++)
565 	if(keytypes[i]->type == type)
566 	    return keytypes[i];
567     return NULL;
568 }
569 
570 
571 struct salt_type des_salt[] = {
572     {
573 	KRB5_PW_SALT,
574 	"pw-salt",
575 	krb5_DES_string_to_key
576     },
577     {
578 	KRB5_AFS3_SALT,
579 	"afs3-salt",
580 	DES_AFS3_string_to_key
581     },
582     { 0 }
583 };
584 
585 struct salt_type des3_salt[] = {
586     {
587 	KRB5_PW_SALT,
588 	"pw-salt",
589 	DES3_string_to_key
590     },
591     { 0 }
592 };
593 
594 struct salt_type des3_salt_derived[] = {
595     {
596 	KRB5_PW_SALT,
597 	"pw-salt",
598 	DES3_string_to_key_derived
599     },
600     { 0 }
601 };
602 
603 struct salt_type arcfour_salt[] = {
604     {
605 	KRB5_PW_SALT,
606 	"pw-salt",
607 	ARCFOUR_string_to_key
608     },
609     { 0 }
610 };
611 
612 krb5_error_code
613 krb5_salttype_to_string (krb5_context context,
614 			 krb5_enctype etype,
615 			 krb5_salttype stype,
616 			 char **string)
617 {
618     struct encryption_type *e;
619     struct salt_type *st;
620 
621     e = _find_enctype (etype);
622     if (e == NULL) {
623 	krb5_set_error_string(context, "encryption type %d not supported",
624 			      etype);
625 	return KRB5_PROG_ETYPE_NOSUPP;
626     }
627     for (st = e->keytype->string_to_key; st && st->type; st++) {
628 	if (st->type == stype) {
629 	    *string = strdup (st->name);
630 	    if (*string == NULL) {
631 		krb5_set_error_string(context, "malloc: out of memory");
632 		return ENOMEM;
633 	    }
634 	    return 0;
635 	}
636     }
637     krb5_set_error_string(context, "salttype %d not supported", stype);
638     return HEIM_ERR_SALTTYPE_NOSUPP;
639 }
640 
641 krb5_error_code
642 krb5_string_to_salttype (krb5_context context,
643 			 krb5_enctype etype,
644 			 const char *string,
645 			 krb5_salttype *salttype)
646 {
647     struct encryption_type *e;
648     struct salt_type *st;
649 
650     e = _find_enctype (etype);
651     if (e == NULL) {
652 	krb5_set_error_string(context, "encryption type %d not supported",
653 			      etype);
654 	return KRB5_PROG_ETYPE_NOSUPP;
655     }
656     for (st = e->keytype->string_to_key; st && st->type; st++) {
657 	if (strcasecmp (st->name, string) == 0) {
658 	    *salttype = st->type;
659 	    return 0;
660 	}
661     }
662     krb5_set_error_string(context, "salttype %s not supported", string);
663     return HEIM_ERR_SALTTYPE_NOSUPP;
664 }
665 
666 krb5_error_code
667 krb5_get_pw_salt(krb5_context context,
668 		 krb5_const_principal principal,
669 		 krb5_salt *salt)
670 {
671     size_t len;
672     int i;
673     krb5_error_code ret;
674     char *p;
675 
676     salt->salttype = KRB5_PW_SALT;
677     len = strlen(principal->realm);
678     for (i = 0; i < principal->name.name_string.len; ++i)
679 	len += strlen(principal->name.name_string.val[i]);
680     ret = krb5_data_alloc (&salt->saltvalue, len);
681     if (ret)
682 	return ret;
683     p = salt->saltvalue.data;
684     memcpy (p, principal->realm, strlen(principal->realm));
685     p += strlen(principal->realm);
686     for (i = 0; i < principal->name.name_string.len; ++i) {
687 	memcpy (p,
688 		principal->name.name_string.val[i],
689 		strlen(principal->name.name_string.val[i]));
690 	p += strlen(principal->name.name_string.val[i]);
691     }
692     return 0;
693 }
694 
695 krb5_error_code
696 krb5_free_salt(krb5_context context,
697 	       krb5_salt salt)
698 {
699     krb5_data_free(&salt.saltvalue);
700     return 0;
701 }
702 
703 krb5_error_code
704 krb5_string_to_key_data (krb5_context context,
705 			 krb5_enctype enctype,
706 			 krb5_data password,
707 			 krb5_principal principal,
708 			 krb5_keyblock *key)
709 {
710     krb5_error_code ret;
711     krb5_salt salt;
712 
713     ret = krb5_get_pw_salt(context, principal, &salt);
714     if(ret)
715 	return ret;
716     ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
717     krb5_free_salt(context, salt);
718     return ret;
719 }
720 
721 krb5_error_code
722 krb5_string_to_key (krb5_context context,
723 		    krb5_enctype enctype,
724 		    const char *password,
725 		    krb5_principal principal,
726 		    krb5_keyblock *key)
727 {
728     krb5_data pw;
729     pw.data = (void*)password;
730     pw.length = strlen(password);
731     return krb5_string_to_key_data(context, enctype, pw, principal, key);
732 }
733 
734 /*
735  * Do a string -> key for encryption type `enctype' operation on
736  * `password' (with salt `salt'), returning the resulting key in `key'
737  */
738 
739 krb5_error_code
740 krb5_string_to_key_data_salt (krb5_context context,
741 			      krb5_enctype enctype,
742 			      krb5_data password,
743 			      krb5_salt salt,
744 			      krb5_keyblock *key)
745 {
746     struct encryption_type *et =_find_enctype(enctype);
747     struct salt_type *st;
748     if(et == NULL) {
749 	krb5_set_error_string(context, "encryption type %d not supported",
750 			      enctype);
751 	return KRB5_PROG_ETYPE_NOSUPP;
752     }
753     for(st = et->keytype->string_to_key; st && st->type; st++)
754 	if(st->type == salt.salttype)
755 	    return (*st->string_to_key)(context, enctype, password, salt, key);
756     krb5_set_error_string(context, "salt type %d not supported",
757 			  salt.salttype);
758     return HEIM_ERR_SALTTYPE_NOSUPP;
759 }
760 
761 /*
762  * Do a string -> key for encryption type `enctype' operation on the
763  * string `password' (with salt `salt'), returning the resulting key
764  * in `key'
765  */
766 
767 krb5_error_code
768 krb5_string_to_key_salt (krb5_context context,
769 			 krb5_enctype enctype,
770 			 const char *password,
771 			 krb5_salt salt,
772 			 krb5_keyblock *key)
773 {
774     krb5_data pw;
775     pw.data = (void*)password;
776     pw.length = strlen(password);
777     return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
778 }
779 
780 krb5_error_code
781 krb5_keytype_to_string(krb5_context context,
782 		       krb5_keytype keytype,
783 		       char **string)
784 {
785     struct key_type *kt = _find_keytype(keytype);
786     if(kt == NULL) {
787 	krb5_set_error_string(context, "key type %d not supported", keytype);
788 	return KRB5_PROG_KEYTYPE_NOSUPP;
789     }
790     *string = strdup(kt->name);
791     if(*string == NULL) {
792 	krb5_set_error_string(context, "malloc: out of memory");
793 	return ENOMEM;
794     }
795     return 0;
796 }
797 
798 krb5_error_code
799 krb5_string_to_keytype(krb5_context context,
800 		       const char *string,
801 		       krb5_keytype *keytype)
802 {
803     int i;
804     for(i = 0; i < num_keytypes; i++)
805 	if(strcasecmp(keytypes[i]->name, string) == 0){
806 	    *keytype = keytypes[i]->type;
807 	    return 0;
808 	}
809     krb5_set_error_string(context, "key type %s not supported", string);
810     return KRB5_PROG_KEYTYPE_NOSUPP;
811 }
812 
813 krb5_error_code
814 krb5_generate_random_keyblock(krb5_context context,
815 			      krb5_enctype type,
816 			      krb5_keyblock *key)
817 {
818     krb5_error_code ret;
819     struct encryption_type *et = _find_enctype(type);
820     if(et == NULL) {
821 	krb5_set_error_string(context, "encryption type %d not supported",
822 			      type);
823 	return KRB5_PROG_ETYPE_NOSUPP;
824     }
825     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
826     if(ret)
827 	return ret;
828     key->keytype = type;
829     if(et->keytype->random_key)
830 	(*et->keytype->random_key)(context, key);
831     else
832 	krb5_generate_random_block(key->keyvalue.data,
833 				   key->keyvalue.length);
834     return 0;
835 }
836 
837 static krb5_error_code
838 _key_schedule(krb5_context context,
839 	      struct key_data *key)
840 {
841     krb5_error_code ret;
842     struct encryption_type *et = _find_enctype(key->key->keytype);
843     struct key_type *kt = et->keytype;
844 
845     if(kt->schedule == NULL)
846 	return 0;
847     if (key->schedule != NULL)
848 	return 0;
849     ALLOC(key->schedule, 1);
850     if(key->schedule == NULL) {
851 	krb5_set_error_string(context, "malloc: out of memory");
852 	return ENOMEM;
853     }
854     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
855     if(ret) {
856 	free(key->schedule);
857 	key->schedule = NULL;
858 	return ret;
859     }
860     (*kt->schedule)(context, key);
861     return 0;
862 }
863 
864 /************************************************************
865  *                                                          *
866  ************************************************************/
867 
868 static void
869 NONE_checksum(krb5_context context,
870 	      struct key_data *key,
871 	      const void *data,
872 	      size_t len,
873 	      unsigned usage,
874 	      Checksum *C)
875 {
876 }
877 
878 static void
879 CRC32_checksum(krb5_context context,
880 	       struct key_data *key,
881 	       const void *data,
882 	       size_t len,
883 	       unsigned usage,
884 	       Checksum *C)
885 {
886     u_int32_t crc;
887     unsigned char *r = C->checksum.data;
888     _krb5_crc_init_table ();
889     crc = _krb5_crc_update (data, len, 0);
890     r[0] = crc & 0xff;
891     r[1] = (crc >> 8)  & 0xff;
892     r[2] = (crc >> 16) & 0xff;
893     r[3] = (crc >> 24) & 0xff;
894 }
895 
896 static void
897 RSA_MD4_checksum(krb5_context context,
898 		 struct key_data *key,
899 		 const void *data,
900 		 size_t len,
901 		 unsigned usage,
902 		 Checksum *C)
903 {
904     MD4_CTX m;
905 
906     MD4_Init (&m);
907     MD4_Update (&m, data, len);
908     MD4_Final (C->checksum.data, &m);
909 }
910 
911 static void
912 RSA_MD4_DES_checksum(krb5_context context,
913 		     struct key_data *key,
914 		     const void *data,
915 		     size_t len,
916 		     unsigned usage,
917 		     Checksum *cksum)
918 {
919     MD4_CTX md4;
920     des_cblock ivec;
921     unsigned char *p = cksum->checksum.data;
922 
923     krb5_generate_random_block(p, 8);
924     MD4_Init (&md4);
925     MD4_Update (&md4, p, 8);
926     MD4_Update (&md4, data, len);
927     MD4_Final (p + 8, &md4);
928     memset (&ivec, 0, sizeof(ivec));
929     des_cbc_encrypt(p,
930 		    p,
931 		    24,
932 		    key->schedule->data,
933 		    &ivec,
934 		    DES_ENCRYPT);
935 }
936 
937 static krb5_error_code
938 RSA_MD4_DES_verify(krb5_context context,
939 		   struct key_data *key,
940 		   const void *data,
941 		   size_t len,
942 		   unsigned usage,
943 		   Checksum *C)
944 {
945     MD4_CTX md4;
946     unsigned char tmp[24];
947     unsigned char res[16];
948     des_cblock ivec;
949     krb5_error_code ret = 0;
950 
951     memset(&ivec, 0, sizeof(ivec));
952     des_cbc_encrypt(C->checksum.data,
953 		    (void*)tmp,
954 		    C->checksum.length,
955 		    key->schedule->data,
956 		    &ivec,
957 		    DES_DECRYPT);
958     MD4_Init (&md4);
959     MD4_Update (&md4, tmp, 8); /* confounder */
960     MD4_Update (&md4, data, len);
961     MD4_Final (res, &md4);
962     if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
963 	krb5_clear_error_string (context);
964 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
965     }
966     memset(tmp, 0, sizeof(tmp));
967     memset(res, 0, sizeof(res));
968     return ret;
969 }
970 
971 static void
972 RSA_MD5_checksum(krb5_context context,
973 		 struct key_data *key,
974 		 const void *data,
975 		 size_t len,
976 		 unsigned usage,
977 		 Checksum *C)
978 {
979     MD5_CTX m;
980 
981     MD5_Init  (&m);
982     MD5_Update(&m, data, len);
983     MD5_Final (C->checksum.data, &m);
984 }
985 
986 static void
987 RSA_MD5_DES_checksum(krb5_context context,
988 		     struct key_data *key,
989 		     const void *data,
990 		     size_t len,
991 		     unsigned usage,
992 		     Checksum *C)
993 {
994     MD5_CTX md5;
995     des_cblock ivec;
996     unsigned char *p = C->checksum.data;
997 
998     krb5_generate_random_block(p, 8);
999     MD5_Init (&md5);
1000     MD5_Update (&md5, p, 8);
1001     MD5_Update (&md5, data, len);
1002     MD5_Final (p + 8, &md5);
1003     memset (&ivec, 0, sizeof(ivec));
1004     des_cbc_encrypt(p,
1005 		    p,
1006 		    24,
1007 		    key->schedule->data,
1008 		    &ivec,
1009 		    DES_ENCRYPT);
1010 }
1011 
1012 static krb5_error_code
1013 RSA_MD5_DES_verify(krb5_context context,
1014 		   struct key_data *key,
1015 		   const void *data,
1016 		   size_t len,
1017 		   unsigned usage,
1018 		   Checksum *C)
1019 {
1020     MD5_CTX md5;
1021     unsigned char tmp[24];
1022     unsigned char res[16];
1023     des_cblock ivec;
1024     des_key_schedule *sched = key->schedule->data;
1025     krb5_error_code ret = 0;
1026 
1027     memset(&ivec, 0, sizeof(ivec));
1028     des_cbc_encrypt(C->checksum.data,
1029 		    (void*)tmp,
1030 		    C->checksum.length,
1031 		    sched[0],
1032 		    &ivec,
1033 		    DES_DECRYPT);
1034     MD5_Init (&md5);
1035     MD5_Update (&md5, tmp, 8); /* confounder */
1036     MD5_Update (&md5, data, len);
1037     MD5_Final (res, &md5);
1038     if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
1039 	krb5_clear_error_string (context);
1040 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1041     }
1042     memset(tmp, 0, sizeof(tmp));
1043     memset(res, 0, sizeof(res));
1044     return ret;
1045 }
1046 
1047 static void
1048 RSA_MD5_DES3_checksum(krb5_context context,
1049 		      struct key_data *key,
1050 		      const void *data,
1051 		      size_t len,
1052 		      unsigned usage,
1053 		      Checksum *C)
1054 {
1055     MD5_CTX md5;
1056     des_cblock ivec;
1057     unsigned char *p = C->checksum.data;
1058     des_key_schedule *sched = key->schedule->data;
1059 
1060     krb5_generate_random_block(p, 8);
1061     MD5_Init (&md5);
1062     MD5_Update (&md5, p, 8);
1063     MD5_Update (&md5, data, len);
1064     MD5_Final (p + 8, &md5);
1065     memset (&ivec, 0, sizeof(ivec));
1066     des_ede3_cbc_encrypt(p,
1067 			 p,
1068 			 24,
1069 			 sched[0], sched[1], sched[2],
1070 			 &ivec,
1071 			 DES_ENCRYPT);
1072 }
1073 
1074 static krb5_error_code
1075 RSA_MD5_DES3_verify(krb5_context context,
1076 		    struct key_data *key,
1077 		    const void *data,
1078 		    size_t len,
1079 		    unsigned usage,
1080 		    Checksum *C)
1081 {
1082     MD5_CTX md5;
1083     unsigned char tmp[24];
1084     unsigned char res[16];
1085     des_cblock ivec;
1086     des_key_schedule *sched = key->schedule->data;
1087     krb5_error_code ret = 0;
1088 
1089     memset(&ivec, 0, sizeof(ivec));
1090     des_ede3_cbc_encrypt(C->checksum.data,
1091 			 (void*)tmp,
1092 			 C->checksum.length,
1093 			 sched[0], sched[1], sched[2],
1094 			 &ivec,
1095 			 DES_DECRYPT);
1096     MD5_Init (&md5);
1097     MD5_Update (&md5, tmp, 8); /* confounder */
1098     MD5_Update (&md5, data, len);
1099     MD5_Final (res, &md5);
1100     if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
1101 	krb5_clear_error_string (context);
1102 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1103     }
1104     memset(tmp, 0, sizeof(tmp));
1105     memset(res, 0, sizeof(res));
1106     return ret;
1107 }
1108 
1109 static void
1110 SHA1_checksum(krb5_context context,
1111 	      struct key_data *key,
1112 	      const void *data,
1113 	      size_t len,
1114 	      unsigned usage,
1115 	      Checksum *C)
1116 {
1117     SHA_CTX m;
1118 
1119     SHA1_Init(&m);
1120     SHA1_Update(&m, data, len);
1121     SHA1_Final(C->checksum.data, &m);
1122 }
1123 
1124 /* HMAC according to RFC2104 */
1125 static void
1126 hmac(krb5_context context,
1127      struct checksum_type *cm,
1128      const void *data,
1129      size_t len,
1130      unsigned usage,
1131      struct key_data *keyblock,
1132      Checksum *result)
1133 {
1134     unsigned char *ipad, *opad;
1135     unsigned char *key;
1136     size_t key_len;
1137     int i;
1138 
1139     if(keyblock->key->keyvalue.length > cm->blocksize){
1140 	(*cm->checksum)(context,
1141 			keyblock,
1142 			keyblock->key->keyvalue.data,
1143 			keyblock->key->keyvalue.length,
1144 			usage,
1145 			result);
1146 	key = result->checksum.data;
1147 	key_len = result->checksum.length;
1148     } else {
1149 	key = keyblock->key->keyvalue.data;
1150 	key_len = keyblock->key->keyvalue.length;
1151     }
1152     ipad = malloc(cm->blocksize + len);
1153     opad = malloc(cm->blocksize + cm->checksumsize);
1154     memset(ipad, 0x36, cm->blocksize);
1155     memset(opad, 0x5c, cm->blocksize);
1156     for(i = 0; i < key_len; i++){
1157 	ipad[i] ^= key[i];
1158 	opad[i] ^= key[i];
1159     }
1160     memcpy(ipad + cm->blocksize, data, len);
1161     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1162 		    usage, result);
1163     memcpy(opad + cm->blocksize, result->checksum.data,
1164 	   result->checksum.length);
1165     (*cm->checksum)(context, keyblock, opad,
1166 		    cm->blocksize + cm->checksumsize, usage, result);
1167     memset(ipad, 0, cm->blocksize + len);
1168     free(ipad);
1169     memset(opad, 0, cm->blocksize + cm->checksumsize);
1170     free(opad);
1171 }
1172 
1173 static void
1174 HMAC_SHA1_DES3_checksum(krb5_context context,
1175 			struct key_data *key,
1176 			const void *data,
1177 			size_t len,
1178 			unsigned usage,
1179 			Checksum *result)
1180 {
1181     struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1182 
1183     hmac(context, c, data, len, usage, key, result);
1184 }
1185 
1186 /*
1187  * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1188  */
1189 
1190 static void
1191 HMAC_MD5_checksum(krb5_context context,
1192 		  struct key_data *key,
1193 		  const void *data,
1194 		  size_t len,
1195 		  unsigned usage,
1196 		  Checksum *result)
1197 {
1198     MD5_CTX md5;
1199     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1200     const char signature[] = "signaturekey";
1201     Checksum ksign_c;
1202     struct key_data ksign;
1203     krb5_keyblock kb;
1204     unsigned char t[4];
1205     unsigned char tmp[16];
1206     unsigned char ksign_c_data[16];
1207 
1208     ksign_c.checksum.length = sizeof(ksign_c_data);
1209     ksign_c.checksum.data   = ksign_c_data;
1210     hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1211     ksign.key = &kb;
1212     kb.keyvalue = ksign_c.checksum;
1213     MD5_Init (&md5);
1214     t[0] = (usage >>  0) & 0xFF;
1215     t[1] = (usage >>  8) & 0xFF;
1216     t[2] = (usage >> 16) & 0xFF;
1217     t[3] = (usage >> 24) & 0xFF;
1218     MD5_Update (&md5, t, 4);
1219     MD5_Update (&md5, data, len);
1220     MD5_Final (tmp, &md5);
1221     hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1222 }
1223 
1224 /*
1225  * same as previous but being used while encrypting.
1226  */
1227 
1228 static void
1229 HMAC_MD5_checksum_enc(krb5_context context,
1230 		      struct key_data *key,
1231 		      const void *data,
1232 		      size_t len,
1233 		      unsigned usage,
1234 		      Checksum *result)
1235 {
1236     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1237     Checksum ksign_c;
1238     struct key_data ksign;
1239     krb5_keyblock kb;
1240     unsigned char t[4];
1241     unsigned char ksign_c_data[16];
1242 
1243     t[0] = (usage >>  0) & 0xFF;
1244     t[1] = (usage >>  8) & 0xFF;
1245     t[2] = (usage >> 16) & 0xFF;
1246     t[3] = (usage >> 24) & 0xFF;
1247 
1248     ksign_c.checksum.length = sizeof(ksign_c_data);
1249     ksign_c.checksum.data   = ksign_c_data;
1250     hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
1251     ksign.key = &kb;
1252     kb.keyvalue = ksign_c.checksum;
1253     hmac(context, c, data, len, 0, &ksign, result);
1254 }
1255 
1256 struct checksum_type checksum_none = {
1257     CKSUMTYPE_NONE,
1258     "none",
1259     1,
1260     0,
1261     0,
1262     NONE_checksum,
1263     NULL
1264 };
1265 struct checksum_type checksum_crc32 = {
1266     CKSUMTYPE_CRC32,
1267     "crc32",
1268     1,
1269     4,
1270     0,
1271     CRC32_checksum,
1272     NULL
1273 };
1274 struct checksum_type checksum_rsa_md4 = {
1275     CKSUMTYPE_RSA_MD4,
1276     "rsa-md4",
1277     64,
1278     16,
1279     F_CPROOF,
1280     RSA_MD4_checksum,
1281     NULL
1282 };
1283 struct checksum_type checksum_rsa_md4_des = {
1284     CKSUMTYPE_RSA_MD4_DES,
1285     "rsa-md4-des",
1286     64,
1287     24,
1288     F_KEYED | F_CPROOF | F_VARIANT,
1289     RSA_MD4_DES_checksum,
1290     RSA_MD4_DES_verify
1291 };
1292 #if 0
1293 struct checksum_type checksum_des_mac = {
1294     CKSUMTYPE_DES_MAC,
1295     "des-mac",
1296     0,
1297     0,
1298     0,
1299     DES_MAC_checksum
1300 };
1301 struct checksum_type checksum_des_mac_k = {
1302     CKSUMTYPE_DES_MAC_K,
1303     "des-mac-k",
1304     0,
1305     0,
1306     0,
1307     DES_MAC_K_checksum
1308 };
1309 struct checksum_type checksum_rsa_md4_des_k = {
1310     CKSUMTYPE_RSA_MD4_DES_K,
1311     "rsa-md4-des-k",
1312     0,
1313     0,
1314     0,
1315     RSA_MD4_DES_K_checksum,
1316     RSA_MD4_DES_K_verify
1317 };
1318 #endif
1319 struct checksum_type checksum_rsa_md5 = {
1320     CKSUMTYPE_RSA_MD5,
1321     "rsa-md5",
1322     64,
1323     16,
1324     F_CPROOF,
1325     RSA_MD5_checksum,
1326     NULL
1327 };
1328 struct checksum_type checksum_rsa_md5_des = {
1329     CKSUMTYPE_RSA_MD5_DES,
1330     "rsa-md5-des",
1331     64,
1332     24,
1333     F_KEYED | F_CPROOF | F_VARIANT,
1334     RSA_MD5_DES_checksum,
1335     RSA_MD5_DES_verify
1336 };
1337 struct checksum_type checksum_rsa_md5_des3 = {
1338     CKSUMTYPE_RSA_MD5_DES3,
1339     "rsa-md5-des3",
1340     64,
1341     24,
1342     F_KEYED | F_CPROOF | F_VARIANT,
1343     RSA_MD5_DES3_checksum,
1344     RSA_MD5_DES3_verify
1345 };
1346 struct checksum_type checksum_sha1 = {
1347     CKSUMTYPE_SHA1,
1348     "sha1",
1349     64,
1350     20,
1351     F_CPROOF,
1352     SHA1_checksum,
1353     NULL
1354 };
1355 struct checksum_type checksum_hmac_sha1_des3 = {
1356     CKSUMTYPE_HMAC_SHA1_DES3,
1357     "hmac-sha1-des3",
1358     64,
1359     20,
1360     F_KEYED | F_CPROOF | F_DERIVED,
1361     HMAC_SHA1_DES3_checksum,
1362     NULL
1363 };
1364 
1365 struct checksum_type checksum_hmac_md5 = {
1366     CKSUMTYPE_HMAC_MD5,
1367     "hmac-md5",
1368     64,
1369     16,
1370     F_KEYED | F_CPROOF,
1371     HMAC_MD5_checksum,
1372     NULL
1373 };
1374 
1375 struct checksum_type checksum_hmac_md5_enc = {
1376     CKSUMTYPE_HMAC_MD5_ENC,
1377     "hmac-md5-enc",
1378     64,
1379     16,
1380     F_KEYED | F_CPROOF | F_PSEUDO,
1381     HMAC_MD5_checksum_enc,
1382     NULL
1383 };
1384 
1385 struct checksum_type *checksum_types[] = {
1386     &checksum_none,
1387     &checksum_crc32,
1388     &checksum_rsa_md4,
1389     &checksum_rsa_md4_des,
1390 #if 0
1391     &checksum_des_mac,
1392     &checksum_des_mac_k,
1393     &checksum_rsa_md4_des_k,
1394 #endif
1395     &checksum_rsa_md5,
1396     &checksum_rsa_md5_des,
1397     &checksum_rsa_md5_des3,
1398     &checksum_sha1,
1399     &checksum_hmac_sha1_des3,
1400     &checksum_hmac_md5,
1401     &checksum_hmac_md5_enc
1402 };
1403 
1404 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1405 
1406 static struct checksum_type *
1407 _find_checksum(krb5_cksumtype type)
1408 {
1409     int i;
1410     for(i = 0; i < num_checksums; i++)
1411 	if(checksum_types[i]->type == type)
1412 	    return checksum_types[i];
1413     return NULL;
1414 }
1415 
1416 static krb5_error_code
1417 get_checksum_key(krb5_context context,
1418 		 krb5_crypto crypto,
1419 		 unsigned usage,  /* not krb5_key_usage */
1420 		 struct checksum_type *ct,
1421 		 struct key_data **key)
1422 {
1423     krb5_error_code ret = 0;
1424 
1425     if(ct->flags & F_DERIVED)
1426 	ret = _get_derived_key(context, crypto, usage, key);
1427     else if(ct->flags & F_VARIANT) {
1428 	int i;
1429 
1430 	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1431 	if(*key == NULL) {
1432 	    krb5_set_error_string(context, "malloc: out of memory");
1433 	    return ENOMEM;
1434 	}
1435 	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1436 	if(ret)
1437 	    return ret;
1438 	for(i = 0; i < (*key)->key->keyvalue.length; i++)
1439 	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1440     } else {
1441 	*key = &crypto->key;
1442     }
1443     if(ret == 0)
1444 	ret = _key_schedule(context, *key);
1445     return ret;
1446 }
1447 
1448 static krb5_error_code
1449 do_checksum (krb5_context context,
1450 	     struct checksum_type *ct,
1451 	     krb5_crypto crypto,
1452 	     unsigned usage,
1453 	     void *data,
1454 	     size_t len,
1455 	     Checksum *result)
1456 {
1457     krb5_error_code ret;
1458     struct key_data *dkey;
1459     int keyed_checksum;
1460 
1461     keyed_checksum = (ct->flags & F_KEYED) != 0;
1462     if(keyed_checksum && crypto == NULL) {
1463 	krb5_clear_error_string (context);
1464 	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1465     }
1466     if(keyed_checksum) {
1467 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1468 	if (ret)
1469 	    return ret;
1470     } else
1471 	dkey = NULL;
1472     result->cksumtype = ct->type;
1473     krb5_data_alloc(&result->checksum, ct->checksumsize);
1474     (*ct->checksum)(context, dkey, data, len, usage, result);
1475     return 0;
1476 }
1477 
1478 static krb5_error_code
1479 create_checksum(krb5_context context,
1480 		krb5_crypto crypto,
1481 		unsigned usage, /* not krb5_key_usage */
1482 		krb5_cksumtype type, /* 0 -> pick from crypto */
1483 		void *data,
1484 		size_t len,
1485 		Checksum *result)
1486 {
1487     struct checksum_type *ct = NULL;
1488 
1489     if (type) {
1490 	ct = _find_checksum(type);
1491     } else if (crypto) {
1492 	ct = crypto->et->keyed_checksum;
1493 	if (ct == NULL)
1494 	    ct = crypto->et->checksum;
1495     }
1496 
1497     if(ct == NULL) {
1498 	krb5_set_error_string (context, "checksum type %d not supported",
1499 			       type);
1500 	return KRB5_PROG_SUMTYPE_NOSUPP;
1501     }
1502     return do_checksum (context, ct, crypto, usage, data, len, result);
1503 }
1504 
1505 krb5_error_code
1506 krb5_create_checksum(krb5_context context,
1507 		     krb5_crypto crypto,
1508 		     krb5_key_usage usage,
1509 		     int type,
1510 		     void *data,
1511 		     size_t len,
1512 		     Checksum *result)
1513 {
1514     return create_checksum(context, crypto,
1515 			   CHECKSUM_USAGE(usage),
1516 			   type, data, len, result);
1517 }
1518 
1519 static krb5_error_code
1520 verify_checksum(krb5_context context,
1521 		krb5_crypto crypto,
1522 		unsigned usage, /* not krb5_key_usage */
1523 		void *data,
1524 		size_t len,
1525 		Checksum *cksum)
1526 {
1527     krb5_error_code ret;
1528     struct key_data *dkey;
1529     int keyed_checksum;
1530     Checksum c;
1531     struct checksum_type *ct;
1532 
1533     ct = _find_checksum(cksum->cksumtype);
1534     if(ct == NULL) {
1535 	krb5_set_error_string (context, "checksum type %d not supported",
1536 			       cksum->cksumtype);
1537 	return KRB5_PROG_SUMTYPE_NOSUPP;
1538     }
1539     if(ct->checksumsize != cksum->checksum.length) {
1540 	krb5_clear_error_string (context);
1541 	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1542     }
1543     keyed_checksum = (ct->flags & F_KEYED) != 0;
1544     if(keyed_checksum && crypto == NULL) {
1545 	krb5_clear_error_string (context);
1546 	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1547     }
1548     if(keyed_checksum)
1549 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1550     else
1551 	dkey = NULL;
1552     if(ct->verify)
1553 	return (*ct->verify)(context, dkey, data, len, usage, cksum);
1554 
1555     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1556     if (ret)
1557 	return ret;
1558 
1559     (*ct->checksum)(context, dkey, data, len, usage, &c);
1560 
1561     if(c.checksum.length != cksum->checksum.length ||
1562        memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1563 	krb5_clear_error_string (context);
1564 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1565     } else {
1566 	ret = 0;
1567     }
1568     krb5_data_free (&c.checksum);
1569     return ret;
1570 }
1571 
1572 krb5_error_code
1573 krb5_verify_checksum(krb5_context context,
1574 		     krb5_crypto crypto,
1575 		     krb5_key_usage usage,
1576 		     void *data,
1577 		     size_t len,
1578 		     Checksum *cksum)
1579 {
1580     return verify_checksum(context, crypto,
1581 			   CHECKSUM_USAGE(usage), data, len, cksum);
1582 }
1583 
1584 krb5_error_code
1585 krb5_checksumsize(krb5_context context,
1586 		  krb5_cksumtype type,
1587 		  size_t *size)
1588 {
1589     struct checksum_type *ct = _find_checksum(type);
1590     if(ct == NULL) {
1591 	krb5_set_error_string (context, "checksum type %d not supported",
1592 			       type);
1593 	return KRB5_PROG_SUMTYPE_NOSUPP;
1594     }
1595     *size = ct->checksumsize;
1596     return 0;
1597 }
1598 
1599 krb5_boolean
1600 krb5_checksum_is_keyed(krb5_context context,
1601 		       krb5_cksumtype type)
1602 {
1603     struct checksum_type *ct = _find_checksum(type);
1604     if(ct == NULL) {
1605 	krb5_set_error_string (context, "checksum type %d not supported",
1606 			       type);
1607 	return KRB5_PROG_SUMTYPE_NOSUPP;
1608     }
1609     return ct->flags & F_KEYED;
1610 }
1611 
1612 krb5_boolean
1613 krb5_checksum_is_collision_proof(krb5_context context,
1614 				 krb5_cksumtype type)
1615 {
1616     struct checksum_type *ct = _find_checksum(type);
1617     if(ct == NULL) {
1618 	krb5_set_error_string (context, "checksum type %d not supported",
1619 			       type);
1620 	return KRB5_PROG_SUMTYPE_NOSUPP;
1621     }
1622     return ct->flags & F_CPROOF;
1623 }
1624 
1625 /************************************************************
1626  *                                                          *
1627  ************************************************************/
1628 
1629 static krb5_error_code
1630 NULL_encrypt(krb5_context context,
1631 	     struct key_data *key,
1632 	     void *data,
1633 	     size_t len,
1634 	     krb5_boolean encrypt,
1635 	     int usage,
1636 	     void *ivec)
1637 {
1638     return 0;
1639 }
1640 
1641 static krb5_error_code
1642 DES_CBC_encrypt_null_ivec(krb5_context context,
1643 			  struct key_data *key,
1644 			  void *data,
1645 			  size_t len,
1646 			  krb5_boolean encrypt,
1647 			  int usage,
1648 			  void *ignore_ivec)
1649 {
1650     des_cblock ivec;
1651     des_key_schedule *s = key->schedule->data;
1652     memset(&ivec, 0, sizeof(ivec));
1653     des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1654     return 0;
1655 }
1656 
1657 static krb5_error_code
1658 DES_CBC_encrypt_key_ivec(krb5_context context,
1659 			 struct key_data *key,
1660 			 void *data,
1661 			 size_t len,
1662 			 krb5_boolean encrypt,
1663 			 int usage,
1664 			 void *ignore_ivec)
1665 {
1666     des_cblock ivec;
1667     des_key_schedule *s = key->schedule->data;
1668     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1669     des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1670     return 0;
1671 }
1672 
1673 static krb5_error_code
1674 DES3_CBC_encrypt(krb5_context context,
1675 		 struct key_data *key,
1676 		 void *data,
1677 		 size_t len,
1678 		 krb5_boolean encrypt,
1679 		 int usage,
1680 		 void *ivec)
1681 {
1682     des_cblock local_ivec;
1683     des_key_schedule *s = key->schedule->data;
1684     if(ivec == NULL) {
1685 	ivec = &local_ivec;
1686 	memset(local_ivec, 0, sizeof(local_ivec));
1687     }
1688     des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt);
1689     return 0;
1690 }
1691 
1692 static krb5_error_code
1693 DES_CFB64_encrypt_null_ivec(krb5_context context,
1694 			    struct key_data *key,
1695 			    void *data,
1696 			    size_t len,
1697 			    krb5_boolean encrypt,
1698 			    int usage,
1699 			    void *ignore_ivec)
1700 {
1701     des_cblock ivec;
1702     int num = 0;
1703     des_key_schedule *s = key->schedule->data;
1704     memset(&ivec, 0, sizeof(ivec));
1705 
1706     des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
1707     return 0;
1708 }
1709 
1710 static krb5_error_code
1711 DES_PCBC_encrypt_key_ivec(krb5_context context,
1712 			  struct key_data *key,
1713 			  void *data,
1714 			  size_t len,
1715 			  krb5_boolean encrypt,
1716 			  int usage,
1717 			  void *ignore_ivec)
1718 {
1719     des_cblock ivec;
1720     des_key_schedule *s = key->schedule->data;
1721     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1722 
1723     des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
1724     return 0;
1725 }
1726 
1727 /*
1728  * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
1729  *
1730  * warning: not for small children
1731  */
1732 
1733 static krb5_error_code
1734 ARCFOUR_subencrypt(krb5_context context,
1735 		   struct key_data *key,
1736 		   void *data,
1737 		   size_t len,
1738 		   int usage,
1739 		   void *ivec)
1740 {
1741     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1742     Checksum k1_c, k2_c, k3_c, cksum;
1743     struct key_data ke;
1744     krb5_keyblock kb;
1745     unsigned char t[4];
1746     RC4_KEY rc4_key;
1747     unsigned char *cdata = data;
1748     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1749 
1750     t[0] = (usage >>  0) & 0xFF;
1751     t[1] = (usage >>  8) & 0xFF;
1752     t[2] = (usage >> 16) & 0xFF;
1753     t[3] = (usage >> 24) & 0xFF;
1754 
1755     k1_c.checksum.length = sizeof(k1_c_data);
1756     k1_c.checksum.data   = k1_c_data;
1757 
1758     hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1759 
1760     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1761 
1762     k2_c.checksum.length = sizeof(k2_c_data);
1763     k2_c.checksum.data   = k2_c_data;
1764 
1765     ke.key = &kb;
1766     kb.keyvalue = k2_c.checksum;
1767 
1768     cksum.checksum.length = 16;
1769     cksum.checksum.data   = data;
1770 
1771     hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1772 
1773     ke.key = &kb;
1774     kb.keyvalue = k1_c.checksum;
1775 
1776     k3_c.checksum.length = sizeof(k3_c_data);
1777     k3_c.checksum.data   = k3_c_data;
1778 
1779     hmac(NULL, c, data, 16, 0, &ke, &k3_c);
1780 
1781     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1782     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1783     memset (k1_c_data, 0, sizeof(k1_c_data));
1784     memset (k2_c_data, 0, sizeof(k2_c_data));
1785     memset (k3_c_data, 0, sizeof(k3_c_data));
1786     return 0;
1787 }
1788 
1789 static krb5_error_code
1790 ARCFOUR_subdecrypt(krb5_context context,
1791 		   struct key_data *key,
1792 		   void *data,
1793 		   size_t len,
1794 		   int usage,
1795 		   void *ivec)
1796 {
1797     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1798     Checksum k1_c, k2_c, k3_c, cksum;
1799     struct key_data ke;
1800     krb5_keyblock kb;
1801     unsigned char t[4];
1802     RC4_KEY rc4_key;
1803     unsigned char *cdata = data;
1804     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1805     unsigned char cksum_data[16];
1806 
1807     t[0] = (usage >>  0) & 0xFF;
1808     t[1] = (usage >>  8) & 0xFF;
1809     t[2] = (usage >> 16) & 0xFF;
1810     t[3] = (usage >> 24) & 0xFF;
1811 
1812     k1_c.checksum.length = sizeof(k1_c_data);
1813     k1_c.checksum.data   = k1_c_data;
1814 
1815     hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1816 
1817     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1818 
1819     k2_c.checksum.length = sizeof(k2_c_data);
1820     k2_c.checksum.data   = k2_c_data;
1821 
1822     ke.key = &kb;
1823     kb.keyvalue = k1_c.checksum;
1824 
1825     k3_c.checksum.length = sizeof(k3_c_data);
1826     k3_c.checksum.data   = k3_c_data;
1827 
1828     hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
1829 
1830     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1831     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1832 
1833     ke.key = &kb;
1834     kb.keyvalue = k2_c.checksum;
1835 
1836     cksum.checksum.length = 16;
1837     cksum.checksum.data   = cksum_data;
1838 
1839     hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1840 
1841     memset (k1_c_data, 0, sizeof(k1_c_data));
1842     memset (k2_c_data, 0, sizeof(k2_c_data));
1843     memset (k3_c_data, 0, sizeof(k3_c_data));
1844 
1845     if (memcmp (cksum.checksum.data, data, 16) != 0) {
1846 	krb5_clear_error_string (context);
1847 	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
1848     } else {
1849 	return 0;
1850     }
1851 }
1852 
1853 /*
1854  * convert the usage numbers used in
1855  * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
1856  * draft-brezak-win2k-krb-rc4-hmac-03.txt
1857  */
1858 
1859 static krb5_error_code
1860 usage2arcfour (krb5_context context, int *usage)
1861 {
1862     switch (*usage) {
1863     case KRB5_KU_PA_ENC_TIMESTAMP :
1864 	*usage = 1;
1865 	return 0;
1866     case KRB5_KU_TICKET :
1867 	*usage = 8;
1868     case KRB5_KU_AS_REP_ENC_PART :
1869 	*usage = 8;
1870 	return 0;
1871     case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
1872     case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
1873     case KRB5_KU_TGS_REQ_AUTH_CKSUM :
1874     case KRB5_KU_TGS_REQ_AUTH :
1875 	*usage = 7;
1876 	return 0;
1877     case KRB5_KU_TGS_REP_ENC_PART_SESSION :
1878     case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1879 	*usage = 8;
1880 	return 0;
1881     case KRB5_KU_AP_REQ_AUTH_CKSUM :
1882     case KRB5_KU_AP_REQ_AUTH :
1883     case KRB5_KU_AP_REQ_ENC_PART :
1884 	*usage = 11;
1885 	return 0;
1886     case KRB5_KU_KRB_PRIV :
1887 	*usage = 0;
1888 	return 0;
1889     case KRB5_KU_KRB_CRED :
1890     case KRB5_KU_KRB_SAFE_CKSUM :
1891     case KRB5_KU_OTHER_ENCRYPTED :
1892     case KRB5_KU_OTHER_CKSUM :
1893     case KRB5_KU_KRB_ERROR :
1894     case KRB5_KU_AD_KDC_ISSUED :
1895     case KRB5_KU_MANDATORY_TICKET_EXTENSION :
1896     case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
1897     case KRB5_KU_USAGE_SEAL :
1898     case KRB5_KU_USAGE_SIGN :
1899     case KRB5_KU_USAGE_SEQ :
1900     default :
1901 	krb5_set_error_string(context, "unknown arcfour usage type %d", *usage);
1902 	return KRB5_PROG_ETYPE_NOSUPP;
1903     }
1904 }
1905 
1906 static krb5_error_code
1907 ARCFOUR_encrypt(krb5_context context,
1908 		struct key_data *key,
1909 		void *data,
1910 		size_t len,
1911 		krb5_boolean encrypt,
1912 		int usage,
1913 		void *ivec)
1914 {
1915     krb5_error_code ret;
1916     if((ret = usage2arcfour (context, &usage)) != 0)
1917 	return ret;
1918 
1919     if (encrypt)
1920 	return ARCFOUR_subencrypt (context, key, data, len, usage, ivec);
1921     else
1922 	return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec);
1923 }
1924 
1925 
1926 /*
1927  * these should currently be in reverse preference order.
1928  * (only relevant for !F_PSEUDO) */
1929 
1930 static struct encryption_type enctype_null = {
1931     ETYPE_NULL,
1932     "null",
1933     1,
1934     0,
1935     &keytype_null,
1936     &checksum_none,
1937     NULL,
1938     0,
1939     NULL_encrypt,
1940 };
1941 static struct encryption_type enctype_des_cbc_crc = {
1942     ETYPE_DES_CBC_CRC,
1943     "des-cbc-crc",
1944     8,
1945     8,
1946     &keytype_des,
1947     &checksum_crc32,
1948     NULL,
1949     0,
1950     DES_CBC_encrypt_key_ivec,
1951 };
1952 static struct encryption_type enctype_des_cbc_md4 = {
1953     ETYPE_DES_CBC_MD4,
1954     "des-cbc-md4",
1955     8,
1956     8,
1957     &keytype_des,
1958     &checksum_rsa_md4,
1959     &checksum_rsa_md4_des,
1960     0,
1961     DES_CBC_encrypt_null_ivec,
1962 };
1963 static struct encryption_type enctype_des_cbc_md5 = {
1964     ETYPE_DES_CBC_MD5,
1965     "des-cbc-md5",
1966     8,
1967     8,
1968     &keytype_des,
1969     &checksum_rsa_md5,
1970     &checksum_rsa_md5_des,
1971     0,
1972     DES_CBC_encrypt_null_ivec,
1973 };
1974 static struct encryption_type enctype_arcfour_hmac_md5 = {
1975     ETYPE_ARCFOUR_HMAC_MD5,
1976     "arcfour-hmac-md5",
1977     1,
1978     8,
1979     &keytype_arcfour,
1980     &checksum_hmac_md5,
1981     &checksum_hmac_md5_enc,
1982     F_SPECIAL,
1983     ARCFOUR_encrypt
1984 };
1985 static struct encryption_type enctype_des3_cbc_md5 = {
1986     ETYPE_DES3_CBC_MD5,
1987     "des3-cbc-md5",
1988     8,
1989     8,
1990     &keytype_des3,
1991     &checksum_rsa_md5,
1992     &checksum_rsa_md5_des3,
1993     0,
1994     DES3_CBC_encrypt,
1995 };
1996 static struct encryption_type enctype_des3_cbc_sha1 = {
1997     ETYPE_DES3_CBC_SHA1,
1998     "des3-cbc-sha1",
1999     8,
2000     8,
2001     &keytype_des3_derived,
2002     &checksum_sha1,
2003     &checksum_hmac_sha1_des3,
2004     F_DERIVED,
2005     DES3_CBC_encrypt,
2006 };
2007 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2008     ETYPE_OLD_DES3_CBC_SHA1,
2009     "old-des3-cbc-sha1",
2010     8,
2011     8,
2012     &keytype_des3,
2013     &checksum_sha1,
2014     &checksum_hmac_sha1_des3,
2015     0,
2016     DES3_CBC_encrypt,
2017 };
2018 static struct encryption_type enctype_des_cbc_none = {
2019     ETYPE_DES_CBC_NONE,
2020     "des-cbc-none",
2021     8,
2022     0,
2023     &keytype_des,
2024     &checksum_none,
2025     NULL,
2026     F_PSEUDO,
2027     DES_CBC_encrypt_null_ivec,
2028 };
2029 static struct encryption_type enctype_des_cfb64_none = {
2030     ETYPE_DES_CFB64_NONE,
2031     "des-cfb64-none",
2032     1,
2033     0,
2034     &keytype_des,
2035     &checksum_none,
2036     NULL,
2037     F_PSEUDO,
2038     DES_CFB64_encrypt_null_ivec,
2039 };
2040 static struct encryption_type enctype_des_pcbc_none = {
2041     ETYPE_DES_PCBC_NONE,
2042     "des-pcbc-none",
2043     8,
2044     0,
2045     &keytype_des,
2046     &checksum_none,
2047     NULL,
2048     F_PSEUDO,
2049     DES_PCBC_encrypt_key_ivec,
2050 };
2051 static struct encryption_type enctype_des3_cbc_none = {
2052     ETYPE_DES3_CBC_NONE,
2053     "des3-cbc-none",
2054     8,
2055     0,
2056     &keytype_des3_derived,
2057     &checksum_none,
2058     NULL,
2059     F_PSEUDO,
2060     DES3_CBC_encrypt,
2061 };
2062 
2063 static struct encryption_type *etypes[] = {
2064     &enctype_null,
2065     &enctype_des_cbc_crc,
2066     &enctype_des_cbc_md4,
2067     &enctype_des_cbc_md5,
2068     &enctype_arcfour_hmac_md5,
2069     &enctype_des3_cbc_md5,
2070     &enctype_des3_cbc_sha1,
2071     &enctype_old_des3_cbc_sha1,
2072     &enctype_des_cbc_none,
2073     &enctype_des_cfb64_none,
2074     &enctype_des_pcbc_none,
2075     &enctype_des3_cbc_none
2076 };
2077 
2078 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2079 
2080 
2081 static struct encryption_type *
2082 _find_enctype(krb5_enctype type)
2083 {
2084     int i;
2085     for(i = 0; i < num_etypes; i++)
2086 	if(etypes[i]->type == type)
2087 	    return etypes[i];
2088     return NULL;
2089 }
2090 
2091 
2092 krb5_error_code
2093 krb5_enctype_to_string(krb5_context context,
2094 		       krb5_enctype etype,
2095 		       char **string)
2096 {
2097     struct encryption_type *e;
2098     e = _find_enctype(etype);
2099     if(e == NULL) {
2100 	krb5_set_error_string (context, "encryption type %d not supported",
2101 			       etype);
2102 	return KRB5_PROG_ETYPE_NOSUPP;
2103     }
2104     *string = strdup(e->name);
2105     if(*string == NULL) {
2106 	krb5_set_error_string(context, "malloc: out of memory");
2107 	return ENOMEM;
2108     }
2109     return 0;
2110 }
2111 
2112 krb5_error_code
2113 krb5_string_to_enctype(krb5_context context,
2114 		       const char *string,
2115 		       krb5_enctype *etype)
2116 {
2117     int i;
2118     for(i = 0; i < num_etypes; i++)
2119 	if(strcasecmp(etypes[i]->name, string) == 0){
2120 	    *etype = etypes[i]->type;
2121 	    return 0;
2122 	}
2123     krb5_set_error_string (context, "encryption type %s not supported",
2124 			   string);
2125     return KRB5_PROG_ETYPE_NOSUPP;
2126 }
2127 
2128 krb5_error_code
2129 krb5_enctype_to_keytype(krb5_context context,
2130 			krb5_enctype etype,
2131 			krb5_keytype *keytype)
2132 {
2133     struct encryption_type *e = _find_enctype(etype);
2134     if(e == NULL) {
2135 	krb5_set_error_string (context, "encryption type %d not supported",
2136 			       etype);
2137 	return KRB5_PROG_ETYPE_NOSUPP;
2138     }
2139     *keytype = e->keytype->type; /* XXX */
2140     return 0;
2141 }
2142 
2143 #if 0
2144 krb5_error_code
2145 krb5_keytype_to_enctype(krb5_context context,
2146 			krb5_keytype keytype,
2147 			krb5_enctype *etype)
2148 {
2149     struct key_type *kt = _find_keytype(keytype);
2150     krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
2151     if(kt == NULL)
2152 	return KRB5_PROG_KEYTYPE_NOSUPP;
2153     *etype = kt->best_etype;
2154     return 0;
2155 }
2156 #endif
2157 
2158 krb5_error_code
2159 krb5_keytype_to_enctypes (krb5_context context,
2160 			  krb5_keytype keytype,
2161 			  unsigned *len,
2162 			  krb5_enctype **val)
2163 {
2164     int i;
2165     unsigned n = 0;
2166     krb5_enctype *ret;
2167 
2168     for (i = num_etypes - 1; i >= 0; --i) {
2169 	if (etypes[i]->keytype->type == keytype
2170 	    && !(etypes[i]->flags & F_PSEUDO))
2171 	    ++n;
2172     }
2173     ret = malloc(n * sizeof(*ret));
2174     if (ret == NULL && n != 0) {
2175 	krb5_set_error_string(context, "malloc: out of memory");
2176 	return ENOMEM;
2177     }
2178     n = 0;
2179     for (i = num_etypes - 1; i >= 0; --i) {
2180 	if (etypes[i]->keytype->type == keytype
2181 	    && !(etypes[i]->flags & F_PSEUDO))
2182 	    ret[n++] = etypes[i]->type;
2183     }
2184     *len = n;
2185     *val = ret;
2186     return 0;
2187 }
2188 
2189 /*
2190  * First take the configured list of etypes for `keytype' if available,
2191  * else, do `krb5_keytype_to_enctypes'.
2192  */
2193 
2194 krb5_error_code
2195 krb5_keytype_to_enctypes_default (krb5_context context,
2196 				  krb5_keytype keytype,
2197 				  unsigned *len,
2198 				  krb5_enctype **val)
2199 {
2200     int i, n;
2201     krb5_enctype *ret;
2202 
2203     if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
2204 	return krb5_keytype_to_enctypes (context, keytype, len, val);
2205 
2206     for (n = 0; context->etypes_des[n]; ++n)
2207 	;
2208     ret = malloc (n * sizeof(*ret));
2209     if (ret == NULL && n != 0) {
2210 	krb5_set_error_string(context, "malloc: out of memory");
2211 	return ENOMEM;
2212     }
2213     for (i = 0; i < n; ++i)
2214 	ret[i] = context->etypes_des[i];
2215     *len = n;
2216     *val = ret;
2217     return 0;
2218 }
2219 
2220 krb5_error_code
2221 krb5_enctype_valid(krb5_context context,
2222 		 krb5_enctype etype)
2223 {
2224     return _find_enctype(etype) != NULL;
2225 }
2226 
2227 /* if two enctypes have compatible keys */
2228 krb5_boolean
2229 krb5_enctypes_compatible_keys(krb5_context context,
2230 			      krb5_enctype etype1,
2231 			      krb5_enctype etype2)
2232 {
2233     struct encryption_type *e1 = _find_enctype(etype1);
2234     struct encryption_type *e2 = _find_enctype(etype2);
2235     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2236 }
2237 
2238 static krb5_boolean
2239 derived_crypto(krb5_context context,
2240 	       krb5_crypto crypto)
2241 {
2242     return (crypto->et->flags & F_DERIVED) != 0;
2243 }
2244 
2245 static krb5_boolean
2246 special_crypto(krb5_context context,
2247 	       krb5_crypto crypto)
2248 {
2249     return (crypto->et->flags & F_SPECIAL) != 0;
2250 }
2251 
2252 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2253 #define CHECKSUMTYPE(C) ((C)->type)
2254 
2255 static krb5_error_code
2256 encrypt_internal_derived(krb5_context context,
2257 			 krb5_crypto crypto,
2258 			 unsigned usage,
2259 			 void *data,
2260 			 size_t len,
2261 			 krb5_data *result,
2262 			 void *ivec)
2263 {
2264     size_t sz, block_sz, checksum_sz, total_sz;
2265     Checksum cksum;
2266     unsigned char *p, *q;
2267     krb5_error_code ret;
2268     struct key_data *dkey;
2269     const struct encryption_type *et = crypto->et;
2270 
2271     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2272 
2273     sz = et->confoundersize + len;
2274     block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2275     total_sz = block_sz + checksum_sz;
2276     p = calloc(1, total_sz);
2277     if(p == NULL) {
2278 	krb5_set_error_string(context, "malloc: out of memory");
2279 	return ENOMEM;
2280     }
2281 
2282     q = p;
2283     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2284     q += et->confoundersize;
2285     memcpy(q, data, len);
2286 
2287     ret = create_checksum(context,
2288 			  crypto,
2289 			  INTEGRITY_USAGE(usage),
2290 			  et->keyed_checksum->type,
2291 			  p,
2292 			  block_sz,
2293 			  &cksum);
2294     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2295 	free_Checksum (&cksum);
2296 	krb5_clear_error_string (context);
2297 	ret = KRB5_CRYPTO_INTERNAL;
2298     }
2299     if(ret)
2300 	goto fail;
2301     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2302     free_Checksum (&cksum);
2303     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2304     if(ret)
2305 	goto fail;
2306     ret = _key_schedule(context, dkey);
2307     if(ret)
2308 	goto fail;
2309 #ifdef CRYPTO_DEBUG
2310     krb5_crypto_debug(context, 1, block_sz, dkey->key);
2311 #endif
2312     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2313     if (ret)
2314 	goto fail;
2315     result->data = p;
2316     result->length = total_sz;
2317     return 0;
2318  fail:
2319     memset(p, 0, total_sz);
2320     free(p);
2321     return ret;
2322 }
2323 
2324 
2325 static krb5_error_code
2326 encrypt_internal(krb5_context context,
2327 		 krb5_crypto crypto,
2328 		 void *data,
2329 		 size_t len,
2330 		 krb5_data *result,
2331 		 void *ivec)
2332 {
2333     size_t sz, block_sz, checksum_sz;
2334     Checksum cksum;
2335     unsigned char *p, *q;
2336     krb5_error_code ret;
2337     const struct encryption_type *et = crypto->et;
2338 
2339     checksum_sz = CHECKSUMSIZE(et->checksum);
2340 
2341     sz = et->confoundersize + checksum_sz + len;
2342     block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2343     p = calloc(1, block_sz);
2344     if(p == NULL) {
2345 	krb5_set_error_string(context, "malloc: out of memory");
2346 	return ENOMEM;
2347     }
2348 
2349     q = p;
2350     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2351     q += et->confoundersize;
2352     memset(q, 0, checksum_sz);
2353     q += checksum_sz;
2354     memcpy(q, data, len);
2355 
2356     ret = create_checksum(context,
2357 			  crypto,
2358 			  0,
2359 			  et->checksum->type,
2360 			  p,
2361 			  block_sz,
2362 			  &cksum);
2363     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2364 	krb5_clear_error_string (context);
2365 	free_Checksum(&cksum);
2366 	ret = KRB5_CRYPTO_INTERNAL;
2367     }
2368     if(ret)
2369 	goto fail;
2370     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2371     free_Checksum(&cksum);
2372     ret = _key_schedule(context, &crypto->key);
2373     if(ret)
2374 	goto fail;
2375 #ifdef CRYPTO_DEBUG
2376     krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
2377 #endif
2378     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2379     if (ret) {
2380 	memset(p, 0, block_sz);
2381 	free(p);
2382 	return ret;
2383     }
2384     result->data = p;
2385     result->length = block_sz;
2386     return 0;
2387  fail:
2388     memset(p, 0, block_sz);
2389     free(p);
2390     return ret;
2391 }
2392 
2393 static krb5_error_code
2394 encrypt_internal_special(krb5_context context,
2395 			 krb5_crypto crypto,
2396 			 int usage,
2397 			 void *data,
2398 			 size_t len,
2399 			 krb5_data *result,
2400 			 void *ivec)
2401 {
2402     struct encryption_type *et = crypto->et;
2403     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2404     size_t sz = len + cksum_sz + et->confoundersize;
2405     char *tmp, *p;
2406     krb5_error_code ret;
2407 
2408     tmp = malloc (sz);
2409     if (tmp == NULL) {
2410 	krb5_set_error_string(context, "malloc: out of memory");
2411 	return ENOMEM;
2412     }
2413     p = tmp;
2414     memset (p, 0, cksum_sz);
2415     p += cksum_sz;
2416     krb5_generate_random_block(p, et->confoundersize);
2417     p += et->confoundersize;
2418     memcpy (p, data, len);
2419     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2420     if (ret) {
2421 	memset(tmp, 0, sz);
2422 	free(tmp);
2423 	return ret;
2424     }
2425     result->data   = tmp;
2426     result->length = sz;
2427     return 0;
2428 }
2429 
2430 static krb5_error_code
2431 decrypt_internal_derived(krb5_context context,
2432 			 krb5_crypto crypto,
2433 			 unsigned usage,
2434 			 void *data,
2435 			 size_t len,
2436 			 krb5_data *result,
2437 			 void *ivec)
2438 {
2439     size_t checksum_sz;
2440     Checksum cksum;
2441     unsigned char *p;
2442     krb5_error_code ret;
2443     struct key_data *dkey;
2444     struct encryption_type *et = crypto->et;
2445     unsigned long l;
2446 
2447     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2448     if (len < checksum_sz) {
2449 	krb5_clear_error_string (context);
2450 	return EINVAL;		/* XXX - better error code? */
2451     }
2452 
2453     p = malloc(len);
2454     if(len != 0 && p == NULL) {
2455 	krb5_set_error_string(context, "malloc: out of memory");
2456 	return ENOMEM;
2457     }
2458     memcpy(p, data, len);
2459 
2460     len -= checksum_sz;
2461 
2462     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2463     if(ret) {
2464 	free(p);
2465 	return ret;
2466     }
2467     ret = _key_schedule(context, dkey);
2468     if(ret) {
2469 	free(p);
2470 	return ret;
2471     }
2472 #ifdef CRYPTO_DEBUG
2473     krb5_crypto_debug(context, 0, len, dkey->key);
2474 #endif
2475     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
2476     if (ret) {
2477 	free(p);
2478 	return ret;
2479     }
2480 
2481     cksum.checksum.data   = p + len;
2482     cksum.checksum.length = checksum_sz;
2483     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
2484 
2485     ret = verify_checksum(context,
2486 			  crypto,
2487 			  INTEGRITY_USAGE(usage),
2488 			  p,
2489 			  len,
2490 			  &cksum);
2491     if(ret) {
2492 	free(p);
2493 	return ret;
2494     }
2495     l = len - et->confoundersize;
2496     memmove(p, p + et->confoundersize, l);
2497     result->data = realloc(p, l);
2498     if(result->data == NULL) {
2499 	free(p);
2500 	krb5_set_error_string(context, "malloc: out of memory");
2501 	return ENOMEM;
2502     }
2503     result->length = l;
2504     return 0;
2505 }
2506 
2507 static krb5_error_code
2508 decrypt_internal(krb5_context context,
2509 		 krb5_crypto crypto,
2510 		 void *data,
2511 		 size_t len,
2512 		 krb5_data *result,
2513 		 void *ivec)
2514 {
2515     krb5_error_code ret;
2516     unsigned char *p;
2517     Checksum cksum;
2518     size_t checksum_sz, l;
2519     struct encryption_type *et = crypto->et;
2520 
2521     checksum_sz = CHECKSUMSIZE(et->checksum);
2522     p = malloc(len);
2523     if(len != 0 && p == NULL) {
2524 	krb5_set_error_string(context, "malloc: out of memory");
2525 	return ENOMEM;
2526     }
2527     memcpy(p, data, len);
2528 
2529     ret = _key_schedule(context, &crypto->key);
2530     if(ret) {
2531 	free(p);
2532 	return ret;
2533     }
2534 #ifdef CRYPTO_DEBUG
2535     krb5_crypto_debug(context, 0, len, crypto->key.key);
2536 #endif
2537     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
2538     if (ret) {
2539 	free(p);
2540 	return ret;
2541     }
2542     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
2543     if(ret) {
2544  	free(p);
2545  	return ret;
2546     }
2547     memset(p + et->confoundersize, 0, checksum_sz);
2548     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
2549     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
2550     free_Checksum(&cksum);
2551     if(ret) {
2552 	free(p);
2553 	return ret;
2554     }
2555     l = len - et->confoundersize - checksum_sz;
2556     memmove(p, p + et->confoundersize + checksum_sz, l);
2557     result->data = realloc(p, l);
2558     if(result->data == NULL) {
2559 	free(p);
2560 	krb5_set_error_string(context, "malloc: out of memory");
2561 	return ENOMEM;
2562     }
2563     result->length = l;
2564     return 0;
2565 }
2566 
2567 static krb5_error_code
2568 decrypt_internal_special(krb5_context context,
2569 			 krb5_crypto crypto,
2570 			 int usage,
2571 			 void *data,
2572 			 size_t len,
2573 			 krb5_data *result,
2574 			 void *ivec)
2575 {
2576     struct encryption_type *et = crypto->et;
2577     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2578     size_t sz = len - cksum_sz - et->confoundersize;
2579     char *cdata = (char *)data;
2580     char *tmp;
2581     krb5_error_code ret;
2582 
2583     tmp = malloc (sz);
2584     if (tmp == NULL) {
2585 	krb5_set_error_string(context, "malloc: out of memory");
2586 	return ENOMEM;
2587     }
2588 
2589     ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
2590     if (ret) {
2591 	free(tmp);
2592 	return ret;
2593     }
2594 
2595     memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
2596 
2597     result->data   = tmp;
2598     result->length = sz;
2599     return 0;
2600 }
2601 
2602 
2603 krb5_error_code
2604 krb5_encrypt_ivec(krb5_context context,
2605 		  krb5_crypto crypto,
2606 		  unsigned usage,
2607 		  void *data,
2608 		  size_t len,
2609 		  krb5_data *result,
2610 		  void *ivec)
2611 {
2612     if(derived_crypto(context, crypto))
2613 	return encrypt_internal_derived(context, crypto, usage,
2614 					data, len, result, ivec);
2615     else if (special_crypto(context, crypto))
2616 	return encrypt_internal_special (context, crypto, usage,
2617 					 data, len, result, ivec);
2618     else
2619 	return encrypt_internal(context, crypto, data, len, result, ivec);
2620 }
2621 
2622 krb5_error_code
2623 krb5_encrypt(krb5_context context,
2624 	     krb5_crypto crypto,
2625 	     unsigned usage,
2626 	     void *data,
2627 	     size_t len,
2628 	     krb5_data *result)
2629 {
2630     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
2631 }
2632 
2633 krb5_error_code
2634 krb5_encrypt_EncryptedData(krb5_context context,
2635 			   krb5_crypto crypto,
2636 			   unsigned usage,
2637 			   void *data,
2638 			   size_t len,
2639 			   int kvno,
2640 			   EncryptedData *result)
2641 {
2642     result->etype = CRYPTO_ETYPE(crypto);
2643     if(kvno){
2644 	ALLOC(result->kvno, 1);
2645 	*result->kvno = kvno;
2646     }else
2647 	result->kvno = NULL;
2648     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
2649 }
2650 
2651 krb5_error_code
2652 krb5_decrypt_ivec(krb5_context context,
2653 		  krb5_crypto crypto,
2654 		  unsigned usage,
2655 		  void *data,
2656 		  size_t len,
2657 		  krb5_data *result,
2658 		  void *ivec)
2659 {
2660     if(derived_crypto(context, crypto))
2661 	return decrypt_internal_derived(context, crypto, usage,
2662 					data, len, result, ivec);
2663     else if (special_crypto (context, crypto))
2664 	return decrypt_internal_special(context, crypto, usage,
2665 					data, len, result, ivec);
2666     else
2667 	return decrypt_internal(context, crypto, data, len, result, ivec);
2668 }
2669 
2670 krb5_error_code
2671 krb5_decrypt(krb5_context context,
2672 	     krb5_crypto crypto,
2673 	     unsigned usage,
2674 	     void *data,
2675 	     size_t len,
2676 	     krb5_data *result)
2677 {
2678     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
2679 			      NULL);
2680 }
2681 
2682 krb5_error_code
2683 krb5_decrypt_EncryptedData(krb5_context context,
2684 			   krb5_crypto crypto,
2685 			   unsigned usage,
2686 			   const EncryptedData *e,
2687 			   krb5_data *result)
2688 {
2689     return krb5_decrypt(context, crypto, usage,
2690 			e->cipher.data, e->cipher.length, result);
2691 }
2692 
2693 /************************************************************
2694  *                                                          *
2695  ************************************************************/
2696 
2697 #ifdef HAVE_OPENSSL
2698 #include <openssl/rand.h>
2699 
2700 /* From openssl/crypto/rand/rand_lcl.h */
2701 #define ENTROPY_NEEDED 20
2702 static int
2703 seed_something(void)
2704 {
2705     int fd = -1;
2706     char buf[1024], seedfile[256];
2707 
2708     /* If there is a seed file, load it. But such a file cannot be trusted,
2709        so use 0 for the entropy estimate */
2710     if (RAND_file_name(seedfile, sizeof(seedfile))) {
2711 	fd = open(seedfile, O_RDONLY);
2712 	if (fd >= 0) {
2713 	    read(fd, buf, sizeof(buf));
2714 	    /* Use the full buffer anyway */
2715 	    RAND_add(buf, sizeof(buf), 0.0);
2716 	} else
2717 	    seedfile[0] = '\0';
2718     } else
2719 	seedfile[0] = '\0';
2720 
2721     /* Calling RAND_status() will try to use /dev/urandom if it exists so
2722        we do not have to deal with it. */
2723     if (RAND_status() != 1) {
2724 	krb5_context context;
2725 	const char *p;
2726 
2727 	/* Try using egd */
2728 	if (!krb5_init_context(&context)) {
2729 	    p = krb5_config_get_string(context, NULL, "libdefaults",
2730 		"egd_socket", NULL);
2731 	    if (p != NULL)
2732 		RAND_egd_bytes(p, ENTROPY_NEEDED);
2733 	    krb5_free_context(context);
2734 	}
2735     }
2736 
2737     if (RAND_status() == 1)	{
2738 	/* Update the seed file */
2739 	if (seedfile[0])
2740 	    RAND_write_file(seedfile);
2741 
2742 	return 0;
2743     } else
2744 	return -1;
2745 }
2746 
2747 void
2748 krb5_generate_random_block(void *buf, size_t len)
2749 {
2750     static int rng_initialized = 0;
2751 
2752     if (!rng_initialized) {
2753 	if (seed_something())
2754 	    krb5_abortx(NULL, "Fatal: could not seed the random number generator");
2755 
2756 	rng_initialized = 1;
2757     }
2758     RAND_bytes(buf, len);
2759 }
2760 
2761 #else
2762 
2763 void
2764 krb5_generate_random_block(void *buf, size_t len)
2765 {
2766     des_cblock key, out;
2767     static des_cblock counter;
2768     static des_key_schedule schedule;
2769     int i;
2770     static int initialized = 0;
2771 
2772     if(!initialized) {
2773 	des_new_random_key(&key);
2774 	des_set_key(&key, schedule);
2775 	memset(&key, 0, sizeof(key));
2776 	des_new_random_key(&counter);
2777     }
2778     while(len > 0) {
2779 	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
2780 	for(i = 7; i >=0; i--)
2781 	    if(counter[i]++)
2782 		break;
2783 	memcpy(buf, out, min(len, sizeof(out)));
2784 	len -= min(len, sizeof(out));
2785 	buf = (char*)buf + sizeof(out);
2786     }
2787 }
2788 #endif
2789 
2790 static void
2791 DES3_postproc(krb5_context context,
2792 	      unsigned char *k, size_t len, struct key_data *key)
2793 {
2794     unsigned char x[24];
2795     int i, j;
2796 
2797     memset(x, 0, sizeof(x));
2798     for (i = 0; i < 3; ++i) {
2799 	unsigned char foo;
2800 
2801 	for (j = 0; j < 7; ++j) {
2802 	    unsigned char b = k[7 * i + j];
2803 
2804 	    x[8 * i + j] = b;
2805 	}
2806 	foo = 0;
2807 	for (j = 6; j >= 0; --j) {
2808 	    foo |= k[7 * i + j] & 1;
2809 	    foo <<= 1;
2810 	}
2811 	x[8 * i + 7] = foo;
2812     }
2813     k = key->key->keyvalue.data;
2814     memcpy(k, x, 24);
2815     memset(x, 0, sizeof(x));
2816     if (key->schedule) {
2817 	krb5_free_data(context, key->schedule);
2818 	key->schedule = NULL;
2819     }
2820     des_set_odd_parity((des_cblock*)k);
2821     des_set_odd_parity((des_cblock*)(k + 8));
2822     des_set_odd_parity((des_cblock*)(k + 16));
2823 }
2824 
2825 static krb5_error_code
2826 derive_key(krb5_context context,
2827 	   struct encryption_type *et,
2828 	   struct key_data *key,
2829 	   const void *constant,
2830 	   size_t len)
2831 {
2832     unsigned char *k;
2833     unsigned int nblocks = 0, i;
2834     krb5_error_code ret = 0;
2835 
2836     struct key_type *kt = et->keytype;
2837     ret = _key_schedule(context, key);
2838     if(ret)
2839 	return ret;
2840     if(et->blocksize * 8 < kt->bits ||
2841        len != et->blocksize) {
2842 	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2843 	k = malloc(nblocks * et->blocksize);
2844 	if(k == NULL) {
2845 	    krb5_set_error_string(context, "malloc: out of memory");
2846 	    return ENOMEM;
2847 	}
2848 	_krb5_n_fold(constant, len, k, et->blocksize);
2849 	for(i = 0; i < nblocks; i++) {
2850 	    if(i > 0)
2851 		memcpy(k + i * et->blocksize,
2852 		       k + (i - 1) * et->blocksize,
2853 		       et->blocksize);
2854 	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
2855 			   1, 0, NULL);
2856 	}
2857     } else {
2858 	/* this case is probably broken, but won't be run anyway */
2859 	void *c = malloc(len);
2860 	size_t res_len = (kt->bits + 7) / 8;
2861 
2862 	if(len != 0 && c == NULL) {
2863 	    krb5_set_error_string(context, "malloc: out of memory");
2864 	    return ENOMEM;
2865 	}
2866 	memcpy(c, constant, len);
2867 	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
2868 	k = malloc(res_len);
2869 	if(res_len != 0 && k == NULL) {
2870 	    free(c);
2871 	    krb5_set_error_string(context, "malloc: out of memory");
2872 	    return ENOMEM;
2873 	}
2874 	_krb5_n_fold(c, len, k, res_len);
2875 	free(c);
2876     }
2877 
2878     /* XXX keytype dependent post-processing */
2879     switch(kt->type) {
2880     case KEYTYPE_DES3:
2881 	DES3_postproc(context, k, nblocks * et->blocksize, key);
2882 	break;
2883     default:
2884 	krb5_set_error_string(context,
2885 			      "derive_key() called with unknown keytype (%u)",
2886 			      kt->type);
2887 	ret = KRB5_CRYPTO_INTERNAL;
2888 	break;
2889     }
2890     memset(k, 0, nblocks * et->blocksize);
2891     free(k);
2892     return ret;
2893 }
2894 
2895 static struct key_data *
2896 _new_derived_key(krb5_crypto crypto, unsigned usage)
2897 {
2898     struct key_usage *d = crypto->key_usage;
2899     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2900     if(d == NULL)
2901 	return NULL;
2902     crypto->key_usage = d;
2903     d += crypto->num_key_usage++;
2904     memset(d, 0, sizeof(*d));
2905     d->usage = usage;
2906     return &d->key;
2907 }
2908 
2909 krb5_error_code
2910 krb5_derive_key(krb5_context context,
2911 		const krb5_keyblock *key,
2912 		krb5_enctype etype,
2913 		const void *constant,
2914 		size_t constant_len,
2915 		krb5_keyblock **derived_key)
2916 {
2917     krb5_error_code ret;
2918     struct encryption_type *et;
2919     struct key_data d;
2920 
2921     et = _find_enctype (etype);
2922     if (et == NULL) {
2923 	krb5_set_error_string(context, "encryption type %d not supported",
2924 			      etype);
2925 	return KRB5_PROG_ETYPE_NOSUPP;
2926     }
2927 
2928     ret = krb5_copy_keyblock(context, key, derived_key);
2929     if (ret)
2930 	return ret;
2931 
2932     d.key = *derived_key;
2933     d.schedule = NULL;
2934     ret = derive_key(context, et, &d, constant, constant_len);
2935     if (ret)
2936 	return ret;
2937     ret = krb5_copy_keyblock(context, d.key, derived_key);
2938     return ret;
2939 }
2940 
2941 static krb5_error_code
2942 _get_derived_key(krb5_context context,
2943 		 krb5_crypto crypto,
2944 		 unsigned usage,
2945 		 struct key_data **key)
2946 {
2947     int i;
2948     struct key_data *d;
2949     unsigned char constant[5];
2950 
2951     for(i = 0; i < crypto->num_key_usage; i++)
2952 	if(crypto->key_usage[i].usage == usage) {
2953 	    *key = &crypto->key_usage[i].key;
2954 	    return 0;
2955 	}
2956     d = _new_derived_key(crypto, usage);
2957     if(d == NULL) {
2958 	krb5_set_error_string(context, "malloc: out of memory");
2959 	return ENOMEM;
2960     }
2961     krb5_copy_keyblock(context, crypto->key.key, &d->key);
2962     _krb5_put_int(constant, usage, 5);
2963     derive_key(context, crypto->et, d, constant, sizeof(constant));
2964     *key = d;
2965     return 0;
2966 }
2967 
2968 
2969 krb5_error_code
2970 krb5_crypto_init(krb5_context context,
2971 		 const krb5_keyblock *key,
2972 		 krb5_enctype etype,
2973 		 krb5_crypto *crypto)
2974 {
2975     krb5_error_code ret;
2976     ALLOC(*crypto, 1);
2977     if(*crypto == NULL) {
2978 	krb5_set_error_string(context, "malloc: out of memory");
2979 	return ENOMEM;
2980     }
2981     if(etype == ETYPE_NULL)
2982 	etype = key->keytype;
2983     (*crypto)->et = _find_enctype(etype);
2984     if((*crypto)->et == NULL) {
2985 	free(*crypto);
2986 	krb5_set_error_string (context, "encryption type %d not supported",
2987 			       etype);
2988 	return KRB5_PROG_ETYPE_NOSUPP;
2989     }
2990     if((*crypto)->et->keytype->size != key->keyvalue.length) {
2991 	free(*crypto);
2992 	krb5_set_error_string (context, "encryption key has bad length");
2993 	return KRB5_BAD_KEYSIZE;
2994     }
2995     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2996     if(ret) {
2997 	free(*crypto);
2998 	return ret;
2999     }
3000     (*crypto)->key.schedule = NULL;
3001     (*crypto)->num_key_usage = 0;
3002     (*crypto)->key_usage = NULL;
3003     return 0;
3004 }
3005 
3006 static void
3007 free_key_data(krb5_context context, struct key_data *key)
3008 {
3009     krb5_free_keyblock(context, key->key);
3010     if(key->schedule) {
3011 	memset(key->schedule->data, 0, key->schedule->length);
3012 	krb5_free_data(context, key->schedule);
3013     }
3014 }
3015 
3016 static void
3017 free_key_usage(krb5_context context, struct key_usage *ku)
3018 {
3019     free_key_data(context, &ku->key);
3020 }
3021 
3022 krb5_error_code
3023 krb5_crypto_destroy(krb5_context context,
3024 		    krb5_crypto crypto)
3025 {
3026     int i;
3027 
3028     for(i = 0; i < crypto->num_key_usage; i++)
3029 	free_key_usage(context, &crypto->key_usage[i]);
3030     free(crypto->key_usage);
3031     free_key_data(context, &crypto->key);
3032     free (crypto);
3033     return 0;
3034 }
3035 
3036 krb5_error_code
3037 krb5_crypto_getblocksize(krb5_context context,
3038 			 krb5_crypto crypto,
3039 			 size_t *blocksize)
3040 {
3041     *blocksize = crypto->et->blocksize;
3042     return 0;
3043 }
3044 
3045 krb5_error_code
3046 krb5_string_to_key_derived(krb5_context context,
3047 			   const void *str,
3048 			   size_t len,
3049 			   krb5_enctype etype,
3050 			   krb5_keyblock *key)
3051 {
3052     struct encryption_type *et = _find_enctype(etype);
3053     krb5_error_code ret;
3054     struct key_data kd;
3055     size_t keylen = et->keytype->bits / 8;
3056     u_char *tmp;
3057 
3058     if(et == NULL) {
3059 	krb5_set_error_string (context, "encryption type %d not supported",
3060 			       etype);
3061 	return KRB5_PROG_ETYPE_NOSUPP;
3062     }
3063     ALLOC(kd.key, 1);
3064     if(kd.key == NULL) {
3065 	krb5_set_error_string (context, "malloc: out of memory");
3066 	return ENOMEM;
3067     }
3068     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
3069     if(ret) {
3070 	free(kd.key);
3071 	return ret;
3072     }
3073     kd.key->keytype = etype;
3074     tmp = malloc (keylen);
3075     if(tmp == NULL) {
3076 	krb5_free_keyblock(context, kd.key);
3077 	krb5_set_error_string (context, "malloc: out of memory");
3078 	return ENOMEM;
3079     }
3080     _krb5_n_fold(str, len, tmp, keylen);
3081     kd.schedule = NULL;
3082     DES3_postproc (context, tmp, keylen, &kd); /* XXX */
3083     memset(tmp, 0, keylen);
3084     free(tmp);
3085     ret = derive_key(context,
3086 		     et,
3087 		     &kd,
3088 		     "kerberos", /* XXX well known constant */
3089 		     strlen("kerberos"));
3090     ret = krb5_copy_keyblock_contents(context, kd.key, key);
3091     free_key_data(context, &kd);
3092     return ret;
3093 }
3094 
3095 static size_t
3096 wrapped_length (krb5_context context,
3097 		krb5_crypto  crypto,
3098 		size_t       data_len)
3099 {
3100     struct encryption_type *et = crypto->et;
3101     size_t blocksize = et->blocksize;
3102     size_t res;
3103 
3104     res =  et->confoundersize + et->checksum->checksumsize + data_len;
3105     res =  (res + blocksize - 1) / blocksize * blocksize;
3106     return res;
3107 }
3108 
3109 static size_t
3110 wrapped_length_dervied (krb5_context context,
3111 			krb5_crypto  crypto,
3112 			size_t       data_len)
3113 {
3114     struct encryption_type *et = crypto->et;
3115     size_t blocksize = et->blocksize;
3116     size_t res;
3117 
3118     res =  et->confoundersize + data_len;
3119     res =  (res + blocksize - 1) / blocksize * blocksize;
3120     res += et->checksum->checksumsize;
3121     return res;
3122 }
3123 
3124 /*
3125  * Return the size of an encrypted packet of length `data_len'
3126  */
3127 
3128 size_t
3129 krb5_get_wrapped_length (krb5_context context,
3130 			 krb5_crypto  crypto,
3131 			 size_t       data_len)
3132 {
3133     if (derived_crypto (context, crypto))
3134 	return wrapped_length_dervied (context, crypto, data_len);
3135     else
3136 	return wrapped_length (context, crypto, data_len);
3137 }
3138 
3139 #ifdef CRYPTO_DEBUG
3140 
3141 static krb5_error_code
3142 krb5_get_keyid(krb5_context context,
3143 	       krb5_keyblock *key,
3144 	       u_int32_t *keyid)
3145 {
3146     MD5_CTX md5;
3147     unsigned char tmp[16];
3148 
3149     MD5_Init (&md5);
3150     MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
3151     MD5_Final (tmp, &md5);
3152     *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
3153     return 0;
3154 }
3155 
3156 static void
3157 krb5_crypto_debug(krb5_context context,
3158 		  int encrypt,
3159 		  size_t len,
3160 		  krb5_keyblock *key)
3161 {
3162     u_int32_t keyid;
3163     char *kt;
3164     krb5_get_keyid(context, key, &keyid);
3165     krb5_enctype_to_string(context, key->keytype, &kt);
3166     krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
3167 	       encrypt ? "encrypting" : "decrypting",
3168 	       (unsigned long)len,
3169 	       keyid,
3170 	       kt);
3171     free(kt);
3172 }
3173 
3174 #endif /* CRYPTO_DEBUG */
3175 
3176 #if 0
3177 int
3178 main()
3179 {
3180 #if 0
3181     int i;
3182     krb5_context context;
3183     krb5_crypto crypto;
3184     struct key_data *d;
3185     krb5_keyblock key;
3186     char constant[4];
3187     unsigned usage = ENCRYPTION_USAGE(3);
3188     krb5_error_code ret;
3189 
3190     ret = krb5_init_context(&context);
3191     if (ret)
3192 	errx (1, "krb5_init_context failed: %d", ret);
3193 
3194     key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
3195     key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
3196 	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
3197 	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
3198     key.keyvalue.length = 24;
3199 
3200     krb5_crypto_init(context, &key, 0, &crypto);
3201 
3202     d = _new_derived_key(crypto, usage);
3203     if(d == NULL)
3204 	return ENOMEM;
3205     krb5_copy_keyblock(context, crypto->key.key, &d->key);
3206     _krb5_put_int(constant, usage, 4);
3207     derive_key(context, crypto->et, d, constant, sizeof(constant));
3208     return 0;
3209 #else
3210     int i;
3211     krb5_context context;
3212     krb5_crypto crypto;
3213     struct key_data *d;
3214     krb5_keyblock key;
3215     krb5_error_code ret;
3216     Checksum res;
3217 
3218     char *data = "what do ya want for nothing?";
3219 
3220     ret = krb5_init_context(&context);
3221     if (ret)
3222 	errx (1, "krb5_init_context failed: %d", ret);
3223 
3224     key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
3225     key.keyvalue.data = "Jefe";
3226     /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
3227        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
3228     key.keyvalue.length = 4;
3229 
3230     d = calloc(1, sizeof(*d));
3231 
3232     d->key = &key;
3233     res.checksum.length = 20;
3234     res.checksum.data = malloc(res.checksum.length);
3235     HMAC_SHA1_DES3_checksum(context, d, data, 28, &res);
3236 
3237     return 0;
3238 #endif
3239 }
3240 #endif
3241