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