xref: /minix3/crypto/external/bsd/heimdal/dist/lib/krb5/crypto.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 /*	$NetBSD: crypto.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $	*/
2 
3 /*
4  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5  * (Royal Institute of Technology, Stockholm, Sweden).
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * 3. Neither the name of the Institute nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #include "krb5_locl.h"
37 
38 struct _krb5_key_usage {
39     unsigned usage;
40     struct _krb5_key_data key;
41 };
42 
43 
44 #ifndef HEIMDAL_SMALLER
45 #define DES3_OLD_ENCTYPE 1
46 #endif
47 
48 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
49 					unsigned, struct _krb5_key_data**);
50 static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
51 
52 static void free_key_schedule(krb5_context,
53 			      struct _krb5_key_data *,
54 			      struct _krb5_encryption_type *);
55 
56 /*
57  * Converts etype to a user readable string and sets as a side effect
58  * the krb5_error_message containing this string. Returns
59  * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
60  * which case the error code of the etype convesion is returned.
61  */
62 
63 static krb5_error_code
unsupported_enctype(krb5_context context,krb5_enctype etype)64 unsupported_enctype(krb5_context context, krb5_enctype etype)
65 {
66     krb5_error_code ret;
67     char *name;
68 
69     ret = krb5_enctype_to_string(context, etype, &name);
70     if (ret)
71 	return ret;
72 
73     krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
74 			   N_("Encryption type %s not supported", ""),
75 			   name);
76     free(name);
77     return KRB5_PROG_ETYPE_NOSUPP;
78 }
79 
80 /*
81  *
82  */
83 
84 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keysize(krb5_context context,krb5_enctype type,size_t * keysize)85 krb5_enctype_keysize(krb5_context context,
86 		     krb5_enctype type,
87 		     size_t *keysize)
88 {
89     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
90     if(et == NULL) {
91         return unsupported_enctype (context, type);
92     }
93     *keysize = et->keytype->size;
94     return 0;
95 }
96 
97 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_keybits(krb5_context context,krb5_enctype type,size_t * keybits)98 krb5_enctype_keybits(krb5_context context,
99 		     krb5_enctype type,
100 		     size_t *keybits)
101 {
102     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
103     if(et == NULL) {
104         return unsupported_enctype (context, type);
105     }
106     *keybits = et->keytype->bits;
107     return 0;
108 }
109 
110 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_generate_random_keyblock(krb5_context context,krb5_enctype type,krb5_keyblock * key)111 krb5_generate_random_keyblock(krb5_context context,
112 			      krb5_enctype type,
113 			      krb5_keyblock *key)
114 {
115     krb5_error_code ret;
116     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
117     if(et == NULL) {
118         return unsupported_enctype (context, type);
119     }
120     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
121     if(ret)
122 	return ret;
123     key->keytype = type;
124     if(et->keytype->random_key)
125 	(*et->keytype->random_key)(context, key);
126     else
127 	krb5_generate_random_block(key->keyvalue.data,
128 				   key->keyvalue.length);
129     return 0;
130 }
131 
132 static krb5_error_code
_key_schedule(krb5_context context,struct _krb5_key_data * key)133 _key_schedule(krb5_context context,
134 	      struct _krb5_key_data *key)
135 {
136     krb5_error_code ret;
137     struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
138     struct _krb5_key_type *kt;
139 
140     if (et == NULL) {
141         return unsupported_enctype (context,
142                                key->key->keytype);
143     }
144 
145     kt = et->keytype;
146 
147     if(kt->schedule == NULL)
148 	return 0;
149     if (key->schedule != NULL)
150 	return 0;
151     ALLOC(key->schedule, 1);
152     if(key->schedule == NULL) {
153 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
154 	return ENOMEM;
155     }
156     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
157     if(ret) {
158 	free(key->schedule);
159 	key->schedule = NULL;
160 	return ret;
161     }
162     (*kt->schedule)(context, kt, key);
163     return 0;
164 }
165 
166 /************************************************************
167  *                                                          *
168  ************************************************************/
169 
170 static krb5_error_code
SHA1_checksum(krb5_context context,struct _krb5_key_data * key,const void * data,size_t len,unsigned usage,Checksum * C)171 SHA1_checksum(krb5_context context,
172 	      struct _krb5_key_data *key,
173 	      const void *data,
174 	      size_t len,
175 	      unsigned usage,
176 	      Checksum *C)
177 {
178     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
179 	krb5_abortx(context, "sha1 checksum failed");
180     return 0;
181 }
182 
183 /* HMAC according to RFC2104 */
184 krb5_error_code
_krb5_internal_hmac(krb5_context context,struct _krb5_checksum_type * cm,const void * data,size_t len,unsigned usage,struct _krb5_key_data * keyblock,Checksum * result)185 _krb5_internal_hmac(krb5_context context,
186 		    struct _krb5_checksum_type *cm,
187 		    const void *data,
188 		    size_t len,
189 		    unsigned usage,
190 		    struct _krb5_key_data *keyblock,
191 		    Checksum *result)
192 {
193     unsigned char *ipad, *opad;
194     unsigned char *key;
195     size_t key_len;
196     size_t i;
197 
198     ipad = malloc(cm->blocksize + len);
199     if (ipad == NULL)
200 	return ENOMEM;
201     opad = malloc(cm->blocksize + cm->checksumsize);
202     if (opad == NULL) {
203 	free(ipad);
204 	return ENOMEM;
205     }
206     memset(ipad, 0x36, cm->blocksize);
207     memset(opad, 0x5c, cm->blocksize);
208 
209     if(keyblock->key->keyvalue.length > cm->blocksize){
210 	(*cm->checksum)(context,
211 			keyblock,
212 			keyblock->key->keyvalue.data,
213 			keyblock->key->keyvalue.length,
214 			usage,
215 			result);
216 	key = result->checksum.data;
217 	key_len = result->checksum.length;
218     } else {
219 	key = keyblock->key->keyvalue.data;
220 	key_len = keyblock->key->keyvalue.length;
221     }
222     for(i = 0; i < key_len; i++){
223 	ipad[i] ^= key[i];
224 	opad[i] ^= key[i];
225     }
226     memcpy(ipad + cm->blocksize, data, len);
227     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
228 		    usage, result);
229     memcpy(opad + cm->blocksize, result->checksum.data,
230 	   result->checksum.length);
231     (*cm->checksum)(context, keyblock, opad,
232 		    cm->blocksize + cm->checksumsize, usage, result);
233     memset(ipad, 0, cm->blocksize + len);
234     free(ipad);
235     memset(opad, 0, cm->blocksize + cm->checksumsize);
236     free(opad);
237 
238     return 0;
239 }
240 
241 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_hmac(krb5_context context,krb5_cksumtype cktype,const void * data,size_t len,unsigned usage,krb5_keyblock * key,Checksum * result)242 krb5_hmac(krb5_context context,
243 	  krb5_cksumtype cktype,
244 	  const void *data,
245 	  size_t len,
246 	  unsigned usage,
247 	  krb5_keyblock *key,
248 	  Checksum *result)
249 {
250     struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
251     struct _krb5_key_data kd;
252     krb5_error_code ret;
253 
254     if (c == NULL) {
255 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
256 				N_("checksum type %d not supported", ""),
257 				cktype);
258 	return KRB5_PROG_SUMTYPE_NOSUPP;
259     }
260 
261     kd.key = key;
262     kd.schedule = NULL;
263 
264     ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
265 
266     if (kd.schedule)
267 	krb5_free_data(context, kd.schedule);
268 
269     return ret;
270 }
271 
272 krb5_error_code
_krb5_SP_HMAC_SHA1_checksum(krb5_context context,struct _krb5_key_data * key,const void * data,size_t len,unsigned usage,Checksum * result)273 _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
274 			    struct _krb5_key_data *key,
275 			    const void *data,
276 			    size_t len,
277 			    unsigned usage,
278 			    Checksum *result)
279 {
280     struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
281     Checksum res;
282     char sha1_data[20];
283     krb5_error_code ret;
284 
285     res.checksum.data = sha1_data;
286     res.checksum.length = sizeof(sha1_data);
287 
288     ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
289     if (ret)
290 	krb5_abortx(context, "hmac failed");
291     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
292     return 0;
293 }
294 
295 struct _krb5_checksum_type _krb5_checksum_sha1 = {
296     CKSUMTYPE_SHA1,
297     "sha1",
298     64,
299     20,
300     F_CPROOF,
301     SHA1_checksum,
302     NULL
303 };
304 
305 struct _krb5_checksum_type *
_krb5_find_checksum(krb5_cksumtype type)306 _krb5_find_checksum(krb5_cksumtype type)
307 {
308     int i;
309     for(i = 0; i < _krb5_num_checksums; i++)
310 	if(_krb5_checksum_types[i]->type == type)
311 	    return _krb5_checksum_types[i];
312     return NULL;
313 }
314 
315 static krb5_error_code
get_checksum_key(krb5_context context,krb5_crypto crypto,unsigned usage,struct _krb5_checksum_type * ct,struct _krb5_key_data ** key)316 get_checksum_key(krb5_context context,
317 		 krb5_crypto crypto,
318 		 unsigned usage,  /* not krb5_key_usage */
319 		 struct _krb5_checksum_type *ct,
320 		 struct _krb5_key_data **key)
321 {
322     krb5_error_code ret = 0;
323 
324     if(ct->flags & F_DERIVED)
325 	ret = _get_derived_key(context, crypto, usage, key);
326     else if(ct->flags & F_VARIANT) {
327 	size_t i;
328 
329 	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
330 	if(*key == NULL) {
331 	    krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
332 	    return ENOMEM;
333 	}
334 	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
335 	if(ret)
336 	    return ret;
337 	for(i = 0; i < (*key)->key->keyvalue.length; i++)
338 	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
339     } else {
340 	*key = &crypto->key;
341     }
342     if(ret == 0)
343 	ret = _key_schedule(context, *key);
344     return ret;
345 }
346 
347 static krb5_error_code
create_checksum(krb5_context context,struct _krb5_checksum_type * ct,krb5_crypto crypto,unsigned usage,void * data,size_t len,Checksum * result)348 create_checksum (krb5_context context,
349 		 struct _krb5_checksum_type *ct,
350 		 krb5_crypto crypto,
351 		 unsigned usage,
352 		 void *data,
353 		 size_t len,
354 		 Checksum *result)
355 {
356     krb5_error_code ret;
357     struct _krb5_key_data *dkey;
358     int keyed_checksum;
359 
360     if (ct->flags & F_DISABLED) {
361 	krb5_clear_error_message (context);
362 	return KRB5_PROG_SUMTYPE_NOSUPP;
363     }
364     keyed_checksum = (ct->flags & F_KEYED) != 0;
365     if(keyed_checksum && crypto == NULL) {
366 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
367 				N_("Checksum type %s is keyed but no "
368 				   "crypto context (key) was passed in", ""),
369 				ct->name);
370 	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
371     }
372     if(keyed_checksum) {
373 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
374 	if (ret)
375 	    return ret;
376     } else
377 	dkey = NULL;
378     result->cksumtype = ct->type;
379     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
380     if (ret)
381 	return (ret);
382     return (*ct->checksum)(context, dkey, data, len, usage, result);
383 }
384 
385 static int
arcfour_checksum_p(struct _krb5_checksum_type * ct,krb5_crypto crypto)386 arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
387 {
388     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
389 	(crypto->key.key->keytype == KEYTYPE_ARCFOUR);
390 }
391 
392 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_create_checksum(krb5_context context,krb5_crypto crypto,krb5_key_usage usage,int type,void * data,size_t len,Checksum * result)393 krb5_create_checksum(krb5_context context,
394 		     krb5_crypto crypto,
395 		     krb5_key_usage usage,
396 		     int type,
397 		     void *data,
398 		     size_t len,
399 		     Checksum *result)
400 {
401     struct _krb5_checksum_type *ct = NULL;
402     unsigned keyusage;
403 
404     /* type 0 -> pick from crypto */
405     if (type) {
406 	ct = _krb5_find_checksum(type);
407     } else if (crypto) {
408 	ct = crypto->et->keyed_checksum;
409 	if (ct == NULL)
410 	    ct = crypto->et->checksum;
411     }
412 
413     if(ct == NULL) {
414 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
415 				N_("checksum type %d not supported", ""),
416 				type);
417 	return KRB5_PROG_SUMTYPE_NOSUPP;
418     }
419 
420     if (arcfour_checksum_p(ct, crypto)) {
421 	keyusage = usage;
422 	_krb5_usage2arcfour(context, &keyusage);
423     } else
424 	keyusage = CHECKSUM_USAGE(usage);
425 
426     return create_checksum(context, ct, crypto, keyusage,
427 			   data, len, result);
428 }
429 
430 static krb5_error_code
verify_checksum(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,Checksum * cksum)431 verify_checksum(krb5_context context,
432 		krb5_crypto crypto,
433 		unsigned usage, /* not krb5_key_usage */
434 		void *data,
435 		size_t len,
436 		Checksum *cksum)
437 {
438     krb5_error_code ret;
439     struct _krb5_key_data *dkey;
440     int keyed_checksum;
441     Checksum c;
442     struct _krb5_checksum_type *ct;
443 
444     ct = _krb5_find_checksum(cksum->cksumtype);
445     if (ct == NULL || (ct->flags & F_DISABLED)) {
446 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
447 				N_("checksum type %d not supported", ""),
448 				cksum->cksumtype);
449 	return KRB5_PROG_SUMTYPE_NOSUPP;
450     }
451     if(ct->checksumsize != cksum->checksum.length) {
452 	krb5_clear_error_message (context);
453 	krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
454 			       N_("Decrypt integrity check failed for checksum type %s, "
455 				  "length was %u, expected %u", ""),
456 			       ct->name, (unsigned)cksum->checksum.length,
457 			       (unsigned)ct->checksumsize);
458 
459 	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
460     }
461     keyed_checksum = (ct->flags & F_KEYED) != 0;
462     if(keyed_checksum) {
463 	struct _krb5_checksum_type *kct;
464 	if (crypto == NULL) {
465 	    krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
466 				   N_("Checksum type %s is keyed but no "
467 				      "crypto context (key) was passed in", ""),
468 				   ct->name);
469 	    return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
470 	}
471 	kct = crypto->et->keyed_checksum;
472 	if (kct == NULL || kct->type != ct->type) {
473 	    krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
474 				   N_("Checksum type %s is keyed, but "
475 				      "the key type %s passed didnt have that checksum "
476 				      "type as the keyed type", ""),
477 				    ct->name, crypto->et->name);
478 	    return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
479 	}
480 
481 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
482 	if (ret)
483 	    return ret;
484     } else
485 	dkey = NULL;
486 
487     /*
488      * If checksum have a verify function, lets use that instead of
489      * calling ->checksum and then compare result.
490      */
491 
492     if(ct->verify) {
493 	ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
494 	if (ret)
495 	    krb5_set_error_message(context, ret,
496 				   N_("Decrypt integrity check failed for checksum "
497 				      "type %s, key type %s", ""),
498 				   ct->name, (crypto != NULL)? crypto->et->name : "(none)");
499 	return ret;
500     }
501 
502     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
503     if (ret)
504 	return ret;
505 
506     ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
507     if (ret) {
508 	krb5_data_free(&c.checksum);
509 	return ret;
510     }
511 
512     if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
513 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
514 	krb5_set_error_message(context, ret,
515 			       N_("Decrypt integrity check failed for checksum "
516 				  "type %s, key type %s", ""),
517 			       ct->name, crypto ? crypto->et->name : "(unkeyed)");
518     } else {
519 	ret = 0;
520     }
521     krb5_data_free (&c.checksum);
522     return ret;
523 }
524 
525 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_checksum(krb5_context context,krb5_crypto crypto,krb5_key_usage usage,void * data,size_t len,Checksum * cksum)526 krb5_verify_checksum(krb5_context context,
527 		     krb5_crypto crypto,
528 		     krb5_key_usage usage,
529 		     void *data,
530 		     size_t len,
531 		     Checksum *cksum)
532 {
533     struct _krb5_checksum_type *ct;
534     unsigned keyusage;
535 
536     ct = _krb5_find_checksum(cksum->cksumtype);
537     if(ct == NULL) {
538 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
539 				N_("checksum type %d not supported", ""),
540 				cksum->cksumtype);
541 	return KRB5_PROG_SUMTYPE_NOSUPP;
542     }
543 
544     if (arcfour_checksum_p(ct, crypto)) {
545 	keyusage = usage;
546 	_krb5_usage2arcfour(context, &keyusage);
547     } else
548 	keyusage = CHECKSUM_USAGE(usage);
549 
550     return verify_checksum(context, crypto, keyusage,
551 			   data, len, cksum);
552 }
553 
554 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_get_checksum_type(krb5_context context,krb5_crypto crypto,krb5_cksumtype * type)555 krb5_crypto_get_checksum_type(krb5_context context,
556                               krb5_crypto crypto,
557 			      krb5_cksumtype *type)
558 {
559     struct _krb5_checksum_type *ct = NULL;
560 
561     if (crypto != NULL) {
562         ct = crypto->et->keyed_checksum;
563         if (ct == NULL)
564             ct = crypto->et->checksum;
565     }
566 
567     if (ct == NULL) {
568 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
569 				N_("checksum type not found", ""));
570         return KRB5_PROG_SUMTYPE_NOSUPP;
571     }
572 
573     *type = ct->type;
574 
575     return 0;
576 }
577 
578 
579 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksumsize(krb5_context context,krb5_cksumtype type,size_t * size)580 krb5_checksumsize(krb5_context context,
581 		  krb5_cksumtype type,
582 		  size_t *size)
583 {
584     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
585     if(ct == NULL) {
586 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
587 				N_("checksum type %d not supported", ""),
588 				type);
589 	return KRB5_PROG_SUMTYPE_NOSUPP;
590     }
591     *size = ct->checksumsize;
592     return 0;
593 }
594 
595 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_keyed(krb5_context context,krb5_cksumtype type)596 krb5_checksum_is_keyed(krb5_context context,
597 		       krb5_cksumtype type)
598 {
599     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
600     if(ct == NULL) {
601 	if (context)
602 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
603 				    N_("checksum type %d not supported", ""),
604 				    type);
605 	return KRB5_PROG_SUMTYPE_NOSUPP;
606     }
607     return ct->flags & F_KEYED;
608 }
609 
610 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_checksum_is_collision_proof(krb5_context context,krb5_cksumtype type)611 krb5_checksum_is_collision_proof(krb5_context context,
612 				 krb5_cksumtype type)
613 {
614     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
615     if(ct == NULL) {
616 	if (context)
617 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
618 				    N_("checksum type %d not supported", ""),
619 				    type);
620 	return KRB5_PROG_SUMTYPE_NOSUPP;
621     }
622     return ct->flags & F_CPROOF;
623 }
624 
625 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_checksum_disable(krb5_context context,krb5_cksumtype type)626 krb5_checksum_disable(krb5_context context,
627 		      krb5_cksumtype type)
628 {
629     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
630     if(ct == NULL) {
631 	if (context)
632 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
633 				    N_("checksum type %d not supported", ""),
634 				    type);
635 	return KRB5_PROG_SUMTYPE_NOSUPP;
636     }
637     ct->flags |= F_DISABLED;
638     return 0;
639 }
640 
641 /************************************************************
642  *                                                          *
643  ************************************************************/
644 
645 struct _krb5_encryption_type *
_krb5_find_enctype(krb5_enctype type)646 _krb5_find_enctype(krb5_enctype type)
647 {
648     int i;
649     for(i = 0; i < _krb5_num_etypes; i++)
650 	if(_krb5_etypes[i]->type == type)
651 	    return _krb5_etypes[i];
652     return NULL;
653 }
654 
655 
656 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_string(krb5_context context,krb5_enctype etype,char ** string)657 krb5_enctype_to_string(krb5_context context,
658 		       krb5_enctype etype,
659 		       char **string)
660 {
661     struct _krb5_encryption_type *e;
662     e = _krb5_find_enctype(etype);
663     if(e == NULL) {
664 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
665 				N_("encryption type %d not supported", ""),
666 				etype);
667 	*string = NULL;
668 	return KRB5_PROG_ETYPE_NOSUPP;
669     }
670     *string = strdup(e->name);
671     if(*string == NULL) {
672 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
673 	return ENOMEM;
674     }
675     return 0;
676 }
677 
678 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_enctype(krb5_context context,const char * string,krb5_enctype * etype)679 krb5_string_to_enctype(krb5_context context,
680 		       const char *string,
681 		       krb5_enctype *etype)
682 {
683     int i;
684     for(i = 0; i < _krb5_num_etypes; i++)
685 	if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
686 	    *etype = _krb5_etypes[i]->type;
687 	    return 0;
688 	}
689     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
690 			    N_("encryption type %s not supported", ""),
691 			    string);
692     return KRB5_PROG_ETYPE_NOSUPP;
693 }
694 
695 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_to_keytype(krb5_context context,krb5_enctype etype,krb5_keytype * keytype)696 krb5_enctype_to_keytype(krb5_context context,
697 			krb5_enctype etype,
698 			krb5_keytype *keytype)
699 {
700     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
701     if(e == NULL) {
702         return unsupported_enctype (context, etype);
703     }
704     *keytype = e->keytype->type; /* XXX */
705     return 0;
706 }
707 
708 /**
709  * Check if a enctype is valid, return 0 if it is.
710  *
711  * @param context Kerberos context
712  * @param etype enctype to check if its valid or not
713  *
714  * @return Return an error code for an failure or 0 on success (enctype valid).
715  * @ingroup krb5_crypto
716  */
717 
718 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_valid(krb5_context context,krb5_enctype etype)719 krb5_enctype_valid(krb5_context context,
720 		   krb5_enctype etype)
721 {
722     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
723     if(e && (e->flags & F_DISABLED) == 0)
724 	return 0;
725     if (context == NULL)
726 	return KRB5_PROG_ETYPE_NOSUPP;
727     if(e == NULL) {
728         return unsupported_enctype (context, etype);
729     }
730     /* Must be (e->flags & F_DISABLED) */
731     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
732 			    N_("encryption type %s is disabled", ""),
733 			    e->name);
734     return KRB5_PROG_ETYPE_NOSUPP;
735 }
736 
737 /**
738  * Return the coresponding encryption type for a checksum type.
739  *
740  * @param context Kerberos context
741  * @param ctype The checksum type to get the result enctype for
742  * @param etype The returned encryption, when the matching etype is
743  * not found, etype is set to ETYPE_NULL.
744  *
745  * @return Return an error code for an failure or 0 on success.
746  * @ingroup krb5_crypto
747  */
748 
749 
750 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_to_enctype(krb5_context context,krb5_cksumtype ctype,krb5_enctype * etype)751 krb5_cksumtype_to_enctype(krb5_context context,
752 			  krb5_cksumtype ctype,
753 			  krb5_enctype *etype)
754 {
755     int i;
756 
757     *etype = ETYPE_NULL;
758 
759     for(i = 0; i < _krb5_num_etypes; i++) {
760 	if(_krb5_etypes[i]->keyed_checksum &&
761 	   _krb5_etypes[i]->keyed_checksum->type == ctype)
762 	    {
763 		*etype = _krb5_etypes[i]->type;
764 		return 0;
765 	    }
766     }
767 
768     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
769 			    N_("checksum type %d not supported", ""),
770 			    (int)ctype);
771     return KRB5_PROG_SUMTYPE_NOSUPP;
772 }
773 
774 
775 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_cksumtype_valid(krb5_context context,krb5_cksumtype ctype)776 krb5_cksumtype_valid(krb5_context context,
777 		     krb5_cksumtype ctype)
778 {
779     struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
780     if (c == NULL) {
781 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
782 				N_("checksum type %d not supported", ""),
783 				ctype);
784 	return KRB5_PROG_SUMTYPE_NOSUPP;
785     }
786     if (c->flags & F_DISABLED) {
787 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
788 				N_("checksum type %s is disabled", ""),
789 				c->name);
790 	return KRB5_PROG_SUMTYPE_NOSUPP;
791     }
792     return 0;
793 }
794 
795 
796 static krb5_boolean
derived_crypto(krb5_context context,krb5_crypto crypto)797 derived_crypto(krb5_context context,
798 	       krb5_crypto crypto)
799 {
800     return (crypto->et->flags & F_DERIVED) != 0;
801 }
802 
803 static krb5_boolean
special_crypto(krb5_context context,krb5_crypto crypto)804 special_crypto(krb5_context context,
805 	       krb5_crypto crypto)
806 {
807     return (crypto->et->flags & F_SPECIAL) != 0;
808 }
809 
810 #define CHECKSUMSIZE(C) ((C)->checksumsize)
811 #define CHECKSUMTYPE(C) ((C)->type)
812 
813 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)814 encrypt_internal_derived(krb5_context context,
815 			 krb5_crypto crypto,
816 			 unsigned usage,
817 			 const void *data,
818 			 size_t len,
819 			 krb5_data *result,
820 			 void *ivec)
821 {
822     size_t sz, block_sz, checksum_sz, total_sz;
823     Checksum cksum;
824     unsigned char *p, *q;
825     krb5_error_code ret;
826     struct _krb5_key_data *dkey;
827     const struct _krb5_encryption_type *et = crypto->et;
828 
829     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
830 
831     sz = et->confoundersize + len;
832     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
833     total_sz = block_sz + checksum_sz;
834     p = calloc(1, total_sz);
835     if(p == NULL) {
836 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
837 	return ENOMEM;
838     }
839 
840     q = p;
841     krb5_generate_random_block(q, et->confoundersize); /* XXX */
842     q += et->confoundersize;
843     memcpy(q, data, len);
844 
845     ret = create_checksum(context,
846 			  et->keyed_checksum,
847 			  crypto,
848 			  INTEGRITY_USAGE(usage),
849 			  p,
850 			  block_sz,
851 			  &cksum);
852     if(ret == 0 && cksum.checksum.length != checksum_sz) {
853 	free_Checksum (&cksum);
854 	krb5_clear_error_message (context);
855 	ret = KRB5_CRYPTO_INTERNAL;
856     }
857     if(ret)
858 	goto fail;
859     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
860     free_Checksum (&cksum);
861     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
862     if(ret)
863 	goto fail;
864     ret = _key_schedule(context, dkey);
865     if(ret)
866 	goto fail;
867     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
868     if (ret)
869 	goto fail;
870     result->data = p;
871     result->length = total_sz;
872     return 0;
873  fail:
874     memset(p, 0, total_sz);
875     free(p);
876     return ret;
877 }
878 
879 
880 static krb5_error_code
encrypt_internal(krb5_context context,krb5_crypto crypto,const void * data,size_t len,krb5_data * result,void * ivec)881 encrypt_internal(krb5_context context,
882 		 krb5_crypto crypto,
883 		 const void *data,
884 		 size_t len,
885 		 krb5_data *result,
886 		 void *ivec)
887 {
888     size_t sz, block_sz, checksum_sz;
889     Checksum cksum;
890     unsigned char *p, *q;
891     krb5_error_code ret;
892     const struct _krb5_encryption_type *et = crypto->et;
893 
894     checksum_sz = CHECKSUMSIZE(et->checksum);
895 
896     sz = et->confoundersize + checksum_sz + len;
897     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
898     p = calloc(1, block_sz);
899     if(p == NULL) {
900 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
901 	return ENOMEM;
902     }
903 
904     q = p;
905     krb5_generate_random_block(q, et->confoundersize); /* XXX */
906     q += et->confoundersize;
907     memset(q, 0, checksum_sz);
908     q += checksum_sz;
909     memcpy(q, data, len);
910 
911     ret = create_checksum(context,
912 			  et->checksum,
913 			  crypto,
914 			  0,
915 			  p,
916 			  block_sz,
917 			  &cksum);
918     if(ret == 0 && cksum.checksum.length != checksum_sz) {
919 	krb5_clear_error_message (context);
920 	free_Checksum(&cksum);
921 	ret = KRB5_CRYPTO_INTERNAL;
922     }
923     if(ret)
924 	goto fail;
925     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
926     free_Checksum(&cksum);
927     ret = _key_schedule(context, &crypto->key);
928     if(ret)
929 	goto fail;
930     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
931     if (ret) {
932 	memset(p, 0, block_sz);
933 	free(p);
934 	return ret;
935     }
936     result->data = p;
937     result->length = block_sz;
938     return 0;
939  fail:
940     memset(p, 0, block_sz);
941     free(p);
942     return ret;
943 }
944 
945 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)946 encrypt_internal_special(krb5_context context,
947 			 krb5_crypto crypto,
948 			 int usage,
949 			 const void *data,
950 			 size_t len,
951 			 krb5_data *result,
952 			 void *ivec)
953 {
954     struct _krb5_encryption_type *et = crypto->et;
955     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
956     size_t sz = len + cksum_sz + et->confoundersize;
957     char *tmp, *p;
958     krb5_error_code ret;
959 
960     tmp = malloc (sz);
961     if (tmp == NULL) {
962 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
963 	return ENOMEM;
964     }
965     p = tmp;
966     memset (p, 0, cksum_sz);
967     p += cksum_sz;
968     krb5_generate_random_block(p, et->confoundersize);
969     p += et->confoundersize;
970     memcpy (p, data, len);
971     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
972     if (ret) {
973 	memset(tmp, 0, sz);
974 	free(tmp);
975 	return ret;
976     }
977     result->data   = tmp;
978     result->length = sz;
979     return 0;
980 }
981 
982 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)983 decrypt_internal_derived(krb5_context context,
984 			 krb5_crypto crypto,
985 			 unsigned usage,
986 			 void *data,
987 			 size_t len,
988 			 krb5_data *result,
989 			 void *ivec)
990 {
991     size_t checksum_sz;
992     Checksum cksum;
993     unsigned char *p;
994     krb5_error_code ret;
995     struct _krb5_key_data *dkey;
996     struct _krb5_encryption_type *et = crypto->et;
997     unsigned long l;
998 
999     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1000     if (len < checksum_sz + et->confoundersize) {
1001 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1002 			       N_("Encrypted data shorter then "
1003 				  "checksum + confunder", ""));
1004 	return KRB5_BAD_MSIZE;
1005     }
1006 
1007     if (((len - checksum_sz) % et->padsize) != 0) {
1008 	krb5_clear_error_message(context);
1009 	return KRB5_BAD_MSIZE;
1010     }
1011 
1012     p = malloc(len);
1013     if(len != 0 && p == NULL) {
1014 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1015 	return ENOMEM;
1016     }
1017     memcpy(p, data, len);
1018 
1019     len -= checksum_sz;
1020 
1021     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1022     if(ret) {
1023 	free(p);
1024 	return ret;
1025     }
1026     ret = _key_schedule(context, dkey);
1027     if(ret) {
1028 	free(p);
1029 	return ret;
1030     }
1031     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1032     if (ret) {
1033 	free(p);
1034 	return ret;
1035     }
1036 
1037     cksum.checksum.data   = p + len;
1038     cksum.checksum.length = checksum_sz;
1039     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
1040 
1041     ret = verify_checksum(context,
1042 			  crypto,
1043 			  INTEGRITY_USAGE(usage),
1044 			  p,
1045 			  len,
1046 			  &cksum);
1047     if(ret) {
1048 	free(p);
1049 	return ret;
1050     }
1051     l = len - et->confoundersize;
1052     memmove(p, p + et->confoundersize, l);
1053     result->data = realloc(p, l);
1054     if(result->data == NULL && l != 0) {
1055 	free(p);
1056 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1057 	return ENOMEM;
1058     }
1059     result->length = l;
1060     return 0;
1061 }
1062 
1063 static krb5_error_code
decrypt_internal(krb5_context context,krb5_crypto crypto,void * data,size_t len,krb5_data * result,void * ivec)1064 decrypt_internal(krb5_context context,
1065 		 krb5_crypto crypto,
1066 		 void *data,
1067 		 size_t len,
1068 		 krb5_data *result,
1069 		 void *ivec)
1070 {
1071     krb5_error_code ret;
1072     unsigned char *p;
1073     Checksum cksum;
1074     size_t checksum_sz, l;
1075     struct _krb5_encryption_type *et = crypto->et;
1076 
1077     if ((len % et->padsize) != 0) {
1078 	krb5_clear_error_message(context);
1079 	return KRB5_BAD_MSIZE;
1080     }
1081     checksum_sz = CHECKSUMSIZE(et->checksum);
1082     if (len < checksum_sz + et->confoundersize) {
1083 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1084 			       N_("Encrypted data shorter then "
1085 				  "checksum + confunder", ""));
1086 	return KRB5_BAD_MSIZE;
1087     }
1088 
1089     p = malloc(len);
1090     if(len != 0 && p == NULL) {
1091 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1092 	return ENOMEM;
1093     }
1094     memcpy(p, data, len);
1095 
1096     ret = _key_schedule(context, &crypto->key);
1097     if(ret) {
1098 	free(p);
1099 	return ret;
1100     }
1101     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1102     if (ret) {
1103 	free(p);
1104 	return ret;
1105     }
1106     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1107     if(ret) {
1108  	free(p);
1109  	return ret;
1110     }
1111     memset(p + et->confoundersize, 0, checksum_sz);
1112     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1113     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1114     free_Checksum(&cksum);
1115     if(ret) {
1116 	free(p);
1117 	return ret;
1118     }
1119     l = len - et->confoundersize - checksum_sz;
1120     memmove(p, p + et->confoundersize + checksum_sz, l);
1121     result->data = realloc(p, l);
1122     if(result->data == NULL && l != 0) {
1123 	free(p);
1124 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1125 	return ENOMEM;
1126     }
1127     result->length = l;
1128     return 0;
1129 }
1130 
1131 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)1132 decrypt_internal_special(krb5_context context,
1133 			 krb5_crypto crypto,
1134 			 int usage,
1135 			 void *data,
1136 			 size_t len,
1137 			 krb5_data *result,
1138 			 void *ivec)
1139 {
1140     struct _krb5_encryption_type *et = crypto->et;
1141     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1142     size_t sz = len - cksum_sz - et->confoundersize;
1143     unsigned char *p;
1144     krb5_error_code ret;
1145 
1146     if ((len % et->padsize) != 0) {
1147 	krb5_clear_error_message(context);
1148 	return KRB5_BAD_MSIZE;
1149     }
1150     if (len < cksum_sz + et->confoundersize) {
1151 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1152 			       N_("Encrypted data shorter then "
1153 				  "checksum + confunder", ""));
1154 	return KRB5_BAD_MSIZE;
1155     }
1156 
1157     p = malloc (len);
1158     if (p == NULL) {
1159 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1160 	return ENOMEM;
1161     }
1162     memcpy(p, data, len);
1163 
1164     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1165     if (ret) {
1166 	free(p);
1167 	return ret;
1168     }
1169 
1170     memmove (p, p + cksum_sz + et->confoundersize, sz);
1171     result->data = realloc(p, sz);
1172     if(result->data == NULL && sz != 0) {
1173 	free(p);
1174 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1175 	return ENOMEM;
1176     }
1177     result->length = sz;
1178     return 0;
1179 }
1180 
1181 static krb5_crypto_iov *
find_iv(krb5_crypto_iov * data,size_t num_data,unsigned type)1182 find_iv(krb5_crypto_iov *data, size_t num_data, unsigned type)
1183 {
1184     size_t i;
1185     for (i = 0; i < num_data; i++)
1186 	if (data[i].flags == type)
1187 	    return &data[i];
1188     return NULL;
1189 }
1190 
1191 /**
1192  * Inline encrypt a kerberos message
1193  *
1194  * @param context Kerberos context
1195  * @param crypto Kerberos crypto context
1196  * @param usage Key usage for this buffer
1197  * @param data array of buffers to process
1198  * @param num_data length of array
1199  * @param ivec initial cbc/cts vector
1200  *
1201  * @return Return an error code or 0.
1202  * @ingroup krb5_crypto
1203  *
1204  * Kerberos encrypted data look like this:
1205  *
1206  * 1. KRB5_CRYPTO_TYPE_HEADER
1207  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1208  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1209  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1210  *    commonly used headers and trailers.
1211  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1212  * 4. KRB5_CRYPTO_TYPE_TRAILER
1213  */
1214 
1215 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_iov_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,int num_data,void * ivec)1216 krb5_encrypt_iov_ivec(krb5_context context,
1217 		      krb5_crypto crypto,
1218 		      unsigned usage,
1219 		      krb5_crypto_iov *data,
1220 		      int num_data,
1221 		      void *ivec)
1222 {
1223     size_t headersz, trailersz, len;
1224     int i;
1225     size_t sz, block_sz, pad_sz;
1226     Checksum cksum;
1227     unsigned char *p, *q;
1228     krb5_error_code ret;
1229     struct _krb5_key_data *dkey;
1230     const struct _krb5_encryption_type *et = crypto->et;
1231     krb5_crypto_iov *tiv, *piv, *hiv;
1232 
1233     if (num_data < 0) {
1234         krb5_clear_error_message(context);
1235 	return KRB5_CRYPTO_INTERNAL;
1236     }
1237 
1238     if(!derived_crypto(context, crypto)) {
1239 	krb5_clear_error_message(context);
1240 	return KRB5_CRYPTO_INTERNAL;
1241     }
1242 
1243     headersz = et->confoundersize;
1244     trailersz = CHECKSUMSIZE(et->keyed_checksum);
1245 
1246     for (len = 0, i = 0; i < num_data; i++) {
1247 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1248 	    continue;
1249 	len += data[i].data.length;
1250     }
1251 
1252     sz = headersz + len;
1253     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1254 
1255     pad_sz = block_sz - sz;
1256 
1257     /* header */
1258 
1259     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1260     if (hiv == NULL || hiv->data.length != headersz)
1261 	return KRB5_BAD_MSIZE;
1262 
1263     krb5_generate_random_block(hiv->data.data, hiv->data.length);
1264 
1265     /* padding */
1266     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1267     /* its ok to have no TYPE_PADDING if there is no padding */
1268     if (piv == NULL && pad_sz != 0)
1269 	return KRB5_BAD_MSIZE;
1270     if (piv) {
1271 	if (piv->data.length < pad_sz)
1272 	    return KRB5_BAD_MSIZE;
1273 	piv->data.length = pad_sz;
1274 	if (pad_sz)
1275 	    memset(piv->data.data, pad_sz, pad_sz);
1276 	else
1277 	    piv = NULL;
1278     }
1279 
1280     /* trailer */
1281     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1282     if (tiv == NULL || tiv->data.length != trailersz)
1283 	return KRB5_BAD_MSIZE;
1284 
1285     /*
1286      * XXX replace with EVP_Sign? at least make create_checksum an iov
1287      * function.
1288      * XXX CTS EVP is broken, can't handle multi buffers :(
1289      */
1290 
1291     len = block_sz;
1292     for (i = 0; i < num_data; i++) {
1293 	if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1294 	    continue;
1295 	len += data[i].data.length;
1296     }
1297 
1298     p = q = malloc(len);
1299 
1300     memcpy(q, hiv->data.data, hiv->data.length);
1301     q += hiv->data.length;
1302     for (i = 0; i < num_data; i++) {
1303 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1304 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1305 	    continue;
1306 	memcpy(q, data[i].data.data, data[i].data.length);
1307 	q += data[i].data.length;
1308     }
1309     if (piv)
1310 	memset(q, 0, piv->data.length);
1311 
1312     ret = create_checksum(context,
1313 			  et->keyed_checksum,
1314 			  crypto,
1315 			  INTEGRITY_USAGE(usage),
1316 			  p,
1317 			  len,
1318 			  &cksum);
1319     free(p);
1320     if(ret == 0 && cksum.checksum.length != trailersz) {
1321 	free_Checksum (&cksum);
1322 	krb5_clear_error_message (context);
1323 	ret = KRB5_CRYPTO_INTERNAL;
1324     }
1325     if(ret)
1326 	return ret;
1327 
1328     /* save cksum at end */
1329     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1330     free_Checksum (&cksum);
1331 
1332     /* XXX replace with EVP_Cipher */
1333     p = q = malloc(block_sz);
1334     if(p == NULL)
1335 	return ENOMEM;
1336 
1337     memcpy(q, hiv->data.data, hiv->data.length);
1338     q += hiv->data.length;
1339 
1340     for (i = 0; i < num_data; i++) {
1341 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1342 	    continue;
1343 	memcpy(q, data[i].data.data, data[i].data.length);
1344 	q += data[i].data.length;
1345     }
1346     if (piv)
1347 	memset(q, 0, piv->data.length);
1348 
1349 
1350     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1351     if(ret) {
1352 	free(p);
1353 	return ret;
1354     }
1355     ret = _key_schedule(context, dkey);
1356     if(ret) {
1357 	free(p);
1358 	return ret;
1359     }
1360 
1361     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1362     if (ret) {
1363 	free(p);
1364 	return ret;
1365     }
1366 
1367     /* now copy data back to buffers */
1368     q = p;
1369 
1370     memcpy(hiv->data.data, q, hiv->data.length);
1371     q += hiv->data.length;
1372 
1373     for (i = 0; i < num_data; i++) {
1374 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1375 	    continue;
1376 	memcpy(data[i].data.data, q, data[i].data.length);
1377 	q += data[i].data.length;
1378     }
1379     if (piv)
1380 	memcpy(piv->data.data, q, pad_sz);
1381 
1382     free(p);
1383 
1384     return ret;
1385 }
1386 
1387 /**
1388  * Inline decrypt a Kerberos message.
1389  *
1390  * @param context Kerberos context
1391  * @param crypto Kerberos crypto context
1392  * @param usage Key usage for this buffer
1393  * @param data array of buffers to process
1394  * @param num_data length of array
1395  * @param ivec initial cbc/cts vector
1396  *
1397  * @return Return an error code or 0.
1398  * @ingroup krb5_crypto
1399  *
1400  * 1. KRB5_CRYPTO_TYPE_HEADER
1401  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1402  *  any order, however the receiver have to aware of the
1403  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1404  *  protocol headers and trailers. The output data will be of same
1405  *  size as the input data or shorter.
1406  */
1407 
1408 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_iov_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,void * ivec)1409 krb5_decrypt_iov_ivec(krb5_context context,
1410 		      krb5_crypto crypto,
1411 		      unsigned usage,
1412 		      krb5_crypto_iov *data,
1413 		      unsigned int num_data,
1414 		      void *ivec)
1415 {
1416     unsigned int i;
1417     size_t headersz, trailersz, len;
1418     Checksum cksum;
1419     unsigned char *p, *q;
1420     krb5_error_code ret;
1421     struct _krb5_key_data *dkey;
1422     struct _krb5_encryption_type *et = crypto->et;
1423     krb5_crypto_iov *tiv, *hiv;
1424 
1425     if(!derived_crypto(context, crypto)) {
1426 	krb5_clear_error_message(context);
1427 	return KRB5_CRYPTO_INTERNAL;
1428     }
1429 
1430     headersz = et->confoundersize;
1431 
1432     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1433     if (hiv == NULL || hiv->data.length != headersz)
1434 	return KRB5_BAD_MSIZE;
1435 
1436     /* trailer */
1437     trailersz = CHECKSUMSIZE(et->keyed_checksum);
1438 
1439     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1440     if (tiv->data.length != trailersz)
1441 	return KRB5_BAD_MSIZE;
1442 
1443     /* Find length of data we will decrypt */
1444 
1445     len = headersz;
1446     for (i = 0; i < num_data; i++) {
1447 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1448 	    continue;
1449 	len += data[i].data.length;
1450     }
1451 
1452     if ((len % et->padsize) != 0) {
1453 	krb5_clear_error_message(context);
1454 	return KRB5_BAD_MSIZE;
1455     }
1456 
1457     /* XXX replace with EVP_Cipher */
1458 
1459     p = q = malloc(len);
1460     if (p == NULL)
1461 	return ENOMEM;
1462 
1463     memcpy(q, hiv->data.data, hiv->data.length);
1464     q += hiv->data.length;
1465 
1466     for (i = 0; i < num_data; i++) {
1467 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1468 	    continue;
1469 	memcpy(q, data[i].data.data, data[i].data.length);
1470 	q += data[i].data.length;
1471     }
1472 
1473     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1474     if(ret) {
1475 	free(p);
1476 	return ret;
1477     }
1478     ret = _key_schedule(context, dkey);
1479     if(ret) {
1480 	free(p);
1481 	return ret;
1482     }
1483 
1484     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1485     if (ret) {
1486 	free(p);
1487 	return ret;
1488     }
1489 
1490     /* copy data back to buffers */
1491     memcpy(hiv->data.data, p, hiv->data.length);
1492     q = p + hiv->data.length;
1493     for (i = 0; i < num_data; i++) {
1494 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1495 	    continue;
1496 	memcpy(data[i].data.data, q, data[i].data.length);
1497 	q += data[i].data.length;
1498     }
1499 
1500     free(p);
1501 
1502     /* check signature */
1503     for (i = 0; i < num_data; i++) {
1504 	if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1505 	    continue;
1506 	len += data[i].data.length;
1507     }
1508 
1509     p = q = malloc(len);
1510     if (p == NULL)
1511 	return ENOMEM;
1512 
1513     memcpy(q, hiv->data.data, hiv->data.length);
1514     q += hiv->data.length;
1515     for (i = 0; i < num_data; i++) {
1516 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1517 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1518 	    continue;
1519 	memcpy(q, data[i].data.data, data[i].data.length);
1520 	q += data[i].data.length;
1521     }
1522 
1523     cksum.checksum.data   = tiv->data.data;
1524     cksum.checksum.length = tiv->data.length;
1525     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
1526 
1527     ret = verify_checksum(context,
1528 			  crypto,
1529 			  INTEGRITY_USAGE(usage),
1530 			  p,
1531 			  len,
1532 			  &cksum);
1533     free(p);
1534     return ret;
1535 }
1536 
1537 /**
1538  * Create a Kerberos message checksum.
1539  *
1540  * @param context Kerberos context
1541  * @param crypto Kerberos crypto context
1542  * @param usage Key usage for this buffer
1543  * @param data array of buffers to process
1544  * @param num_data length of array
1545  * @param type output data
1546  *
1547  * @return Return an error code or 0.
1548  * @ingroup krb5_crypto
1549  */
1550 
1551 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_create_checksum_iov(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,krb5_cksumtype * type)1552 krb5_create_checksum_iov(krb5_context context,
1553 			 krb5_crypto crypto,
1554 			 unsigned usage,
1555 			 krb5_crypto_iov *data,
1556 			 unsigned int num_data,
1557 			 krb5_cksumtype *type)
1558 {
1559     Checksum cksum;
1560     krb5_crypto_iov *civ;
1561     krb5_error_code ret;
1562     size_t i;
1563     size_t len;
1564     char *p, *q;
1565 
1566     if(!derived_crypto(context, crypto)) {
1567 	krb5_clear_error_message(context);
1568 	return KRB5_CRYPTO_INTERNAL;
1569     }
1570 
1571     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1572     if (civ == NULL)
1573 	return KRB5_BAD_MSIZE;
1574 
1575     len = 0;
1576     for (i = 0; i < num_data; i++) {
1577 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1578 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1579 	    continue;
1580 	len += data[i].data.length;
1581     }
1582 
1583     p = q = malloc(len);
1584 
1585     for (i = 0; i < num_data; i++) {
1586 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1587 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1588 	    continue;
1589 	memcpy(q, data[i].data.data, data[i].data.length);
1590 	q += data[i].data.length;
1591     }
1592 
1593     ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
1594     free(p);
1595     if (ret)
1596 	return ret;
1597 
1598     if (type)
1599 	*type = cksum.cksumtype;
1600 
1601     if (cksum.checksum.length > civ->data.length) {
1602 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1603 			       N_("Checksum larger then input buffer", ""));
1604 	free_Checksum(&cksum);
1605 	return KRB5_BAD_MSIZE;
1606     }
1607 
1608     civ->data.length = cksum.checksum.length;
1609     memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
1610     free_Checksum(&cksum);
1611 
1612     return 0;
1613 }
1614 
1615 /**
1616  * Verify a Kerberos message checksum.
1617  *
1618  * @param context Kerberos context
1619  * @param crypto Kerberos crypto context
1620  * @param usage Key usage for this buffer
1621  * @param data array of buffers to process
1622  * @param num_data length of array
1623  * @param type return checksum type if not NULL
1624  *
1625  * @return Return an error code or 0.
1626  * @ingroup krb5_crypto
1627  */
1628 
1629 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_verify_checksum_iov(krb5_context context,krb5_crypto crypto,unsigned usage,krb5_crypto_iov * data,unsigned int num_data,krb5_cksumtype * type)1630 krb5_verify_checksum_iov(krb5_context context,
1631 			 krb5_crypto crypto,
1632 			 unsigned usage,
1633 			 krb5_crypto_iov *data,
1634 			 unsigned int num_data,
1635 			 krb5_cksumtype *type)
1636 {
1637     struct _krb5_encryption_type *et = crypto->et;
1638     Checksum cksum;
1639     krb5_crypto_iov *civ;
1640     krb5_error_code ret;
1641     size_t i;
1642     size_t len;
1643     char *p, *q;
1644 
1645     if(!derived_crypto(context, crypto)) {
1646 	krb5_clear_error_message(context);
1647 	return KRB5_CRYPTO_INTERNAL;
1648     }
1649 
1650     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1651     if (civ == NULL)
1652 	return KRB5_BAD_MSIZE;
1653 
1654     len = 0;
1655     for (i = 0; i < num_data; i++) {
1656 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1657 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1658 	    continue;
1659 	len += data[i].data.length;
1660     }
1661 
1662     p = q = malloc(len);
1663 
1664     for (i = 0; i < num_data; i++) {
1665 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1666 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1667 	    continue;
1668 	memcpy(q, data[i].data.data, data[i].data.length);
1669 	q += data[i].data.length;
1670     }
1671 
1672     cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1673     cksum.checksum.length = civ->data.length;
1674     cksum.checksum.data = civ->data.data;
1675 
1676     ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
1677     free(p);
1678 
1679     if (ret == 0 && type)
1680 	*type = cksum.cksumtype;
1681 
1682     return ret;
1683 }
1684 
1685 
1686 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_length(krb5_context context,krb5_crypto crypto,int type,size_t * len)1687 krb5_crypto_length(krb5_context context,
1688 		   krb5_crypto crypto,
1689 		   int type,
1690 		   size_t *len)
1691 {
1692     if (!derived_crypto(context, crypto)) {
1693 	krb5_set_error_message(context, EINVAL, "not a derived crypto");
1694 	return EINVAL;
1695     }
1696 
1697     switch(type) {
1698     case KRB5_CRYPTO_TYPE_EMPTY:
1699 	*len = 0;
1700 	return 0;
1701     case KRB5_CRYPTO_TYPE_HEADER:
1702 	*len = crypto->et->blocksize;
1703 	return 0;
1704     case KRB5_CRYPTO_TYPE_DATA:
1705     case KRB5_CRYPTO_TYPE_SIGN_ONLY:
1706 	/* len must already been filled in */
1707 	return 0;
1708     case KRB5_CRYPTO_TYPE_PADDING:
1709 	if (crypto->et->padsize > 1)
1710 	    *len = crypto->et->padsize;
1711 	else
1712 	    *len = 0;
1713 	return 0;
1714     case KRB5_CRYPTO_TYPE_TRAILER:
1715 	*len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1716 	return 0;
1717     case KRB5_CRYPTO_TYPE_CHECKSUM:
1718 	if (crypto->et->keyed_checksum)
1719 	    *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1720 	else
1721 	    *len = CHECKSUMSIZE(crypto->et->checksum);
1722 	return 0;
1723     }
1724     krb5_set_error_message(context, EINVAL,
1725 			   "%d not a supported type", type);
1726     return EINVAL;
1727 }
1728 
1729 
1730 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_length_iov(krb5_context context,krb5_crypto crypto,krb5_crypto_iov * data,unsigned int num_data)1731 krb5_crypto_length_iov(krb5_context context,
1732 		       krb5_crypto crypto,
1733 		       krb5_crypto_iov *data,
1734 		       unsigned int num_data)
1735 {
1736     krb5_error_code ret;
1737     size_t i;
1738 
1739     for (i = 0; i < num_data; i++) {
1740 	ret = krb5_crypto_length(context, crypto,
1741 				 data[i].flags,
1742 				 &data[i].data.length);
1743 	if (ret)
1744 	    return ret;
1745     }
1746     return 0;
1747 }
1748 
1749 
1750 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,const void * data,size_t len,krb5_data * result,void * ivec)1751 krb5_encrypt_ivec(krb5_context context,
1752 		  krb5_crypto crypto,
1753 		  unsigned usage,
1754 		  const void *data,
1755 		  size_t len,
1756 		  krb5_data *result,
1757 		  void *ivec)
1758 {
1759     if(derived_crypto(context, crypto))
1760 	return encrypt_internal_derived(context, crypto, usage,
1761 					data, len, result, ivec);
1762     else if (special_crypto(context, crypto))
1763 	return encrypt_internal_special (context, crypto, usage,
1764 					 data, len, result, ivec);
1765     else
1766 	return encrypt_internal(context, crypto, data, len, result, ivec);
1767 }
1768 
1769 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt(krb5_context context,krb5_crypto crypto,unsigned usage,const void * data,size_t len,krb5_data * result)1770 krb5_encrypt(krb5_context context,
1771 	     krb5_crypto crypto,
1772 	     unsigned usage,
1773 	     const void *data,
1774 	     size_t len,
1775 	     krb5_data *result)
1776 {
1777     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
1778 }
1779 
1780 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_encrypt_EncryptedData(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,int kvno,EncryptedData * result)1781 krb5_encrypt_EncryptedData(krb5_context context,
1782 			   krb5_crypto crypto,
1783 			   unsigned usage,
1784 			   void *data,
1785 			   size_t len,
1786 			   int kvno,
1787 			   EncryptedData *result)
1788 {
1789     result->etype = CRYPTO_ETYPE(crypto);
1790     if(kvno){
1791 	ALLOC(result->kvno, 1);
1792 	*result->kvno = kvno;
1793     }else
1794 	result->kvno = NULL;
1795     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1796 }
1797 
1798 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_ivec(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,krb5_data * result,void * ivec)1799 krb5_decrypt_ivec(krb5_context context,
1800 		  krb5_crypto crypto,
1801 		  unsigned usage,
1802 		  void *data,
1803 		  size_t len,
1804 		  krb5_data *result,
1805 		  void *ivec)
1806 {
1807     if(derived_crypto(context, crypto))
1808 	return decrypt_internal_derived(context, crypto, usage,
1809 					data, len, result, ivec);
1810     else if (special_crypto (context, crypto))
1811 	return decrypt_internal_special(context, crypto, usage,
1812 					data, len, result, ivec);
1813     else
1814 	return decrypt_internal(context, crypto, data, len, result, ivec);
1815 }
1816 
1817 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt(krb5_context context,krb5_crypto crypto,unsigned usage,void * data,size_t len,krb5_data * result)1818 krb5_decrypt(krb5_context context,
1819 	     krb5_crypto crypto,
1820 	     unsigned usage,
1821 	     void *data,
1822 	     size_t len,
1823 	     krb5_data *result)
1824 {
1825     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
1826 			      NULL);
1827 }
1828 
1829 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_decrypt_EncryptedData(krb5_context context,krb5_crypto crypto,unsigned usage,const EncryptedData * e,krb5_data * result)1830 krb5_decrypt_EncryptedData(krb5_context context,
1831 			   krb5_crypto crypto,
1832 			   unsigned usage,
1833 			   const EncryptedData *e,
1834 			   krb5_data *result)
1835 {
1836     return krb5_decrypt(context, crypto, usage,
1837 			e->cipher.data, e->cipher.length, result);
1838 }
1839 
1840 /************************************************************
1841  *                                                          *
1842  ************************************************************/
1843 
1844 krb5_error_code
_krb5_derive_key(krb5_context context,struct _krb5_encryption_type * et,struct _krb5_key_data * key,const void * constant,size_t len)1845 _krb5_derive_key(krb5_context context,
1846 		 struct _krb5_encryption_type *et,
1847 		 struct _krb5_key_data *key,
1848 		 const void *constant,
1849 		 size_t len)
1850 {
1851     unsigned char *k = NULL;
1852     unsigned int nblocks = 0, i;
1853     krb5_error_code ret = 0;
1854     struct _krb5_key_type *kt = et->keytype;
1855 
1856     ret = _key_schedule(context, key);
1857     if(ret)
1858 	return ret;
1859     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
1860 	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1861 	k = malloc(nblocks * et->blocksize);
1862 	if(k == NULL) {
1863 	    ret = ENOMEM;
1864 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1865 	    goto out;
1866 	}
1867 	ret = _krb5_n_fold(constant, len, k, et->blocksize);
1868 	if (ret) {
1869 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1870 	    goto out;
1871 	}
1872 
1873 	for(i = 0; i < nblocks; i++) {
1874 	    if(i > 0)
1875 		memcpy(k + i * et->blocksize,
1876 		       k + (i - 1) * et->blocksize,
1877 		       et->blocksize);
1878 	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
1879 			   1, 0, NULL);
1880 	}
1881     } else {
1882 	/* this case is probably broken, but won't be run anyway */
1883 	void *c = malloc(len);
1884 	size_t res_len = (kt->bits + 7) / 8;
1885 
1886 	if(len != 0 && c == NULL) {
1887 	    ret = ENOMEM;
1888 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1889 	    goto out;
1890 	}
1891 	memcpy(c, constant, len);
1892 	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
1893 	k = malloc(res_len);
1894 	if(res_len != 0 && k == NULL) {
1895 	    free(c);
1896 	    ret = ENOMEM;
1897 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1898 	    goto out;
1899 	}
1900 	ret = _krb5_n_fold(c, len, k, res_len);
1901 	free(c);
1902 	if (ret) {
1903 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1904 	    goto out;
1905 	}
1906     }
1907 
1908     /* XXX keytype dependent post-processing */
1909     switch(kt->type) {
1910     case ETYPE_OLD_DES3_CBC_SHA1:
1911 	_krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
1912 	break;
1913     case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
1914     case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
1915 	memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
1916 	break;
1917     default:
1918 	ret = KRB5_CRYPTO_INTERNAL;
1919 	krb5_set_error_message(context, ret,
1920 			       N_("derive_key() called with unknown keytype (%u)", ""),
1921 			       kt->type);
1922 	break;
1923     }
1924  out:
1925     if (key->schedule) {
1926 	free_key_schedule(context, key, et);
1927 	key->schedule = NULL;
1928     }
1929     if (k) {
1930 	memset(k, 0, nblocks * et->blocksize);
1931 	free(k);
1932     }
1933     return ret;
1934 }
1935 
1936 static struct _krb5_key_data *
_new_derived_key(krb5_crypto crypto,unsigned usage)1937 _new_derived_key(krb5_crypto crypto, unsigned usage)
1938 {
1939     struct _krb5_key_usage *d = crypto->key_usage;
1940     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
1941     if(d == NULL)
1942 	return NULL;
1943     crypto->key_usage = d;
1944     d += crypto->num_key_usage++;
1945     memset(d, 0, sizeof(*d));
1946     d->usage = usage;
1947     return &d->key;
1948 }
1949 
1950 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_derive_key(krb5_context context,const krb5_keyblock * key,krb5_enctype etype,const void * constant,size_t constant_len,krb5_keyblock ** derived_key)1951 krb5_derive_key(krb5_context context,
1952 		const krb5_keyblock *key,
1953 		krb5_enctype etype,
1954 		const void *constant,
1955 		size_t constant_len,
1956 		krb5_keyblock **derived_key)
1957 {
1958     krb5_error_code ret;
1959     struct _krb5_encryption_type *et;
1960     struct _krb5_key_data d;
1961 
1962     *derived_key = NULL;
1963 
1964     et = _krb5_find_enctype (etype);
1965     if (et == NULL) {
1966         return unsupported_enctype (context, etype);
1967     }
1968 
1969     ret = krb5_copy_keyblock(context, key, &d.key);
1970     if (ret)
1971 	return ret;
1972 
1973     d.schedule = NULL;
1974     ret = _krb5_derive_key(context, et, &d, constant, constant_len);
1975     if (ret == 0)
1976 	ret = krb5_copy_keyblock(context, d.key, derived_key);
1977     _krb5_free_key_data(context, &d, et);
1978     return ret;
1979 }
1980 
1981 static krb5_error_code
_get_derived_key(krb5_context context,krb5_crypto crypto,unsigned usage,struct _krb5_key_data ** key)1982 _get_derived_key(krb5_context context,
1983 		 krb5_crypto crypto,
1984 		 unsigned usage,
1985 		 struct _krb5_key_data **key)
1986 {
1987     int i;
1988     struct _krb5_key_data *d;
1989     unsigned char constant[5];
1990 
1991     for(i = 0; i < crypto->num_key_usage; i++)
1992 	if(crypto->key_usage[i].usage == usage) {
1993 	    *key = &crypto->key_usage[i].key;
1994 	    return 0;
1995 	}
1996     d = _new_derived_key(crypto, usage);
1997     if(d == NULL) {
1998 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1999 	return ENOMEM;
2000     }
2001     krb5_copy_keyblock(context, crypto->key.key, &d->key);
2002     _krb5_put_int(constant, usage, 5);
2003     _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2004     *key = d;
2005     return 0;
2006 }
2007 
2008 /**
2009  * Create a crypto context used for all encryption and signature
2010  * operation. The encryption type to use is taken from the key, but
2011  * can be overridden with the enctype parameter.  This can be useful
2012  * for encryptions types which is compatiable (DES for example).
2013  *
2014  * To free the crypto context, use krb5_crypto_destroy().
2015  *
2016  * @param context Kerberos context
2017  * @param key the key block information with all key data
2018  * @param etype the encryption type
2019  * @param crypto the resulting crypto context
2020  *
2021  * @return Return an error code or 0.
2022  *
2023  * @ingroup krb5_crypto
2024  */
2025 
2026 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_init(krb5_context context,const krb5_keyblock * key,krb5_enctype etype,krb5_crypto * crypto)2027 krb5_crypto_init(krb5_context context,
2028 		 const krb5_keyblock *key,
2029 		 krb5_enctype etype,
2030 		 krb5_crypto *crypto)
2031 {
2032     krb5_error_code ret;
2033     ALLOC(*crypto, 1);
2034     if(*crypto == NULL) {
2035 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2036 	return ENOMEM;
2037     }
2038     if(etype == ETYPE_NULL)
2039 	etype = key->keytype;
2040     (*crypto)->et = _krb5_find_enctype(etype);
2041     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2042 	free(*crypto);
2043 	*crypto = NULL;
2044 	return unsupported_enctype(context, etype);
2045     }
2046     if((*crypto)->et->keytype->size != key->keyvalue.length) {
2047 	free(*crypto);
2048 	*crypto = NULL;
2049 	krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2050 				"encryption key has bad length");
2051 	return KRB5_BAD_KEYSIZE;
2052     }
2053     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2054     if(ret) {
2055 	free(*crypto);
2056 	*crypto = NULL;
2057 	return ret;
2058     }
2059     (*crypto)->key.schedule = NULL;
2060     (*crypto)->num_key_usage = 0;
2061     (*crypto)->key_usage = NULL;
2062     return 0;
2063 }
2064 
2065 static void
free_key_schedule(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2066 free_key_schedule(krb5_context context,
2067 		  struct _krb5_key_data *key,
2068 		  struct _krb5_encryption_type *et)
2069 {
2070     if (et->keytype->cleanup)
2071 	(*et->keytype->cleanup)(context, key);
2072     memset(key->schedule->data, 0, key->schedule->length);
2073     krb5_free_data(context, key->schedule);
2074 }
2075 
2076 void
_krb5_free_key_data(krb5_context context,struct _krb5_key_data * key,struct _krb5_encryption_type * et)2077 _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2078 	      struct _krb5_encryption_type *et)
2079 {
2080     krb5_free_keyblock(context, key->key);
2081     if(key->schedule) {
2082 	free_key_schedule(context, key, et);
2083 	key->schedule = NULL;
2084     }
2085 }
2086 
2087 static void
free_key_usage(krb5_context context,struct _krb5_key_usage * ku,struct _krb5_encryption_type * et)2088 free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2089 	       struct _krb5_encryption_type *et)
2090 {
2091     _krb5_free_key_data(context, &ku->key, et);
2092 }
2093 
2094 /**
2095  * Free a crypto context created by krb5_crypto_init().
2096  *
2097  * @param context Kerberos context
2098  * @param crypto crypto context to free
2099  *
2100  * @return Return an error code or 0.
2101  *
2102  * @ingroup krb5_crypto
2103  */
2104 
2105 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_destroy(krb5_context context,krb5_crypto crypto)2106 krb5_crypto_destroy(krb5_context context,
2107 		    krb5_crypto crypto)
2108 {
2109     int i;
2110 
2111     for(i = 0; i < crypto->num_key_usage; i++)
2112 	free_key_usage(context, &crypto->key_usage[i], crypto->et);
2113     free(crypto->key_usage);
2114     _krb5_free_key_data(context, &crypto->key, crypto->et);
2115     free (crypto);
2116     return 0;
2117 }
2118 
2119 /**
2120  * Return the blocksize used algorithm referenced by the crypto context
2121  *
2122  * @param context Kerberos context
2123  * @param crypto crypto context to query
2124  * @param blocksize the resulting blocksize
2125  *
2126  * @return Return an error code or 0.
2127  *
2128  * @ingroup krb5_crypto
2129  */
2130 
2131 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getblocksize(krb5_context context,krb5_crypto crypto,size_t * blocksize)2132 krb5_crypto_getblocksize(krb5_context context,
2133 			 krb5_crypto crypto,
2134 			 size_t *blocksize)
2135 {
2136     *blocksize = crypto->et->blocksize;
2137     return 0;
2138 }
2139 
2140 /**
2141  * Return the encryption type used by the crypto context
2142  *
2143  * @param context Kerberos context
2144  * @param crypto crypto context to query
2145  * @param enctype the resulting encryption type
2146  *
2147  * @return Return an error code or 0.
2148  *
2149  * @ingroup krb5_crypto
2150  */
2151 
2152 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getenctype(krb5_context context,krb5_crypto crypto,krb5_enctype * enctype)2153 krb5_crypto_getenctype(krb5_context context,
2154 		       krb5_crypto crypto,
2155 		       krb5_enctype *enctype)
2156 {
2157     *enctype = crypto->et->type;
2158     return 0;
2159 }
2160 
2161 /**
2162  * Return the padding size used by the crypto context
2163  *
2164  * @param context Kerberos context
2165  * @param crypto crypto context to query
2166  * @param padsize the return padding size
2167  *
2168  * @return Return an error code or 0.
2169  *
2170  * @ingroup krb5_crypto
2171  */
2172 
2173 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getpadsize(krb5_context context,krb5_crypto crypto,size_t * padsize)2174 krb5_crypto_getpadsize(krb5_context context,
2175                        krb5_crypto crypto,
2176                        size_t *padsize)
2177 {
2178     *padsize = crypto->et->padsize;
2179     return 0;
2180 }
2181 
2182 /**
2183  * Return the confounder size used by the crypto context
2184  *
2185  * @param context Kerberos context
2186  * @param crypto crypto context to query
2187  * @param confoundersize the returned confounder size
2188  *
2189  * @return Return an error code or 0.
2190  *
2191  * @ingroup krb5_crypto
2192  */
2193 
2194 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_getconfoundersize(krb5_context context,krb5_crypto crypto,size_t * confoundersize)2195 krb5_crypto_getconfoundersize(krb5_context context,
2196                               krb5_crypto crypto,
2197                               size_t *confoundersize)
2198 {
2199     *confoundersize = crypto->et->confoundersize;
2200     return 0;
2201 }
2202 
2203 
2204 /**
2205  * Disable encryption type
2206  *
2207  * @param context Kerberos 5 context
2208  * @param enctype encryption type to disable
2209  *
2210  * @return Return an error code or 0.
2211  *
2212  * @ingroup krb5_crypto
2213  */
2214 
2215 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_disable(krb5_context context,krb5_enctype enctype)2216 krb5_enctype_disable(krb5_context context,
2217 		     krb5_enctype enctype)
2218 {
2219     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2220     if(et == NULL) {
2221 	if (context)
2222 	    krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2223 				    N_("encryption type %d not supported", ""),
2224 				    enctype);
2225 	return KRB5_PROG_ETYPE_NOSUPP;
2226     }
2227     et->flags |= F_DISABLED;
2228     return 0;
2229 }
2230 
2231 /**
2232  * Enable encryption type
2233  *
2234  * @param context Kerberos 5 context
2235  * @param enctype encryption type to enable
2236  *
2237  * @return Return an error code or 0.
2238  *
2239  * @ingroup krb5_crypto
2240  */
2241 
2242 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_enctype_enable(krb5_context context,krb5_enctype enctype)2243 krb5_enctype_enable(krb5_context context,
2244 		    krb5_enctype enctype)
2245 {
2246     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2247     if(et == NULL) {
2248 	if (context)
2249 	    krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2250 				    N_("encryption type %d not supported", ""),
2251 				    enctype);
2252 	return KRB5_PROG_ETYPE_NOSUPP;
2253     }
2254     et->flags &= ~F_DISABLED;
2255     return 0;
2256 }
2257 
2258 /**
2259  * Enable or disable all weak encryption types
2260  *
2261  * @param context Kerberos 5 context
2262  * @param enable true to enable, false to disable
2263  *
2264  * @return Return an error code or 0.
2265  *
2266  * @ingroup krb5_crypto
2267  */
2268 
2269 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_allow_weak_crypto(krb5_context context,krb5_boolean enable)2270 krb5_allow_weak_crypto(krb5_context context,
2271 		       krb5_boolean enable)
2272 {
2273     int i;
2274 
2275     for(i = 0; i < _krb5_num_etypes; i++)
2276 	if(_krb5_etypes[i]->flags & F_WEAK) {
2277 	    if(enable)
2278 		_krb5_etypes[i]->flags &= ~F_DISABLED;
2279 	    else
2280 		_krb5_etypes[i]->flags |= F_DISABLED;
2281 	}
2282     return 0;
2283 }
2284 
2285 static size_t
wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)2286 wrapped_length (krb5_context context,
2287 		krb5_crypto  crypto,
2288 		size_t       data_len)
2289 {
2290     struct _krb5_encryption_type *et = crypto->et;
2291     size_t padsize = et->padsize;
2292     size_t checksumsize = CHECKSUMSIZE(et->checksum);
2293     size_t res;
2294 
2295     res =  et->confoundersize + checksumsize + data_len;
2296     res =  (res + padsize - 1) / padsize * padsize;
2297     return res;
2298 }
2299 
2300 static size_t
wrapped_length_dervied(krb5_context context,krb5_crypto crypto,size_t data_len)2301 wrapped_length_dervied (krb5_context context,
2302 			krb5_crypto  crypto,
2303 			size_t       data_len)
2304 {
2305     struct _krb5_encryption_type *et = crypto->et;
2306     size_t padsize = et->padsize;
2307     size_t res;
2308 
2309     res =  et->confoundersize + data_len;
2310     res =  (res + padsize - 1) / padsize * padsize;
2311     if (et->keyed_checksum)
2312 	res += et->keyed_checksum->checksumsize;
2313     else
2314 	res += et->checksum->checksumsize;
2315     return res;
2316 }
2317 
2318 /*
2319  * Return the size of an encrypted packet of length `data_len'
2320  */
2321 
2322 KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_get_wrapped_length(krb5_context context,krb5_crypto crypto,size_t data_len)2323 krb5_get_wrapped_length (krb5_context context,
2324 			 krb5_crypto  crypto,
2325 			 size_t       data_len)
2326 {
2327     if (derived_crypto (context, crypto))
2328 	return wrapped_length_dervied (context, crypto, data_len);
2329     else
2330 	return wrapped_length (context, crypto, data_len);
2331 }
2332 
2333 /*
2334  * Return the size of an encrypted packet of length `data_len'
2335  */
2336 
2337 static size_t
crypto_overhead(krb5_context context,krb5_crypto crypto)2338 crypto_overhead (krb5_context context,
2339 		 krb5_crypto  crypto)
2340 {
2341     struct _krb5_encryption_type *et = crypto->et;
2342     size_t res;
2343 
2344     res = CHECKSUMSIZE(et->checksum);
2345     res += et->confoundersize;
2346     if (et->padsize > 1)
2347 	res += et->padsize;
2348     return res;
2349 }
2350 
2351 static size_t
crypto_overhead_dervied(krb5_context context,krb5_crypto crypto)2352 crypto_overhead_dervied (krb5_context context,
2353 			 krb5_crypto  crypto)
2354 {
2355     struct _krb5_encryption_type *et = crypto->et;
2356     size_t res;
2357 
2358     if (et->keyed_checksum)
2359 	res = CHECKSUMSIZE(et->keyed_checksum);
2360     else
2361 	res = CHECKSUMSIZE(et->checksum);
2362     res += et->confoundersize;
2363     if (et->padsize > 1)
2364 	res += et->padsize;
2365     return res;
2366 }
2367 
2368 KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
krb5_crypto_overhead(krb5_context context,krb5_crypto crypto)2369 krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2370 {
2371     if (derived_crypto (context, crypto))
2372 	return crypto_overhead_dervied (context, crypto);
2373     else
2374 	return crypto_overhead (context, crypto);
2375 }
2376 
2377 /**
2378  * Converts the random bytestring to a protocol key according to
2379  * Kerberos crypto frame work. It may be assumed that all the bits of
2380  * the input string are equally random, even though the entropy
2381  * present in the random source may be limited.
2382  *
2383  * @param context Kerberos 5 context
2384  * @param type the enctype resulting key will be of
2385  * @param data input random data to convert to a key
2386  * @param size size of input random data, at least krb5_enctype_keysize() long
2387  * @param key key, output key, free with krb5_free_keyblock_contents()
2388  *
2389  * @return Return an error code or 0.
2390  *
2391  * @ingroup krb5_crypto
2392  */
2393 
2394 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_random_to_key(krb5_context context,krb5_enctype type,const void * data,size_t size,krb5_keyblock * key)2395 krb5_random_to_key(krb5_context context,
2396 		   krb5_enctype type,
2397 		   const void *data,
2398 		   size_t size,
2399 		   krb5_keyblock *key)
2400 {
2401     krb5_error_code ret;
2402     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2403     if(et == NULL) {
2404 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2405 			       N_("encryption type %d not supported", ""),
2406 			       type);
2407 	return KRB5_PROG_ETYPE_NOSUPP;
2408     }
2409     if ((et->keytype->bits + 7) / 8 > size) {
2410 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2411 			       N_("encryption key %s needs %d bytes "
2412 				  "of random to make an encryption key "
2413 				  "out of it", ""),
2414 			       et->name, (int)et->keytype->size);
2415 	return KRB5_PROG_ETYPE_NOSUPP;
2416     }
2417     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
2418     if(ret)
2419 	return ret;
2420     key->keytype = type;
2421     if (et->keytype->random_to_key)
2422  	(*et->keytype->random_to_key)(context, key, data, size);
2423     else
2424 	memcpy(key->keyvalue.data, data, et->keytype->size);
2425 
2426     return 0;
2427 }
2428 
2429 
2430 
2431 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_prf_length(krb5_context context,krb5_enctype type,size_t * length)2432 krb5_crypto_prf_length(krb5_context context,
2433 		       krb5_enctype type,
2434 		       size_t *length)
2435 {
2436     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2437 
2438     if(et == NULL || et->prf_length == 0) {
2439 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2440 			       N_("encryption type %d not supported", ""),
2441 			       type);
2442 	return KRB5_PROG_ETYPE_NOSUPP;
2443     }
2444 
2445     *length = et->prf_length;
2446     return 0;
2447 }
2448 
2449 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_prf(krb5_context context,const krb5_crypto crypto,const krb5_data * input,krb5_data * output)2450 krb5_crypto_prf(krb5_context context,
2451 		const krb5_crypto crypto,
2452 		const krb5_data *input,
2453 		krb5_data *output)
2454 {
2455     struct _krb5_encryption_type *et = crypto->et;
2456 
2457     krb5_data_zero(output);
2458 
2459     if(et->prf == NULL) {
2460 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2461 			       "kerberos prf for %s not supported",
2462 			       et->name);
2463 	return KRB5_PROG_ETYPE_NOSUPP;
2464     }
2465 
2466     return (*et->prf)(context, crypto, input, output);
2467 }
2468 
2469 static krb5_error_code
krb5_crypto_prfplus(krb5_context context,const krb5_crypto crypto,const krb5_data * input,size_t length,krb5_data * output)2470 krb5_crypto_prfplus(krb5_context context,
2471 		    const krb5_crypto crypto,
2472 		    const krb5_data *input,
2473 		    size_t length,
2474 		    krb5_data *output)
2475 {
2476     krb5_error_code ret;
2477     krb5_data input2;
2478     unsigned char i = 1;
2479     unsigned char *p;
2480 
2481     krb5_data_zero(&input2);
2482     krb5_data_zero(output);
2483 
2484     krb5_clear_error_message(context);
2485 
2486     ret = krb5_data_alloc(output, length);
2487     if (ret) goto out;
2488     ret = krb5_data_alloc(&input2, input->length + 1);
2489     if (ret) goto out;
2490 
2491     krb5_clear_error_message(context);
2492 
2493     memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
2494 
2495     p = output->data;
2496 
2497     while (length) {
2498 	krb5_data block;
2499 
2500 	((unsigned char *)input2.data)[0] = i++;
2501 
2502 	ret = krb5_crypto_prf(context, crypto, &input2, &block);
2503 	if (ret)
2504 	    goto out;
2505 
2506 	if (block.length < length) {
2507 	    memcpy(p, block.data, block.length);
2508 	    length -= block.length;
2509 	} else {
2510 	    memcpy(p, block.data, length);
2511 	    length = 0;
2512 	}
2513 	p += block.length;
2514 	krb5_data_free(&block);
2515     }
2516 
2517  out:
2518     krb5_data_free(&input2);
2519     if (ret)
2520 	krb5_data_free(output);
2521     return ret;
2522 }
2523 
2524 /**
2525  * The FX-CF2 key derivation function, used in FAST and preauth framework.
2526  *
2527  * @param context Kerberos 5 context
2528  * @param crypto1 first key to combine
2529  * @param crypto2 second key to combine
2530  * @param pepper1 factor to combine with first key to garante uniqueness
2531  * @param pepper2 factor to combine with second key to garante uniqueness
2532  * @param enctype the encryption type of the resulting key
2533  * @param res allocated key, free with krb5_free_keyblock_contents()
2534  *
2535  * @return Return an error code or 0.
2536  *
2537  * @ingroup krb5_crypto
2538  */
2539 
2540 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_crypto_fx_cf2(krb5_context context,const krb5_crypto crypto1,const krb5_crypto crypto2,krb5_data * pepper1,krb5_data * pepper2,krb5_enctype enctype,krb5_keyblock * res)2541 krb5_crypto_fx_cf2(krb5_context context,
2542 		   const krb5_crypto crypto1,
2543 		   const krb5_crypto crypto2,
2544 		   krb5_data *pepper1,
2545 		   krb5_data *pepper2,
2546 		   krb5_enctype enctype,
2547 		   krb5_keyblock *res)
2548 {
2549     krb5_error_code ret;
2550     krb5_data os1, os2;
2551     size_t i, keysize;
2552 
2553     memset(res, 0, sizeof(*res));
2554     krb5_data_zero(&os1);
2555     krb5_data_zero(&os2);
2556 
2557     ret = krb5_enctype_keysize(context, enctype, &keysize);
2558     if (ret)
2559 	return ret;
2560 
2561     ret = krb5_data_alloc(&res->keyvalue, keysize);
2562     if (ret)
2563 	goto out;
2564     ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
2565     if (ret)
2566 	goto out;
2567     ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
2568     if (ret)
2569 	goto out;
2570 
2571     res->keytype = enctype;
2572     {
2573 	unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
2574 	for (i = 0; i < keysize; i++)
2575 	    p3[i] = p1[i] ^ p2[i];
2576     }
2577  out:
2578     if (ret)
2579 	krb5_data_free(&res->keyvalue);
2580     krb5_data_free(&os1);
2581     krb5_data_free(&os2);
2582 
2583     return ret;
2584 }
2585 
2586 
2587 
2588 #ifndef HEIMDAL_SMALLER
2589 
2590 /**
2591  * Deprecated: keytypes doesn't exists, they are really enctypes.
2592  *
2593  * @ingroup krb5_deprecated
2594  */
2595 
2596 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_keytype_to_enctypes(krb5_context context,krb5_keytype keytype,unsigned * len,krb5_enctype ** val)2597 krb5_keytype_to_enctypes (krb5_context context,
2598 			  krb5_keytype keytype,
2599 			  unsigned *len,
2600 			  krb5_enctype **val)
2601     KRB5_DEPRECATED_FUNCTION("Use X instead")
2602 {
2603     int i;
2604     unsigned n = 0;
2605     krb5_enctype *ret;
2606 
2607     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2608 	if (_krb5_etypes[i]->keytype->type == keytype
2609 	    && !(_krb5_etypes[i]->flags & F_PSEUDO)
2610 	    && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2611 	    ++n;
2612     }
2613     if (n == 0) {
2614 	krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
2615 			       "Keytype have no mapping");
2616 	return KRB5_PROG_KEYTYPE_NOSUPP;
2617     }
2618 
2619     ret = malloc(n * sizeof(*ret));
2620     if (ret == NULL && n != 0) {
2621 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
2622 	return ENOMEM;
2623     }
2624     n = 0;
2625     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2626 	if (_krb5_etypes[i]->keytype->type == keytype
2627 	    && !(_krb5_etypes[i]->flags & F_PSEUDO)
2628 	    && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2629 	    ret[n++] = _krb5_etypes[i]->type;
2630     }
2631     *len = n;
2632     *val = ret;
2633     return 0;
2634 }
2635 
2636 /**
2637  * Deprecated: keytypes doesn't exists, they are really enctypes.
2638  *
2639  * @ingroup krb5_deprecated
2640  */
2641 
2642 /* if two enctypes have compatible keys */
2643 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
krb5_enctypes_compatible_keys(krb5_context context,krb5_enctype etype1,krb5_enctype etype2)2644 krb5_enctypes_compatible_keys(krb5_context context,
2645 			      krb5_enctype etype1,
2646 			      krb5_enctype etype2)
2647     KRB5_DEPRECATED_FUNCTION("Use X instead")
2648 {
2649     struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
2650     struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
2651     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2652 }
2653 
2654 #endif /* HEIMDAL_SMALLER */
2655