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