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