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