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