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