xref: /freebsd/crypto/heimdal/lib/krb5/crypto.c (revision 0cadf2f4d7b9f212800448d915003abd40c2e40d)
1 /*
2  * Copyright (c) 1997 - 2002 Kungliga Tekniska H�gskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include "krb5_locl.h"
35 RCSID("$Id: crypto.c,v 1.66 2002/09/03 19:58:15 joda Exp $");
36 
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 *ivec)
1680 {
1681     des_cblock local_ivec;
1682     des_key_schedule *s = key->schedule->data;
1683     if(ivec == NULL) {
1684 	ivec = &local_ivec;
1685 	memset(local_ivec, 0, sizeof(local_ivec));
1686     }
1687     des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt);
1688     return 0;
1689 }
1690 
1691 static krb5_error_code
1692 DES_CFB64_encrypt_null_ivec(krb5_context context,
1693 			    struct key_data *key,
1694 			    void *data,
1695 			    size_t len,
1696 			    krb5_boolean encrypt,
1697 			    int usage,
1698 			    void *ignore_ivec)
1699 {
1700     des_cblock ivec;
1701     int num = 0;
1702     des_key_schedule *s = key->schedule->data;
1703     memset(&ivec, 0, sizeof(ivec));
1704 
1705     des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
1706     return 0;
1707 }
1708 
1709 static krb5_error_code
1710 DES_PCBC_encrypt_key_ivec(krb5_context context,
1711 			  struct key_data *key,
1712 			  void *data,
1713 			  size_t len,
1714 			  krb5_boolean encrypt,
1715 			  int usage,
1716 			  void *ignore_ivec)
1717 {
1718     des_cblock ivec;
1719     des_key_schedule *s = key->schedule->data;
1720     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1721 
1722     des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
1723     return 0;
1724 }
1725 
1726 /*
1727  * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
1728  *
1729  * warning: not for small children
1730  */
1731 
1732 static krb5_error_code
1733 ARCFOUR_subencrypt(krb5_context context,
1734 		   struct key_data *key,
1735 		   void *data,
1736 		   size_t len,
1737 		   int usage,
1738 		   void *ivec)
1739 {
1740     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1741     Checksum k1_c, k2_c, k3_c, cksum;
1742     struct key_data ke;
1743     krb5_keyblock kb;
1744     unsigned char t[4];
1745     RC4_KEY rc4_key;
1746     unsigned char *cdata = data;
1747     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1748 
1749     t[0] = (usage >>  0) & 0xFF;
1750     t[1] = (usage >>  8) & 0xFF;
1751     t[2] = (usage >> 16) & 0xFF;
1752     t[3] = (usage >> 24) & 0xFF;
1753 
1754     k1_c.checksum.length = sizeof(k1_c_data);
1755     k1_c.checksum.data   = k1_c_data;
1756 
1757     hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1758 
1759     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1760 
1761     k2_c.checksum.length = sizeof(k2_c_data);
1762     k2_c.checksum.data   = k2_c_data;
1763 
1764     ke.key = &kb;
1765     kb.keyvalue = k2_c.checksum;
1766 
1767     cksum.checksum.length = 16;
1768     cksum.checksum.data   = data;
1769 
1770     hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1771 
1772     ke.key = &kb;
1773     kb.keyvalue = k1_c.checksum;
1774 
1775     k3_c.checksum.length = sizeof(k3_c_data);
1776     k3_c.checksum.data   = k3_c_data;
1777 
1778     hmac(NULL, c, data, 16, 0, &ke, &k3_c);
1779 
1780     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1781     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1782     memset (k1_c_data, 0, sizeof(k1_c_data));
1783     memset (k2_c_data, 0, sizeof(k2_c_data));
1784     memset (k3_c_data, 0, sizeof(k3_c_data));
1785     return 0;
1786 }
1787 
1788 static krb5_error_code
1789 ARCFOUR_subdecrypt(krb5_context context,
1790 		   struct key_data *key,
1791 		   void *data,
1792 		   size_t len,
1793 		   int usage,
1794 		   void *ivec)
1795 {
1796     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1797     Checksum k1_c, k2_c, k3_c, cksum;
1798     struct key_data ke;
1799     krb5_keyblock kb;
1800     unsigned char t[4];
1801     RC4_KEY rc4_key;
1802     unsigned char *cdata = data;
1803     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1804     unsigned char cksum_data[16];
1805 
1806     t[0] = (usage >>  0) & 0xFF;
1807     t[1] = (usage >>  8) & 0xFF;
1808     t[2] = (usage >> 16) & 0xFF;
1809     t[3] = (usage >> 24) & 0xFF;
1810 
1811     k1_c.checksum.length = sizeof(k1_c_data);
1812     k1_c.checksum.data   = k1_c_data;
1813 
1814     hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1815 
1816     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1817 
1818     k2_c.checksum.length = sizeof(k2_c_data);
1819     k2_c.checksum.data   = k2_c_data;
1820 
1821     ke.key = &kb;
1822     kb.keyvalue = k1_c.checksum;
1823 
1824     k3_c.checksum.length = sizeof(k3_c_data);
1825     k3_c.checksum.data   = k3_c_data;
1826 
1827     hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
1828 
1829     RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1830     RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1831 
1832     ke.key = &kb;
1833     kb.keyvalue = k2_c.checksum;
1834 
1835     cksum.checksum.length = 16;
1836     cksum.checksum.data   = cksum_data;
1837 
1838     hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1839 
1840     memset (k1_c_data, 0, sizeof(k1_c_data));
1841     memset (k2_c_data, 0, sizeof(k2_c_data));
1842     memset (k3_c_data, 0, sizeof(k3_c_data));
1843 
1844     if (memcmp (cksum.checksum.data, data, 16) != 0) {
1845 	krb5_clear_error_string (context);
1846 	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
1847     } else {
1848 	return 0;
1849     }
1850 }
1851 
1852 /*
1853  * convert the usage numbers used in
1854  * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
1855  * draft-brezak-win2k-krb-rc4-hmac-03.txt
1856  */
1857 
1858 static krb5_error_code
1859 usage2arcfour (krb5_context context, int *usage)
1860 {
1861     switch (*usage) {
1862     case KRB5_KU_PA_ENC_TIMESTAMP :
1863 	*usage = 1;
1864 	return 0;
1865     case KRB5_KU_TICKET :
1866 	*usage = 8;
1867     case KRB5_KU_AS_REP_ENC_PART :
1868 	*usage = 8;
1869 	return 0;
1870     case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
1871     case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
1872     case KRB5_KU_TGS_REQ_AUTH_CKSUM :
1873     case KRB5_KU_TGS_REQ_AUTH :
1874 	*usage = 7;
1875 	return 0;
1876     case KRB5_KU_TGS_REP_ENC_PART_SESSION :
1877     case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1878 	*usage = 8;
1879 	return 0;
1880     case KRB5_KU_AP_REQ_AUTH_CKSUM :
1881     case KRB5_KU_AP_REQ_AUTH :
1882     case KRB5_KU_AP_REQ_ENC_PART :
1883 	*usage = 11;
1884 	return 0;
1885     case KRB5_KU_KRB_PRIV :
1886 	*usage = 0;
1887 	return 0;
1888     case KRB5_KU_KRB_CRED :
1889     case KRB5_KU_KRB_SAFE_CKSUM :
1890     case KRB5_KU_OTHER_ENCRYPTED :
1891     case KRB5_KU_OTHER_CKSUM :
1892     case KRB5_KU_KRB_ERROR :
1893     case KRB5_KU_AD_KDC_ISSUED :
1894     case KRB5_KU_MANDATORY_TICKET_EXTENSION :
1895     case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
1896     case KRB5_KU_USAGE_SEAL :
1897     case KRB5_KU_USAGE_SIGN :
1898     case KRB5_KU_USAGE_SEQ :
1899     default :
1900 	krb5_set_error_string(context, "unknown arcfour usage type %d", *usage);
1901 	return KRB5_PROG_ETYPE_NOSUPP;
1902     }
1903 }
1904 
1905 static krb5_error_code
1906 ARCFOUR_encrypt(krb5_context context,
1907 		struct key_data *key,
1908 		void *data,
1909 		size_t len,
1910 		krb5_boolean encrypt,
1911 		int usage,
1912 		void *ivec)
1913 {
1914     krb5_error_code ret;
1915     if((ret = usage2arcfour (context, &usage)) != 0)
1916 	return ret;
1917 
1918     if (encrypt)
1919 	return ARCFOUR_subencrypt (context, key, data, len, usage, ivec);
1920     else
1921 	return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec);
1922 }
1923 
1924 
1925 /*
1926  * these should currently be in reverse preference order.
1927  * (only relevant for !F_PSEUDO) */
1928 
1929 static struct encryption_type enctype_null = {
1930     ETYPE_NULL,
1931     "null",
1932     1,
1933     0,
1934     &keytype_null,
1935     &checksum_none,
1936     NULL,
1937     0,
1938     NULL_encrypt,
1939 };
1940 static struct encryption_type enctype_des_cbc_crc = {
1941     ETYPE_DES_CBC_CRC,
1942     "des-cbc-crc",
1943     8,
1944     8,
1945     &keytype_des,
1946     &checksum_crc32,
1947     NULL,
1948     0,
1949     DES_CBC_encrypt_key_ivec,
1950 };
1951 static struct encryption_type enctype_des_cbc_md4 = {
1952     ETYPE_DES_CBC_MD4,
1953     "des-cbc-md4",
1954     8,
1955     8,
1956     &keytype_des,
1957     &checksum_rsa_md4,
1958     &checksum_rsa_md4_des,
1959     0,
1960     DES_CBC_encrypt_null_ivec,
1961 };
1962 static struct encryption_type enctype_des_cbc_md5 = {
1963     ETYPE_DES_CBC_MD5,
1964     "des-cbc-md5",
1965     8,
1966     8,
1967     &keytype_des,
1968     &checksum_rsa_md5,
1969     &checksum_rsa_md5_des,
1970     0,
1971     DES_CBC_encrypt_null_ivec,
1972 };
1973 static struct encryption_type enctype_arcfour_hmac_md5 = {
1974     ETYPE_ARCFOUR_HMAC_MD5,
1975     "arcfour-hmac-md5",
1976     1,
1977     8,
1978     &keytype_arcfour,
1979     &checksum_hmac_md5,
1980     &checksum_hmac_md5_enc,
1981     F_SPECIAL,
1982     ARCFOUR_encrypt
1983 };
1984 static struct encryption_type enctype_des3_cbc_md5 = {
1985     ETYPE_DES3_CBC_MD5,
1986     "des3-cbc-md5",
1987     8,
1988     8,
1989     &keytype_des3,
1990     &checksum_rsa_md5,
1991     &checksum_rsa_md5_des3,
1992     0,
1993     DES3_CBC_encrypt,
1994 };
1995 static struct encryption_type enctype_des3_cbc_sha1 = {
1996     ETYPE_DES3_CBC_SHA1,
1997     "des3-cbc-sha1",
1998     8,
1999     8,
2000     &keytype_des3_derived,
2001     &checksum_sha1,
2002     &checksum_hmac_sha1_des3,
2003     F_DERIVED,
2004     DES3_CBC_encrypt,
2005 };
2006 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2007     ETYPE_OLD_DES3_CBC_SHA1,
2008     "old-des3-cbc-sha1",
2009     8,
2010     8,
2011     &keytype_des3,
2012     &checksum_sha1,
2013     &checksum_hmac_sha1_des3,
2014     0,
2015     DES3_CBC_encrypt,
2016 };
2017 static struct encryption_type enctype_des_cbc_none = {
2018     ETYPE_DES_CBC_NONE,
2019     "des-cbc-none",
2020     8,
2021     0,
2022     &keytype_des,
2023     &checksum_none,
2024     NULL,
2025     F_PSEUDO,
2026     DES_CBC_encrypt_null_ivec,
2027 };
2028 static struct encryption_type enctype_des_cfb64_none = {
2029     ETYPE_DES_CFB64_NONE,
2030     "des-cfb64-none",
2031     1,
2032     0,
2033     &keytype_des,
2034     &checksum_none,
2035     NULL,
2036     F_PSEUDO,
2037     DES_CFB64_encrypt_null_ivec,
2038 };
2039 static struct encryption_type enctype_des_pcbc_none = {
2040     ETYPE_DES_PCBC_NONE,
2041     "des-pcbc-none",
2042     8,
2043     0,
2044     &keytype_des,
2045     &checksum_none,
2046     NULL,
2047     F_PSEUDO,
2048     DES_PCBC_encrypt_key_ivec,
2049 };
2050 static struct encryption_type enctype_des3_cbc_none = {
2051     ETYPE_DES3_CBC_NONE,
2052     "des3-cbc-none",
2053     8,
2054     0,
2055     &keytype_des3_derived,
2056     &checksum_none,
2057     NULL,
2058     F_PSEUDO,
2059     DES3_CBC_encrypt,
2060 };
2061 
2062 static struct encryption_type *etypes[] = {
2063     &enctype_null,
2064     &enctype_des_cbc_crc,
2065     &enctype_des_cbc_md4,
2066     &enctype_des_cbc_md5,
2067     &enctype_arcfour_hmac_md5,
2068     &enctype_des3_cbc_md5,
2069     &enctype_des3_cbc_sha1,
2070     &enctype_old_des3_cbc_sha1,
2071     &enctype_des_cbc_none,
2072     &enctype_des_cfb64_none,
2073     &enctype_des_pcbc_none,
2074     &enctype_des3_cbc_none
2075 };
2076 
2077 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2078 
2079 
2080 static struct encryption_type *
2081 _find_enctype(krb5_enctype type)
2082 {
2083     int i;
2084     for(i = 0; i < num_etypes; i++)
2085 	if(etypes[i]->type == type)
2086 	    return etypes[i];
2087     return NULL;
2088 }
2089 
2090 
2091 krb5_error_code
2092 krb5_enctype_to_string(krb5_context context,
2093 		       krb5_enctype etype,
2094 		       char **string)
2095 {
2096     struct encryption_type *e;
2097     e = _find_enctype(etype);
2098     if(e == NULL) {
2099 	krb5_set_error_string (context, "encryption type %d not supported",
2100 			       etype);
2101 	return KRB5_PROG_ETYPE_NOSUPP;
2102     }
2103     *string = strdup(e->name);
2104     if(*string == NULL) {
2105 	krb5_set_error_string(context, "malloc: out of memory");
2106 	return ENOMEM;
2107     }
2108     return 0;
2109 }
2110 
2111 krb5_error_code
2112 krb5_string_to_enctype(krb5_context context,
2113 		       const char *string,
2114 		       krb5_enctype *etype)
2115 {
2116     int i;
2117     for(i = 0; i < num_etypes; i++)
2118 	if(strcasecmp(etypes[i]->name, string) == 0){
2119 	    *etype = etypes[i]->type;
2120 	    return 0;
2121 	}
2122     krb5_set_error_string (context, "encryption type %s not supported",
2123 			   string);
2124     return KRB5_PROG_ETYPE_NOSUPP;
2125 }
2126 
2127 krb5_error_code
2128 krb5_enctype_to_keytype(krb5_context context,
2129 			krb5_enctype etype,
2130 			krb5_keytype *keytype)
2131 {
2132     struct encryption_type *e = _find_enctype(etype);
2133     if(e == NULL) {
2134 	krb5_set_error_string (context, "encryption type %d not supported",
2135 			       etype);
2136 	return KRB5_PROG_ETYPE_NOSUPP;
2137     }
2138     *keytype = e->keytype->type; /* XXX */
2139     return 0;
2140 }
2141 
2142 #if 0
2143 krb5_error_code
2144 krb5_keytype_to_enctype(krb5_context context,
2145 			krb5_keytype keytype,
2146 			krb5_enctype *etype)
2147 {
2148     struct key_type *kt = _find_keytype(keytype);
2149     krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
2150     if(kt == NULL)
2151 	return KRB5_PROG_KEYTYPE_NOSUPP;
2152     *etype = kt->best_etype;
2153     return 0;
2154 }
2155 #endif
2156 
2157 krb5_error_code
2158 krb5_keytype_to_enctypes (krb5_context context,
2159 			  krb5_keytype keytype,
2160 			  unsigned *len,
2161 			  krb5_enctype **val)
2162 {
2163     int i;
2164     unsigned n = 0;
2165     krb5_enctype *ret;
2166 
2167     for (i = num_etypes - 1; i >= 0; --i) {
2168 	if (etypes[i]->keytype->type == keytype
2169 	    && !(etypes[i]->flags & F_PSEUDO))
2170 	    ++n;
2171     }
2172     ret = malloc(n * sizeof(*ret));
2173     if (ret == NULL && n != 0) {
2174 	krb5_set_error_string(context, "malloc: out of memory");
2175 	return ENOMEM;
2176     }
2177     n = 0;
2178     for (i = num_etypes - 1; i >= 0; --i) {
2179 	if (etypes[i]->keytype->type == keytype
2180 	    && !(etypes[i]->flags & F_PSEUDO))
2181 	    ret[n++] = etypes[i]->type;
2182     }
2183     *len = n;
2184     *val = ret;
2185     return 0;
2186 }
2187 
2188 /*
2189  * First take the configured list of etypes for `keytype' if available,
2190  * else, do `krb5_keytype_to_enctypes'.
2191  */
2192 
2193 krb5_error_code
2194 krb5_keytype_to_enctypes_default (krb5_context context,
2195 				  krb5_keytype keytype,
2196 				  unsigned *len,
2197 				  krb5_enctype **val)
2198 {
2199     int i, n;
2200     krb5_enctype *ret;
2201 
2202     if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
2203 	return krb5_keytype_to_enctypes (context, keytype, len, val);
2204 
2205     for (n = 0; context->etypes_des[n]; ++n)
2206 	;
2207     ret = malloc (n * sizeof(*ret));
2208     if (ret == NULL && n != 0) {
2209 	krb5_set_error_string(context, "malloc: out of memory");
2210 	return ENOMEM;
2211     }
2212     for (i = 0; i < n; ++i)
2213 	ret[i] = context->etypes_des[i];
2214     *len = n;
2215     *val = ret;
2216     return 0;
2217 }
2218 
2219 krb5_error_code
2220 krb5_enctype_valid(krb5_context context,
2221 		 krb5_enctype etype)
2222 {
2223     return _find_enctype(etype) != NULL;
2224 }
2225 
2226 /* if two enctypes have compatible keys */
2227 krb5_boolean
2228 krb5_enctypes_compatible_keys(krb5_context context,
2229 			      krb5_enctype etype1,
2230 			      krb5_enctype etype2)
2231 {
2232     struct encryption_type *e1 = _find_enctype(etype1);
2233     struct encryption_type *e2 = _find_enctype(etype2);
2234     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2235 }
2236 
2237 static krb5_boolean
2238 derived_crypto(krb5_context context,
2239 	       krb5_crypto crypto)
2240 {
2241     return (crypto->et->flags & F_DERIVED) != 0;
2242 }
2243 
2244 static krb5_boolean
2245 special_crypto(krb5_context context,
2246 	       krb5_crypto crypto)
2247 {
2248     return (crypto->et->flags & F_SPECIAL) != 0;
2249 }
2250 
2251 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2252 #define CHECKSUMTYPE(C) ((C)->type)
2253 
2254 static krb5_error_code
2255 encrypt_internal_derived(krb5_context context,
2256 			 krb5_crypto crypto,
2257 			 unsigned usage,
2258 			 void *data,
2259 			 size_t len,
2260 			 krb5_data *result,
2261 			 void *ivec)
2262 {
2263     size_t sz, block_sz, checksum_sz, total_sz;
2264     Checksum cksum;
2265     unsigned char *p, *q;
2266     krb5_error_code ret;
2267     struct key_data *dkey;
2268     const struct encryption_type *et = crypto->et;
2269 
2270     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2271 
2272     sz = et->confoundersize + len;
2273     block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2274     total_sz = block_sz + checksum_sz;
2275     p = calloc(1, total_sz);
2276     if(p == NULL) {
2277 	krb5_set_error_string(context, "malloc: out of memory");
2278 	return ENOMEM;
2279     }
2280 
2281     q = p;
2282     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2283     q += et->confoundersize;
2284     memcpy(q, data, len);
2285 
2286     ret = create_checksum(context,
2287 			  crypto,
2288 			  INTEGRITY_USAGE(usage),
2289 			  et->keyed_checksum->type,
2290 			  p,
2291 			  block_sz,
2292 			  &cksum);
2293     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2294 	free_Checksum (&cksum);
2295 	krb5_clear_error_string (context);
2296 	ret = KRB5_CRYPTO_INTERNAL;
2297     }
2298     if(ret)
2299 	goto fail;
2300     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2301     free_Checksum (&cksum);
2302     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2303     if(ret)
2304 	goto fail;
2305     ret = _key_schedule(context, dkey);
2306     if(ret)
2307 	goto fail;
2308 #ifdef CRYPTO_DEBUG
2309     krb5_crypto_debug(context, 1, block_sz, dkey->key);
2310 #endif
2311     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2312     if (ret)
2313 	goto fail;
2314     result->data = p;
2315     result->length = total_sz;
2316     return 0;
2317  fail:
2318     memset(p, 0, total_sz);
2319     free(p);
2320     return ret;
2321 }
2322 
2323 
2324 static krb5_error_code
2325 encrypt_internal(krb5_context context,
2326 		 krb5_crypto crypto,
2327 		 void *data,
2328 		 size_t len,
2329 		 krb5_data *result,
2330 		 void *ivec)
2331 {
2332     size_t sz, block_sz, checksum_sz;
2333     Checksum cksum;
2334     unsigned char *p, *q;
2335     krb5_error_code ret;
2336     const struct encryption_type *et = crypto->et;
2337 
2338     checksum_sz = CHECKSUMSIZE(et->checksum);
2339 
2340     sz = et->confoundersize + checksum_sz + len;
2341     block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2342     p = calloc(1, block_sz);
2343     if(p == NULL) {
2344 	krb5_set_error_string(context, "malloc: out of memory");
2345 	return ENOMEM;
2346     }
2347 
2348     q = p;
2349     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2350     q += et->confoundersize;
2351     memset(q, 0, checksum_sz);
2352     q += checksum_sz;
2353     memcpy(q, data, len);
2354 
2355     ret = create_checksum(context,
2356 			  crypto,
2357 			  0,
2358 			  et->checksum->type,
2359 			  p,
2360 			  block_sz,
2361 			  &cksum);
2362     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2363 	krb5_clear_error_string (context);
2364 	free_Checksum(&cksum);
2365 	ret = KRB5_CRYPTO_INTERNAL;
2366     }
2367     if(ret)
2368 	goto fail;
2369     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2370     free_Checksum(&cksum);
2371     ret = _key_schedule(context, &crypto->key);
2372     if(ret)
2373 	goto fail;
2374 #ifdef CRYPTO_DEBUG
2375     krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
2376 #endif
2377     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
2378     if (ret) {
2379 	memset(p, 0, block_sz);
2380 	free(p);
2381 	return ret;
2382     }
2383     result->data = p;
2384     result->length = block_sz;
2385     return 0;
2386  fail:
2387     memset(p, 0, block_sz);
2388     free(p);
2389     return ret;
2390 }
2391 
2392 static krb5_error_code
2393 encrypt_internal_special(krb5_context context,
2394 			 krb5_crypto crypto,
2395 			 int usage,
2396 			 void *data,
2397 			 size_t len,
2398 			 krb5_data *result,
2399 			 void *ivec)
2400 {
2401     struct encryption_type *et = crypto->et;
2402     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2403     size_t sz = len + cksum_sz + et->confoundersize;
2404     char *tmp, *p;
2405     krb5_error_code ret;
2406 
2407     tmp = malloc (sz);
2408     if (tmp == NULL) {
2409 	krb5_set_error_string(context, "malloc: out of memory");
2410 	return ENOMEM;
2411     }
2412     p = tmp;
2413     memset (p, 0, cksum_sz);
2414     p += cksum_sz;
2415     krb5_generate_random_block(p, et->confoundersize);
2416     p += et->confoundersize;
2417     memcpy (p, data, len);
2418     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
2419     if (ret) {
2420 	memset(tmp, 0, sz);
2421 	free(tmp);
2422 	return ret;
2423     }
2424     result->data   = tmp;
2425     result->length = sz;
2426     return 0;
2427 }
2428 
2429 static krb5_error_code
2430 decrypt_internal_derived(krb5_context context,
2431 			 krb5_crypto crypto,
2432 			 unsigned usage,
2433 			 void *data,
2434 			 size_t len,
2435 			 krb5_data *result,
2436 			 void *ivec)
2437 {
2438     size_t checksum_sz;
2439     Checksum cksum;
2440     unsigned char *p;
2441     krb5_error_code ret;
2442     struct key_data *dkey;
2443     struct encryption_type *et = crypto->et;
2444     unsigned long l;
2445 
2446     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2447     if (len < checksum_sz) {
2448 	krb5_clear_error_string (context);
2449 	return EINVAL;		/* XXX - better error code? */
2450     }
2451 
2452     p = malloc(len);
2453     if(len != 0 && p == NULL) {
2454 	krb5_set_error_string(context, "malloc: out of memory");
2455 	return ENOMEM;
2456     }
2457     memcpy(p, data, len);
2458 
2459     len -= checksum_sz;
2460 
2461     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2462     if(ret) {
2463 	free(p);
2464 	return ret;
2465     }
2466     ret = _key_schedule(context, dkey);
2467     if(ret) {
2468 	free(p);
2469 	return ret;
2470     }
2471 #ifdef CRYPTO_DEBUG
2472     krb5_crypto_debug(context, 0, len, dkey->key);
2473 #endif
2474     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
2475     if (ret) {
2476 	free(p);
2477 	return ret;
2478     }
2479 
2480     cksum.checksum.data   = p + len;
2481     cksum.checksum.length = checksum_sz;
2482     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
2483 
2484     ret = verify_checksum(context,
2485 			  crypto,
2486 			  INTEGRITY_USAGE(usage),
2487 			  p,
2488 			  len,
2489 			  &cksum);
2490     if(ret) {
2491 	free(p);
2492 	return ret;
2493     }
2494     l = len - et->confoundersize;
2495     memmove(p, p + et->confoundersize, l);
2496     result->data = realloc(p, l);
2497     if(result->data == NULL) {
2498 	free(p);
2499 	krb5_set_error_string(context, "malloc: out of memory");
2500 	return ENOMEM;
2501     }
2502     result->length = l;
2503     return 0;
2504 }
2505 
2506 static krb5_error_code
2507 decrypt_internal(krb5_context context,
2508 		 krb5_crypto crypto,
2509 		 void *data,
2510 		 size_t len,
2511 		 krb5_data *result,
2512 		 void *ivec)
2513 {
2514     krb5_error_code ret;
2515     unsigned char *p;
2516     Checksum cksum;
2517     size_t checksum_sz, l;
2518     struct encryption_type *et = crypto->et;
2519 
2520     checksum_sz = CHECKSUMSIZE(et->checksum);
2521     p = malloc(len);
2522     if(len != 0 && p == NULL) {
2523 	krb5_set_error_string(context, "malloc: out of memory");
2524 	return ENOMEM;
2525     }
2526     memcpy(p, data, len);
2527 
2528     ret = _key_schedule(context, &crypto->key);
2529     if(ret) {
2530 	free(p);
2531 	return ret;
2532     }
2533 #ifdef CRYPTO_DEBUG
2534     krb5_crypto_debug(context, 0, len, crypto->key.key);
2535 #endif
2536     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
2537     if (ret) {
2538 	free(p);
2539 	return ret;
2540     }
2541     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
2542     if(ret) {
2543  	free(p);
2544  	return ret;
2545     }
2546     memset(p + et->confoundersize, 0, checksum_sz);
2547     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
2548     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
2549     free_Checksum(&cksum);
2550     if(ret) {
2551 	free(p);
2552 	return ret;
2553     }
2554     l = len - et->confoundersize - checksum_sz;
2555     memmove(p, p + et->confoundersize + checksum_sz, l);
2556     result->data = realloc(p, l);
2557     if(result->data == NULL) {
2558 	free(p);
2559 	krb5_set_error_string(context, "malloc: out of memory");
2560 	return ENOMEM;
2561     }
2562     result->length = l;
2563     return 0;
2564 }
2565 
2566 static krb5_error_code
2567 decrypt_internal_special(krb5_context context,
2568 			 krb5_crypto crypto,
2569 			 int usage,
2570 			 void *data,
2571 			 size_t len,
2572 			 krb5_data *result,
2573 			 void *ivec)
2574 {
2575     struct encryption_type *et = crypto->et;
2576     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
2577     size_t sz = len - cksum_sz - et->confoundersize;
2578     char *cdata = (char *)data;
2579     char *tmp;
2580     krb5_error_code ret;
2581 
2582     tmp = malloc (sz);
2583     if (tmp == NULL) {
2584 	krb5_set_error_string(context, "malloc: out of memory");
2585 	return ENOMEM;
2586     }
2587 
2588     ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
2589     if (ret) {
2590 	free(tmp);
2591 	return ret;
2592     }
2593 
2594     memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
2595 
2596     result->data   = tmp;
2597     result->length = sz;
2598     return 0;
2599 }
2600 
2601 
2602 krb5_error_code
2603 krb5_encrypt_ivec(krb5_context context,
2604 		  krb5_crypto crypto,
2605 		  unsigned usage,
2606 		  void *data,
2607 		  size_t len,
2608 		  krb5_data *result,
2609 		  void *ivec)
2610 {
2611     if(derived_crypto(context, crypto))
2612 	return encrypt_internal_derived(context, crypto, usage,
2613 					data, len, result, ivec);
2614     else if (special_crypto(context, crypto))
2615 	return encrypt_internal_special (context, crypto, usage,
2616 					 data, len, result, ivec);
2617     else
2618 	return encrypt_internal(context, crypto, data, len, result, ivec);
2619 }
2620 
2621 krb5_error_code
2622 krb5_encrypt(krb5_context context,
2623 	     krb5_crypto crypto,
2624 	     unsigned usage,
2625 	     void *data,
2626 	     size_t len,
2627 	     krb5_data *result)
2628 {
2629     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
2630 }
2631 
2632 krb5_error_code
2633 krb5_encrypt_EncryptedData(krb5_context context,
2634 			   krb5_crypto crypto,
2635 			   unsigned usage,
2636 			   void *data,
2637 			   size_t len,
2638 			   int kvno,
2639 			   EncryptedData *result)
2640 {
2641     result->etype = CRYPTO_ETYPE(crypto);
2642     if(kvno){
2643 	ALLOC(result->kvno, 1);
2644 	*result->kvno = kvno;
2645     }else
2646 	result->kvno = NULL;
2647     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
2648 }
2649 
2650 krb5_error_code
2651 krb5_decrypt_ivec(krb5_context context,
2652 		  krb5_crypto crypto,
2653 		  unsigned usage,
2654 		  void *data,
2655 		  size_t len,
2656 		  krb5_data *result,
2657 		  void *ivec)
2658 {
2659     if(derived_crypto(context, crypto))
2660 	return decrypt_internal_derived(context, crypto, usage,
2661 					data, len, result, ivec);
2662     else if (special_crypto (context, crypto))
2663 	return decrypt_internal_special(context, crypto, usage,
2664 					data, len, result, ivec);
2665     else
2666 	return decrypt_internal(context, crypto, data, len, result, ivec);
2667 }
2668 
2669 krb5_error_code
2670 krb5_decrypt(krb5_context context,
2671 	     krb5_crypto crypto,
2672 	     unsigned usage,
2673 	     void *data,
2674 	     size_t len,
2675 	     krb5_data *result)
2676 {
2677     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
2678 			      NULL);
2679 }
2680 
2681 krb5_error_code
2682 krb5_decrypt_EncryptedData(krb5_context context,
2683 			   krb5_crypto crypto,
2684 			   unsigned usage,
2685 			   const EncryptedData *e,
2686 			   krb5_data *result)
2687 {
2688     return krb5_decrypt(context, crypto, usage,
2689 			e->cipher.data, e->cipher.length, result);
2690 }
2691 
2692 /************************************************************
2693  *                                                          *
2694  ************************************************************/
2695 
2696 #ifdef HAVE_OPENSSL
2697 #include <openssl/rand.h>
2698 
2699 /* From openssl/crypto/rand/rand_lcl.h */
2700 #define ENTROPY_NEEDED 20
2701 static int
2702 seed_something(void)
2703 {
2704     int fd = -1;
2705     char buf[1024], seedfile[256];
2706 
2707     /* If there is a seed file, load it. But such a file cannot be trusted,
2708        so use 0 for the entropy estimate */
2709     if (RAND_file_name(seedfile, sizeof(seedfile))) {
2710 	fd = open(seedfile, O_RDONLY);
2711 	if (fd >= 0) {
2712 	    read(fd, buf, sizeof(buf));
2713 	    /* Use the full buffer anyway */
2714 	    RAND_add(buf, sizeof(buf), 0.0);
2715 	} else
2716 	    seedfile[0] = '\0';
2717     } else
2718 	seedfile[0] = '\0';
2719 
2720     /* Calling RAND_status() will try to use /dev/urandom if it exists so
2721        we do not have to deal with it. */
2722     if (RAND_status() != 1) {
2723 	krb5_context context;
2724 	const char *p;
2725 
2726 	/* Try using egd */
2727 	if (!krb5_init_context(&context)) {
2728 	    p = krb5_config_get_string(context, NULL, "libdefaults",
2729 		"egd_socket", NULL);
2730 	    if (p != NULL)
2731 		RAND_egd_bytes(p, ENTROPY_NEEDED);
2732 	    krb5_free_context(context);
2733 	}
2734     }
2735 
2736     if (RAND_status() == 1)	{
2737 	/* Update the seed file */
2738 	if (seedfile[0])
2739 	    RAND_write_file(seedfile);
2740 
2741 	return 0;
2742     } else
2743 	return -1;
2744 }
2745 
2746 void
2747 krb5_generate_random_block(void *buf, size_t len)
2748 {
2749     static int rng_initialized = 0;
2750 
2751     if (!rng_initialized) {
2752 	if (seed_something())
2753 	    krb5_abortx(NULL, "Fatal: could not seed the random number generator");
2754 
2755 	rng_initialized = 1;
2756     }
2757     RAND_bytes(buf, len);
2758 }
2759 
2760 #else
2761 
2762 void
2763 krb5_generate_random_block(void *buf, size_t len)
2764 {
2765     des_cblock key, out;
2766     static des_cblock counter;
2767     static des_key_schedule schedule;
2768     int i;
2769     static int initialized = 0;
2770 
2771     if(!initialized) {
2772 	des_new_random_key(&key);
2773 	des_set_key(&key, schedule);
2774 	memset(&key, 0, sizeof(key));
2775 	des_new_random_key(&counter);
2776     }
2777     while(len > 0) {
2778 	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
2779 	for(i = 7; i >=0; i--)
2780 	    if(counter[i]++)
2781 		break;
2782 	memcpy(buf, out, min(len, sizeof(out)));
2783 	len -= min(len, sizeof(out));
2784 	buf = (char*)buf + sizeof(out);
2785     }
2786 }
2787 #endif
2788 
2789 static void
2790 DES3_postproc(krb5_context context,
2791 	      unsigned char *k, size_t len, struct key_data *key)
2792 {
2793     unsigned char x[24];
2794     int i, j;
2795 
2796     memset(x, 0, sizeof(x));
2797     for (i = 0; i < 3; ++i) {
2798 	unsigned char foo;
2799 
2800 	for (j = 0; j < 7; ++j) {
2801 	    unsigned char b = k[7 * i + j];
2802 
2803 	    x[8 * i + j] = b;
2804 	}
2805 	foo = 0;
2806 	for (j = 6; j >= 0; --j) {
2807 	    foo |= k[7 * i + j] & 1;
2808 	    foo <<= 1;
2809 	}
2810 	x[8 * i + 7] = foo;
2811     }
2812     k = key->key->keyvalue.data;
2813     memcpy(k, x, 24);
2814     memset(x, 0, sizeof(x));
2815     if (key->schedule) {
2816 	krb5_free_data(context, key->schedule);
2817 	key->schedule = NULL;
2818     }
2819     des_set_odd_parity((des_cblock*)k);
2820     des_set_odd_parity((des_cblock*)(k + 8));
2821     des_set_odd_parity((des_cblock*)(k + 16));
2822 }
2823 
2824 static krb5_error_code
2825 derive_key(krb5_context context,
2826 	   struct encryption_type *et,
2827 	   struct key_data *key,
2828 	   const void *constant,
2829 	   size_t len)
2830 {
2831     unsigned char *k;
2832     unsigned int nblocks = 0, i;
2833     krb5_error_code ret = 0;
2834 
2835     struct key_type *kt = et->keytype;
2836     ret = _key_schedule(context, key);
2837     if(ret)
2838 	return ret;
2839     if(et->blocksize * 8 < kt->bits ||
2840        len != et->blocksize) {
2841 	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2842 	k = malloc(nblocks * et->blocksize);
2843 	if(k == NULL) {
2844 	    krb5_set_error_string(context, "malloc: out of memory");
2845 	    return ENOMEM;
2846 	}
2847 	_krb5_n_fold(constant, len, k, et->blocksize);
2848 	for(i = 0; i < nblocks; i++) {
2849 	    if(i > 0)
2850 		memcpy(k + i * et->blocksize,
2851 		       k + (i - 1) * et->blocksize,
2852 		       et->blocksize);
2853 	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
2854 			   1, 0, NULL);
2855 	}
2856     } else {
2857 	/* this case is probably broken, but won't be run anyway */
2858 	void *c = malloc(len);
2859 	size_t res_len = (kt->bits + 7) / 8;
2860 
2861 	if(len != 0 && c == NULL) {
2862 	    krb5_set_error_string(context, "malloc: out of memory");
2863 	    return ENOMEM;
2864 	}
2865 	memcpy(c, constant, len);
2866 	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
2867 	k = malloc(res_len);
2868 	if(res_len != 0 && k == NULL) {
2869 	    free(c);
2870 	    krb5_set_error_string(context, "malloc: out of memory");
2871 	    return ENOMEM;
2872 	}
2873 	_krb5_n_fold(c, len, k, res_len);
2874 	free(c);
2875     }
2876 
2877     /* XXX keytype dependent post-processing */
2878     switch(kt->type) {
2879     case KEYTYPE_DES3:
2880 	DES3_postproc(context, k, nblocks * et->blocksize, key);
2881 	break;
2882     default:
2883 	krb5_set_error_string(context,
2884 			      "derive_key() called with unknown keytype (%u)",
2885 			      kt->type);
2886 	ret = KRB5_CRYPTO_INTERNAL;
2887 	break;
2888     }
2889     memset(k, 0, nblocks * et->blocksize);
2890     free(k);
2891     return ret;
2892 }
2893 
2894 static struct key_data *
2895 _new_derived_key(krb5_crypto crypto, unsigned usage)
2896 {
2897     struct key_usage *d = crypto->key_usage;
2898     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2899     if(d == NULL)
2900 	return NULL;
2901     crypto->key_usage = d;
2902     d += crypto->num_key_usage++;
2903     memset(d, 0, sizeof(*d));
2904     d->usage = usage;
2905     return &d->key;
2906 }
2907 
2908 krb5_error_code
2909 krb5_derive_key(krb5_context context,
2910 		const krb5_keyblock *key,
2911 		krb5_enctype etype,
2912 		const void *constant,
2913 		size_t constant_len,
2914 		krb5_keyblock **derived_key)
2915 {
2916     krb5_error_code ret;
2917     struct encryption_type *et;
2918     struct key_data d;
2919 
2920     et = _find_enctype (etype);
2921     if (et == NULL) {
2922 	krb5_set_error_string(context, "encryption type %d not supported",
2923 			      etype);
2924 	return KRB5_PROG_ETYPE_NOSUPP;
2925     }
2926 
2927     ret = krb5_copy_keyblock(context, key, derived_key);
2928     if (ret)
2929 	return ret;
2930 
2931     d.key = *derived_key;
2932     d.schedule = NULL;
2933     ret = derive_key(context, et, &d, constant, constant_len);
2934     if (ret)
2935 	return ret;
2936     ret = krb5_copy_keyblock(context, d.key, derived_key);
2937     return ret;
2938 }
2939 
2940 static krb5_error_code
2941 _get_derived_key(krb5_context context,
2942 		 krb5_crypto crypto,
2943 		 unsigned usage,
2944 		 struct key_data **key)
2945 {
2946     int i;
2947     struct key_data *d;
2948     unsigned char constant[5];
2949 
2950     for(i = 0; i < crypto->num_key_usage; i++)
2951 	if(crypto->key_usage[i].usage == usage) {
2952 	    *key = &crypto->key_usage[i].key;
2953 	    return 0;
2954 	}
2955     d = _new_derived_key(crypto, usage);
2956     if(d == NULL) {
2957 	krb5_set_error_string(context, "malloc: out of memory");
2958 	return ENOMEM;
2959     }
2960     krb5_copy_keyblock(context, crypto->key.key, &d->key);
2961     _krb5_put_int(constant, usage, 5);
2962     derive_key(context, crypto->et, d, constant, sizeof(constant));
2963     *key = d;
2964     return 0;
2965 }
2966 
2967 
2968 krb5_error_code
2969 krb5_crypto_init(krb5_context context,
2970 		 const krb5_keyblock *key,
2971 		 krb5_enctype etype,
2972 		 krb5_crypto *crypto)
2973 {
2974     krb5_error_code ret;
2975     ALLOC(*crypto, 1);
2976     if(*crypto == NULL) {
2977 	krb5_set_error_string(context, "malloc: out of memory");
2978 	return ENOMEM;
2979     }
2980     if(etype == ETYPE_NULL)
2981 	etype = key->keytype;
2982     (*crypto)->et = _find_enctype(etype);
2983     if((*crypto)->et == NULL) {
2984 	free(*crypto);
2985 	krb5_set_error_string (context, "encryption type %d not supported",
2986 			       etype);
2987 	return KRB5_PROG_ETYPE_NOSUPP;
2988     }
2989     if((*crypto)->et->keytype->size != key->keyvalue.length) {
2990 	free(*crypto);
2991 	krb5_set_error_string (context, "encryption key has bad length");
2992 	return KRB5_BAD_KEYSIZE;
2993     }
2994     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2995     if(ret) {
2996 	free(*crypto);
2997 	return ret;
2998     }
2999     (*crypto)->key.schedule = NULL;
3000     (*crypto)->num_key_usage = 0;
3001     (*crypto)->key_usage = NULL;
3002     return 0;
3003 }
3004 
3005 static void
3006 free_key_data(krb5_context context, struct key_data *key)
3007 {
3008     krb5_free_keyblock(context, key->key);
3009     if(key->schedule) {
3010 	memset(key->schedule->data, 0, key->schedule->length);
3011 	krb5_free_data(context, key->schedule);
3012     }
3013 }
3014 
3015 static void
3016 free_key_usage(krb5_context context, struct key_usage *ku)
3017 {
3018     free_key_data(context, &ku->key);
3019 }
3020 
3021 krb5_error_code
3022 krb5_crypto_destroy(krb5_context context,
3023 		    krb5_crypto crypto)
3024 {
3025     int i;
3026 
3027     for(i = 0; i < crypto->num_key_usage; i++)
3028 	free_key_usage(context, &crypto->key_usage[i]);
3029     free(crypto->key_usage);
3030     free_key_data(context, &crypto->key);
3031     free (crypto);
3032     return 0;
3033 }
3034 
3035 krb5_error_code
3036 krb5_crypto_getblocksize(krb5_context context,
3037 			 krb5_crypto crypto,
3038 			 size_t *blocksize)
3039 {
3040     *blocksize = crypto->et->blocksize;
3041     return 0;
3042 }
3043 
3044 krb5_error_code
3045 krb5_string_to_key_derived(krb5_context context,
3046 			   const void *str,
3047 			   size_t len,
3048 			   krb5_enctype etype,
3049 			   krb5_keyblock *key)
3050 {
3051     struct encryption_type *et = _find_enctype(etype);
3052     krb5_error_code ret;
3053     struct key_data kd;
3054     size_t keylen = et->keytype->bits / 8;
3055     u_char *tmp;
3056 
3057     if(et == NULL) {
3058 	krb5_set_error_string (context, "encryption type %d not supported",
3059 			       etype);
3060 	return KRB5_PROG_ETYPE_NOSUPP;
3061     }
3062     ALLOC(kd.key, 1);
3063     if(kd.key == NULL) {
3064 	krb5_set_error_string (context, "malloc: out of memory");
3065 	return ENOMEM;
3066     }
3067     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
3068     if(ret) {
3069 	free(kd.key);
3070 	return ret;
3071     }
3072     kd.key->keytype = etype;
3073     tmp = malloc (keylen);
3074     if(tmp == NULL) {
3075 	krb5_free_keyblock(context, kd.key);
3076 	krb5_set_error_string (context, "malloc: out of memory");
3077 	return ENOMEM;
3078     }
3079     _krb5_n_fold(str, len, tmp, keylen);
3080     kd.schedule = NULL;
3081     DES3_postproc (context, tmp, keylen, &kd); /* XXX */
3082     memset(tmp, 0, keylen);
3083     free(tmp);
3084     ret = derive_key(context,
3085 		     et,
3086 		     &kd,
3087 		     "kerberos", /* XXX well known constant */
3088 		     strlen("kerberos"));
3089     ret = krb5_copy_keyblock_contents(context, kd.key, key);
3090     free_key_data(context, &kd);
3091     return ret;
3092 }
3093 
3094 static size_t
3095 wrapped_length (krb5_context context,
3096 		krb5_crypto  crypto,
3097 		size_t       data_len)
3098 {
3099     struct encryption_type *et = crypto->et;
3100     size_t blocksize = et->blocksize;
3101     size_t res;
3102 
3103     res =  et->confoundersize + et->checksum->checksumsize + data_len;
3104     res =  (res + blocksize - 1) / blocksize * blocksize;
3105     return res;
3106 }
3107 
3108 static size_t
3109 wrapped_length_dervied (krb5_context context,
3110 			krb5_crypto  crypto,
3111 			size_t       data_len)
3112 {
3113     struct encryption_type *et = crypto->et;
3114     size_t blocksize = et->blocksize;
3115     size_t res;
3116 
3117     res =  et->confoundersize + data_len;
3118     res =  (res + blocksize - 1) / blocksize * blocksize;
3119     res += et->checksum->checksumsize;
3120     return res;
3121 }
3122 
3123 /*
3124  * Return the size of an encrypted packet of length `data_len'
3125  */
3126 
3127 size_t
3128 krb5_get_wrapped_length (krb5_context context,
3129 			 krb5_crypto  crypto,
3130 			 size_t       data_len)
3131 {
3132     if (derived_crypto (context, crypto))
3133 	return wrapped_length_dervied (context, crypto, data_len);
3134     else
3135 	return wrapped_length (context, crypto, data_len);
3136 }
3137 
3138 #ifdef CRYPTO_DEBUG
3139 
3140 static krb5_error_code
3141 krb5_get_keyid(krb5_context context,
3142 	       krb5_keyblock *key,
3143 	       u_int32_t *keyid)
3144 {
3145     MD5_CTX md5;
3146     unsigned char tmp[16];
3147 
3148     MD5_Init (&md5);
3149     MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
3150     MD5_Final (tmp, &md5);
3151     *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
3152     return 0;
3153 }
3154 
3155 static void
3156 krb5_crypto_debug(krb5_context context,
3157 		  int encrypt,
3158 		  size_t len,
3159 		  krb5_keyblock *key)
3160 {
3161     u_int32_t keyid;
3162     char *kt;
3163     krb5_get_keyid(context, key, &keyid);
3164     krb5_enctype_to_string(context, key->keytype, &kt);
3165     krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
3166 	       encrypt ? "encrypting" : "decrypting",
3167 	       (unsigned long)len,
3168 	       keyid,
3169 	       kt);
3170     free(kt);
3171 }
3172 
3173 #endif /* CRYPTO_DEBUG */
3174 
3175 #if 0
3176 int
3177 main()
3178 {
3179 #if 0
3180     int i;
3181     krb5_context context;
3182     krb5_crypto crypto;
3183     struct key_data *d;
3184     krb5_keyblock key;
3185     char constant[4];
3186     unsigned usage = ENCRYPTION_USAGE(3);
3187     krb5_error_code ret;
3188 
3189     ret = krb5_init_context(&context);
3190     if (ret)
3191 	errx (1, "krb5_init_context failed: %d", ret);
3192 
3193     key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
3194     key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
3195 	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
3196 	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
3197     key.keyvalue.length = 24;
3198 
3199     krb5_crypto_init(context, &key, 0, &crypto);
3200 
3201     d = _new_derived_key(crypto, usage);
3202     if(d == NULL)
3203 	return ENOMEM;
3204     krb5_copy_keyblock(context, crypto->key.key, &d->key);
3205     _krb5_put_int(constant, usage, 4);
3206     derive_key(context, crypto->et, d, constant, sizeof(constant));
3207     return 0;
3208 #else
3209     int i;
3210     krb5_context context;
3211     krb5_crypto crypto;
3212     struct key_data *d;
3213     krb5_keyblock key;
3214     krb5_error_code ret;
3215     Checksum res;
3216 
3217     char *data = "what do ya want for nothing?";
3218 
3219     ret = krb5_init_context(&context);
3220     if (ret)
3221 	errx (1, "krb5_init_context failed: %d", ret);
3222 
3223     key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
3224     key.keyvalue.data = "Jefe";
3225     /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
3226        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
3227     key.keyvalue.length = 4;
3228 
3229     d = calloc(1, sizeof(*d));
3230 
3231     d->key = &key;
3232     res.checksum.length = 20;
3233     res.checksum.data = malloc(res.checksum.length);
3234     HMAC_SHA1_DES3_checksum(context, d, data, 28, &res);
3235 
3236     return 0;
3237 #endif
3238 }
3239 #endif
3240