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