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