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