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