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