Line data Source code
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
62 223808 : unsupported_enctype(krb5_context context, krb5_enctype etype)
63 : {
64 6826 : krb5_error_code ret;
65 6826 : char *name;
66 :
67 223808 : ret = krb5_enctype_to_string(context, etype, &name);
68 223808 : if (ret)
69 216982 : return ret;
70 :
71 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
72 0 : N_("Encryption type %s not supported", ""),
73 : name);
74 0 : free(name);
75 0 : return KRB5_PROG_ETYPE_NOSUPP;
76 : }
77 :
78 : /*
79 : *
80 : */
81 :
82 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
83 871419 : krb5_enctype_keysize(krb5_context context,
84 : krb5_enctype type,
85 : size_t *keysize)
86 : {
87 871419 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
88 871419 : if(et == NULL) {
89 0 : return unsupported_enctype (context, type);
90 : }
91 871419 : *keysize = et->keytype->size;
92 871419 : return 0;
93 : }
94 :
95 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
96 180537 : krb5_enctype_keybits(krb5_context context,
97 : krb5_enctype type,
98 : size_t *keybits)
99 : {
100 180537 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
101 180537 : if(et == NULL) {
102 0 : return unsupported_enctype (context, type);
103 : }
104 180537 : *keybits = et->keytype->bits;
105 180537 : return 0;
106 : }
107 :
108 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
109 250057 : krb5_generate_random_keyblock(krb5_context context,
110 : krb5_enctype type,
111 : krb5_keyblock *key)
112 : {
113 8060 : krb5_error_code ret;
114 250057 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
115 250057 : if(et == NULL) {
116 0 : return unsupported_enctype (context, type);
117 : }
118 250057 : ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
119 250057 : if(ret)
120 0 : return ret;
121 250057 : key->keytype = type;
122 250057 : if(et->keytype->random_key)
123 0 : (*et->keytype->random_key)(context, key);
124 : else
125 250057 : krb5_generate_random_block(key->keyvalue.data,
126 : key->keyvalue.length);
127 241997 : return 0;
128 : }
129 :
130 : static krb5_error_code
131 11968827 : _key_schedule(krb5_context context,
132 : struct _krb5_key_data *key)
133 : {
134 186076 : krb5_error_code ret;
135 186076 : struct _krb5_encryption_type *et;
136 186076 : struct _krb5_key_type *kt;
137 :
138 11968827 : if (key->schedule != NULL)
139 6145991 : return 0;
140 :
141 5815328 : et = _krb5_find_enctype(key->key->keytype);
142 :
143 5815328 : if (et == NULL) {
144 0 : return unsupported_enctype (context,
145 0 : key->key->keytype);
146 : }
147 :
148 5815328 : kt = et->keytype;
149 :
150 5815328 : if(kt->schedule == NULL)
151 0 : return 0;
152 5815328 : ALLOC(key->schedule, 1);
153 5815328 : if (key->schedule == NULL)
154 0 : return krb5_enomem(context);
155 5815328 : ret = krb5_data_alloc(key->schedule, kt->schedule_size);
156 5815328 : if(ret) {
157 0 : free(key->schedule);
158 0 : key->schedule = NULL;
159 0 : return ret;
160 : }
161 5815328 : (*kt->schedule)(context, kt, key);
162 5815328 : return 0;
163 : }
164 :
165 : /************************************************************
166 : * *
167 : ************************************************************/
168 :
169 : static krb5_error_code
170 722331 : EVP_unkeyed_checksum(krb5_context context,
171 : krb5_crypto crypto,
172 : struct _krb5_key_data *key,
173 : unsigned usage,
174 : const struct krb5_crypto_iov *iov,
175 : int niov,
176 : Checksum *C,
177 : const EVP_MD *md)
178 : {
179 722331 : if (_krb5_evp_digest_iov(crypto,
180 : iov, niov,
181 : C->checksum.data, NULL,
182 : md, NULL) != 1)
183 0 : krb5_abortx(context, "unkeyed checksum failed");
184 :
185 722331 : return 0;
186 : }
187 :
188 : #define EVP_SHA_CHECKSUM(name) \
189 : \
190 : static krb5_error_code \
191 : SHA ## name ##_checksum(krb5_context context, \
192 : krb5_crypto crypto, \
193 : struct _krb5_key_data *key, \
194 : unsigned usage, \
195 : const struct krb5_crypto_iov *iov, \
196 : int niov, \
197 : Checksum *C) \
198 : { \
199 : return EVP_unkeyed_checksum(context, crypto, key, \
200 : usage, iov, niov, \
201 : C, EVP_sha##name()); \
202 : }
203 :
204 722331 : EVP_SHA_CHECKSUM(1)
205 0 : EVP_SHA_CHECKSUM(256)
206 0 : EVP_SHA_CHECKSUM(384)
207 0 : EVP_SHA_CHECKSUM(512)
208 :
209 : /* HMAC according to RFC2104 */
210 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
211 1130119 : _krb5_internal_hmac_iov(krb5_context context,
212 : krb5_crypto crypto,
213 : struct _krb5_checksum_type *cm,
214 : unsigned usage,
215 : const struct krb5_crypto_iov *iov,
216 : int niov,
217 : struct _krb5_key_data *keyblock,
218 : Checksum *result)
219 : {
220 196 : unsigned char *ipad, *opad;
221 196 : unsigned char *key;
222 196 : struct krb5_crypto_iov *working;
223 196 : size_t key_len;
224 196 : size_t i;
225 :
226 1130119 : ipad = malloc(cm->blocksize);
227 1130119 : if (ipad == NULL)
228 0 : return ENOMEM;
229 :
230 1130119 : opad = malloc(cm->blocksize + cm->checksumsize);
231 1130119 : if (opad == NULL) {
232 0 : free(ipad);
233 0 : return ENOMEM;
234 : }
235 :
236 1130119 : working = calloc(niov + 1, sizeof(struct krb5_crypto_iov));
237 1130119 : if (working == NULL) {
238 0 : free(ipad);
239 0 : free(opad);
240 0 : return ENOMEM;
241 : }
242 :
243 1130119 : memset(ipad, 0x36, cm->blocksize);
244 1130119 : memset(opad, 0x5c, cm->blocksize);
245 :
246 1130119 : if(keyblock->key->keyvalue.length > cm->blocksize){
247 0 : working[0].data = keyblock->key->keyvalue;
248 0 : working[0].flags = KRB5_CRYPTO_TYPE_DATA;
249 0 : (*cm->checksum)(context,
250 : crypto,
251 : keyblock,
252 : usage,
253 : working,
254 : 1,
255 : result);
256 0 : key = result->checksum.data;
257 0 : key_len = result->checksum.length;
258 : } else {
259 1130119 : key = keyblock->key->keyvalue.data;
260 1130119 : key_len = keyblock->key->keyvalue.length;
261 : }
262 19212039 : for(i = 0; i < key_len; i++){
263 18081920 : ipad[i] ^= key[i];
264 18081920 : opad[i] ^= key[i];
265 : }
266 :
267 1130119 : working[0].data.data = ipad;
268 1130119 : working[0].data.length = cm->blocksize;
269 1130119 : working[0].flags = KRB5_CRYPTO_TYPE_DATA;
270 2260238 : for (i = 0; i < niov; i++)
271 1130119 : working[i + 1] = iov[i];
272 :
273 1130119 : (*cm->checksum)(context, crypto, keyblock, usage, working, niov + 1, result);
274 1130119 : memcpy(opad + cm->blocksize, result->checksum.data,
275 : result->checksum.length);
276 :
277 1130119 : working[0].data.data = opad;
278 1130119 : working[0].data.length = cm->blocksize + cm->checksumsize;
279 1130119 : working[0].flags = KRB5_CRYPTO_TYPE_DATA;
280 1130119 : (*cm->checksum)(context, crypto, keyblock, usage, working, 1, result);
281 1130119 : memset(ipad, 0, cm->blocksize);
282 1130119 : free(ipad);
283 1130119 : memset(opad, 0, cm->blocksize + cm->checksumsize);
284 1130119 : free(opad);
285 1130119 : free(working);
286 :
287 1130119 : return 0;
288 : }
289 :
290 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
291 1130119 : _krb5_internal_hmac(krb5_context context,
292 : krb5_crypto crypto,
293 : struct _krb5_checksum_type *cm,
294 : const void *data,
295 : size_t len,
296 : unsigned usage,
297 : struct _krb5_key_data *keyblock,
298 : Checksum *result)
299 : {
300 196 : struct krb5_crypto_iov iov[1];
301 :
302 1130119 : iov[0].data.data = (void *) data;
303 1130119 : iov[0].data.length = len;
304 1130119 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
305 1130119 : return _krb5_internal_hmac_iov(context, crypto, cm, usage, iov, 1,
306 : keyblock, result);
307 : }
308 :
309 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
310 589876 : krb5_hmac(krb5_context context,
311 : krb5_cksumtype cktype,
312 : const void *data,
313 : size_t len,
314 : unsigned usage,
315 : krb5_keyblock *key,
316 : Checksum *result)
317 : {
318 589876 : struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
319 0 : struct _krb5_key_data kd;
320 :
321 0 : krb5_error_code ret;
322 :
323 589876 : if (c == NULL) {
324 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
325 0 : N_("checksum type %d not supported", ""),
326 : cktype);
327 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
328 : }
329 :
330 589876 : kd.key = key;
331 589876 : kd.schedule = NULL;
332 :
333 589876 : ret = _krb5_internal_hmac(context, NULL, c, data, len, usage, &kd, result);
334 :
335 589876 : if (kd.schedule)
336 0 : krb5_free_data(context, kd.schedule);
337 :
338 589876 : return ret;
339 : }
340 :
341 : krb5_error_code
342 2796492 : _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
343 : krb5_crypto crypto,
344 : struct _krb5_key_data *key,
345 : unsigned usage,
346 : const struct krb5_crypto_iov *iov,
347 : int niov,
348 : Checksum *result)
349 : {
350 28803 : krb5_error_code ret;
351 28803 : unsigned char hmac[EVP_MAX_MD_SIZE];
352 2796492 : unsigned int hmaclen = sizeof(hmac);
353 :
354 2796492 : ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
355 : EVP_sha1(), NULL);
356 2796492 : if (ret)
357 0 : return ret;
358 :
359 2796492 : heim_assert(result->checksum.length <= hmaclen,
360 : "SHA1 checksum too short");
361 2796492 : memcpy(result->checksum.data, hmac, result->checksum.length);
362 :
363 2796492 : return 0;
364 : }
365 :
366 : krb5_error_code
367 2027794 : _krb5_SP_HMAC_SHA1_verify(krb5_context context,
368 : krb5_crypto crypto,
369 : struct _krb5_key_data *key,
370 : unsigned usage,
371 : const struct krb5_crypto_iov *iov,
372 : int niov,
373 : Checksum *verify)
374 : {
375 23420 : krb5_error_code ret;
376 23420 : unsigned char hmac[EVP_MAX_MD_SIZE];
377 2027794 : unsigned int hmaclen = sizeof(hmac);
378 23420 : krb5_data data;
379 :
380 2027794 : ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
381 : EVP_sha1(), NULL);
382 2027794 : if (ret)
383 0 : return ret;
384 :
385 2027794 : data.data = hmac;
386 2027794 : data.length = min(hmaclen, verify->checksum.length);
387 :
388 2027794 : if(krb5_data_ct_cmp(&data, &verify->checksum) != 0)
389 477 : return KRB5KRB_AP_ERR_BAD_INTEGRITY;
390 :
391 2003897 : return 0;
392 : }
393 :
394 : #define SHA_CHECKSUM(name, blocksize, outputsize) \
395 : struct _krb5_checksum_type _krb5_checksum_sha##name = { \
396 : CKSUMTYPE_SHA##name, \
397 : "sha" #name, \
398 : blocksize, \
399 : outputsize, \
400 : F_CPROOF, \
401 : SHA##name##_checksum, \
402 : NULL \
403 : };
404 :
405 : SHA_CHECKSUM(1, 64, 20);
406 : SHA_CHECKSUM(256, 64, 32);
407 : SHA_CHECKSUM(384, 128, 48);
408 : SHA_CHECKSUM(512, 128, 64);
409 :
410 : KRB5_LIB_FUNCTION struct _krb5_checksum_type * KRB5_LIB_CALL
411 4639485 : _krb5_find_checksum(krb5_cksumtype type)
412 : {
413 50927 : int i;
414 29203735 : for(i = 0; i < _krb5_num_checksums; i++)
415 29203716 : if(_krb5_checksum_types[i]->type == type)
416 4639466 : return _krb5_checksum_types[i];
417 19 : return NULL;
418 : }
419 :
420 : static krb5_error_code
421 4993524 : get_checksum_key(krb5_context context,
422 : krb5_crypto crypto,
423 : unsigned usage, /* not krb5_key_usage */
424 : struct _krb5_checksum_type *ct,
425 : struct _krb5_key_data **key)
426 : {
427 4993524 : krb5_error_code ret = 0;
428 4993524 : struct _krb5_checksum_type *kct = NULL;
429 :
430 4993524 : if (crypto == NULL) {
431 0 : krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
432 0 : N_("Checksum type %s is keyed but no "
433 : "crypto context (key) was passed in", ""),
434 : ct->name);
435 0 : return KRB5_BAD_ENCTYPE;
436 : }
437 4993524 : kct = crypto->et->keyed_checksum;
438 4993524 : if (kct == NULL || kct->type != ct->type) {
439 104 : krb5_set_error_message(context, KRB5_BAD_ENCTYPE,
440 104 : N_("Checksum type %s is keyed, but "
441 : "the key type %s passed didnt have that checksum "
442 : "type as the keyed type", ""),
443 104 : ct->name, crypto->et->name);
444 104 : return KRB5_BAD_ENCTYPE;
445 : }
446 :
447 4993420 : if(ct->flags & F_DERIVED)
448 4824286 : ret = _get_derived_key(context, crypto, usage, key);
449 169134 : else if(ct->flags & F_VARIANT) {
450 0 : size_t i;
451 :
452 0 : *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
453 0 : if (*key == NULL)
454 0 : return krb5_enomem(context);
455 0 : ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
456 0 : if(ret)
457 0 : return ret;
458 0 : for(i = 0; i < (*key)->key->keyvalue.length; i++)
459 0 : ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
460 : } else {
461 169134 : *key = &crypto->key;
462 : }
463 4993420 : if(ret == 0)
464 4993420 : ret = _key_schedule(context, *key);
465 4941153 : return ret;
466 : }
467 :
468 : static krb5_error_code
469 2968974 : create_checksum_iov(krb5_context context,
470 : struct _krb5_checksum_type *ct,
471 : krb5_crypto crypto,
472 : unsigned usage,
473 : struct krb5_crypto_iov *iov,
474 : int niov,
475 : krb5_flags flags,
476 : Checksum *result)
477 : {
478 28827 : krb5_error_code ret;
479 28827 : struct _krb5_key_data *dkey;
480 :
481 2968974 : if (ct->flags & F_DISABLED) {
482 0 : krb5_clear_error_message (context);
483 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
484 : }
485 2968974 : if (ct->flags & F_KEYED) {
486 2964073 : ret = get_checksum_key(context, crypto, usage, ct, &dkey);
487 2964073 : if (ret)
488 0 : return ret;
489 4901 : } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
490 0 : return EINVAL;
491 : } else
492 4901 : dkey = NULL;
493 :
494 2968974 : result->cksumtype = ct->type;
495 :
496 2968974 : return (*ct->checksum)(context, crypto, dkey, usage, iov, niov, result);
497 : }
498 :
499 : static krb5_error_code
500 1826746 : create_checksum (krb5_context context,
501 : struct _krb5_checksum_type *ct,
502 : krb5_crypto crypto,
503 : unsigned usage,
504 : void *data,
505 : size_t len,
506 : krb5_flags flags,
507 : Checksum *result)
508 : {
509 27514 : int ret;
510 27514 : struct krb5_crypto_iov iov[1];
511 :
512 1826746 : ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
513 1826746 : if (ret)
514 0 : return ret;
515 :
516 1826746 : iov[0].data.data = data;
517 1826746 : iov[0].data.length = len;
518 1826746 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
519 :
520 1826746 : return create_checksum_iov(context, ct, crypto, usage, iov, 1, flags, result);
521 : }
522 :
523 : static int
524 1246492 : arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
525 : {
526 1415730 : return (ct->type == CKSUMTYPE_HMAC_MD5) &&
527 169238 : (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
528 : }
529 :
530 : static inline krb5_flags
531 1246492 : crypto_flags(krb5_crypto crypto)
532 : {
533 : /* If caller didn't specify a key, unkeyed checksums are the only option */
534 1246492 : if (crypto == NULL)
535 179 : return KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM;
536 : else
537 1246313 : return crypto->flags;
538 : }
539 :
540 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
541 757737 : krb5_create_checksum(krb5_context context,
542 : krb5_crypto crypto,
543 : krb5_key_usage usage,
544 : int type,
545 : void *data,
546 : size_t len,
547 : Checksum *result)
548 : {
549 757737 : struct _krb5_checksum_type *ct = NULL;
550 13375 : unsigned keyusage;
551 :
552 : /* type 0 -> pick from crypto */
553 757737 : if (type) {
554 4901 : ct = _krb5_find_checksum(type);
555 752836 : } else if (crypto) {
556 752836 : ct = crypto->et->keyed_checksum;
557 752836 : if (ct == NULL)
558 0 : ct = crypto->et->checksum;
559 : }
560 :
561 757737 : if(ct == NULL) {
562 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
563 0 : N_("checksum type %d not supported", ""),
564 : type);
565 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
566 : }
567 :
568 757737 : if (arcfour_checksum_p(ct, crypto)) {
569 167581 : keyusage = usage;
570 167581 : _krb5_usage2arcfour(context, &keyusage);
571 : } else
572 590156 : keyusage = CHECKSUM_USAGE(usage);
573 :
574 771112 : return create_checksum(context, ct, crypto, keyusage, data, len,
575 : crypto_flags(crypto), result);
576 : }
577 :
578 : static krb5_error_code
579 2033224 : verify_checksum_iov(krb5_context context,
580 : krb5_crypto crypto,
581 : unsigned usage, /* not krb5_key_usage */
582 : struct krb5_crypto_iov *iov,
583 : int niov,
584 : krb5_flags flags,
585 : Checksum *cksum)
586 : {
587 23440 : krb5_error_code ret;
588 23440 : struct _krb5_key_data *dkey;
589 23440 : Checksum c;
590 23440 : struct _krb5_checksum_type *ct;
591 :
592 2033224 : ct = _krb5_find_checksum(cksum->cksumtype);
593 2033224 : if (ct == NULL || (ct->flags & F_DISABLED)) {
594 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
595 0 : N_("checksum type %d not supported", ""),
596 0 : cksum->cksumtype);
597 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
598 : }
599 2033224 : if(ct->checksumsize != cksum->checksum.length) {
600 0 : krb5_clear_error_message (context);
601 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
602 0 : N_("Decrypt integrity check failed for checksum type %s, "
603 : "length was %u, expected %u", ""),
604 0 : ct->name, (unsigned)cksum->checksum.length,
605 0 : (unsigned)ct->checksumsize);
606 :
607 0 : return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
608 : }
609 2033224 : if (ct->flags & F_KEYED) {
610 2029451 : ret = get_checksum_key(context, crypto, usage, ct, &dkey);
611 2029451 : if (ret)
612 104 : return ret;
613 3773 : } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
614 0 : krb5_clear_error_message (context);
615 0 : krb5_set_error_message(context, KRB5KRB_AP_ERR_INAPP_CKSUM,
616 0 : N_("Unkeyed checksum type %s provided where keyed "
617 : "checksum was expected", ""), ct->name);
618 :
619 0 : return KRB5KRB_AP_ERR_INAPP_CKSUM;
620 : } else
621 3773 : dkey = NULL;
622 :
623 : /*
624 : * If checksum have a verify function, lets use that instead of
625 : * calling ->checksum and then compare result.
626 : */
627 :
628 2033120 : if(ct->verify) {
629 2027794 : ret = (*ct->verify)(context, crypto, dkey, usage, iov, niov, cksum);
630 2027794 : if (ret)
631 477 : krb5_set_error_message(context, ret,
632 477 : N_("Decrypt integrity check failed for checksum "
633 : "type %s, key type %s", ""),
634 477 : ct->name, (crypto != NULL)? crypto->et->name : "(none)");
635 2027794 : return ret;
636 : }
637 :
638 5326 : ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
639 5326 : if (ret)
640 0 : return ret;
641 :
642 5326 : ret = (*ct->checksum)(context, crypto, dkey, usage, iov, niov, &c);
643 5326 : if (ret) {
644 0 : krb5_data_free(&c.checksum);
645 0 : return ret;
646 : }
647 :
648 5326 : if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
649 28 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
650 28 : krb5_set_error_message(context, ret,
651 28 : N_("Decrypt integrity check failed for checksum "
652 : "type %s, key type %s", ""),
653 28 : ct->name, crypto ? crypto->et->name : "(unkeyed)");
654 : } else {
655 5278 : ret = 0;
656 : }
657 5326 : krb5_data_free (&c.checksum);
658 5326 : return ret;
659 : }
660 :
661 : static krb5_error_code
662 1607545 : verify_checksum(krb5_context context,
663 : krb5_crypto crypto,
664 : unsigned usage, /* not krb5_key_usage */
665 : void *data,
666 : size_t len,
667 : krb5_flags flags,
668 : Checksum *cksum)
669 : {
670 22128 : struct krb5_crypto_iov iov[1];
671 :
672 1607545 : iov[0].data.data = data;
673 1607545 : iov[0].data.length = len;
674 1607545 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
675 :
676 1607545 : return verify_checksum_iov(context, crypto, usage, iov, 1, flags, cksum);
677 : }
678 :
679 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
680 488757 : krb5_verify_checksum(krb5_context context,
681 : krb5_crypto crypto,
682 : krb5_key_usage usage,
683 : void *data,
684 : size_t len,
685 : Checksum *cksum)
686 : {
687 8429 : struct _krb5_checksum_type *ct;
688 8429 : unsigned keyusage;
689 :
690 488757 : ct = _krb5_find_checksum(cksum->cksumtype);
691 488757 : if(ct == NULL) {
692 2 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
693 2 : N_("checksum type %d not supported", ""),
694 2 : cksum->cksumtype);
695 2 : return KRB5_PROG_SUMTYPE_NOSUPP;
696 : }
697 :
698 488755 : if (arcfour_checksum_p(ct, crypto)) {
699 1553 : keyusage = usage;
700 1553 : _krb5_usage2arcfour(context, &keyusage);
701 : } else
702 487202 : keyusage = CHECKSUM_USAGE(usage);
703 :
704 497184 : return verify_checksum(context, crypto, keyusage,
705 : data, len, crypto_flags(crypto), cksum);
706 : }
707 :
708 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
709 1089695 : krb5_crypto_get_checksum_type(krb5_context context,
710 : krb5_crypto crypto,
711 : krb5_cksumtype *type)
712 : {
713 1089695 : struct _krb5_checksum_type *ct = NULL;
714 :
715 1089695 : if (crypto != NULL) {
716 1089695 : ct = crypto->et->keyed_checksum;
717 1089695 : if (ct == NULL)
718 0 : ct = crypto->et->checksum;
719 : }
720 :
721 1089695 : if (ct == NULL) {
722 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
723 0 : N_("checksum type not found", ""));
724 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
725 : }
726 :
727 1089695 : *type = ct->type;
728 :
729 1089695 : return 0;
730 : }
731 :
732 :
733 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
734 957240 : krb5_checksumsize(krb5_context context,
735 : krb5_cksumtype type,
736 : size_t *size)
737 : {
738 957240 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
739 957240 : if(ct == NULL) {
740 15 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
741 15 : N_("checksum type %d not supported", ""),
742 : type);
743 15 : return KRB5_PROG_SUMTYPE_NOSUPP;
744 : }
745 957225 : *size = ct->checksumsize;
746 957225 : return 0;
747 : }
748 :
749 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
750 264359 : krb5_checksum_is_keyed(krb5_context context,
751 : krb5_cksumtype type)
752 : {
753 264359 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
754 264359 : if(ct == NULL) {
755 2 : if (context)
756 2 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
757 2 : N_("checksum type %d not supported", ""),
758 : type);
759 2 : return KRB5_PROG_SUMTYPE_NOSUPP;
760 : }
761 264357 : return ct->flags & F_KEYED;
762 : }
763 :
764 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
765 51162 : krb5_checksum_is_collision_proof(krb5_context context,
766 : krb5_cksumtype type)
767 : {
768 51162 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
769 51162 : if(ct == NULL) {
770 0 : if (context)
771 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
772 0 : N_("checksum type %d not supported", ""),
773 : type);
774 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
775 : }
776 51162 : return ct->flags & F_CPROOF;
777 : }
778 :
779 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
780 0 : krb5_checksum_disable(krb5_context context,
781 : krb5_cksumtype type)
782 : {
783 0 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
784 0 : if(ct == NULL) {
785 0 : if (context)
786 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
787 0 : N_("checksum type %d not supported", ""),
788 : type);
789 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
790 : }
791 0 : ct->flags |= F_DISABLED;
792 0 : return 0;
793 : }
794 :
795 : /************************************************************
796 : * *
797 : ************************************************************/
798 :
799 : KRB5_LIB_FUNCTION struct _krb5_encryption_type * KRB5_LIB_CALL
800 12718278 : _krb5_find_enctype(krb5_enctype type)
801 : {
802 397559 : int i;
803 46987276 : for(i = 0; i < _krb5_num_etypes; i++)
804 46539522 : if(_krb5_etypes[i]->type == type)
805 12270524 : return _krb5_etypes[i];
806 434102 : return NULL;
807 : }
808 :
809 :
810 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
811 881097 : krb5_enctype_to_string(krb5_context context,
812 : krb5_enctype etype,
813 : char **string)
814 : {
815 31790 : struct _krb5_encryption_type *e;
816 881097 : e = _krb5_find_enctype(etype);
817 881097 : if(e == NULL) {
818 223834 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
819 223834 : N_("encryption type %d not supported", ""),
820 : etype);
821 223834 : *string = NULL;
822 223834 : return KRB5_PROG_ETYPE_NOSUPP;
823 : }
824 657263 : *string = strdup(e->name);
825 657263 : if (*string == NULL)
826 0 : return krb5_enomem(context);
827 632299 : return 0;
828 : }
829 :
830 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
831 415811 : krb5_string_to_enctype(krb5_context context,
832 : const char *string,
833 : krb5_enctype *etype)
834 : {
835 0 : int i;
836 3994878 : for(i = 0; i < _krb5_num_etypes; i++) {
837 3720954 : if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
838 141887 : *etype = _krb5_etypes[i]->type;
839 141887 : return 0;
840 : }
841 3579067 : if(_krb5_etypes[i]->alias != NULL &&
842 1932241 : strcasecmp(_krb5_etypes[i]->alias, string) == 0){
843 0 : *etype = _krb5_etypes[i]->type;
844 0 : return 0;
845 : }
846 : }
847 273924 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
848 273924 : N_("encryption type %s not supported", ""),
849 : string);
850 273924 : return KRB5_PROG_ETYPE_NOSUPP;
851 : }
852 :
853 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
854 30260 : krb5_enctype_to_keytype(krb5_context context,
855 : krb5_enctype etype,
856 : krb5_keytype *keytype)
857 : {
858 30260 : struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
859 30260 : if(e == NULL) {
860 0 : return unsupported_enctype (context, etype);
861 : }
862 30260 : *keytype = (krb5_keytype)e->keytype->type;
863 30260 : return 0;
864 : }
865 :
866 : /**
867 : * Check if a enctype is valid, return 0 if it is.
868 : *
869 : * @param context Kerberos context
870 : * @param etype enctype to check if its valid or not
871 : *
872 : * @return Return an error code for an failure or 0 on success (enctype valid).
873 : * @ingroup krb5_crypto
874 : */
875 :
876 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
877 1599683 : krb5_enctype_valid(krb5_context context,
878 : krb5_enctype etype)
879 : {
880 1599683 : struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
881 1599683 : if(e && (e->flags & F_DISABLED) == 0)
882 1336519 : return 0;
883 223808 : if (context == NULL)
884 0 : return KRB5_PROG_ETYPE_NOSUPP;
885 223808 : if(e == NULL) {
886 223808 : return unsupported_enctype (context, etype);
887 : }
888 : /* Must be (e->flags & F_DISABLED) */
889 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
890 0 : N_("encryption type %s is disabled", ""),
891 : e->name);
892 0 : return KRB5_PROG_ETYPE_NOSUPP;
893 : }
894 :
895 : /**
896 : * Return the coresponding encryption type for a checksum type.
897 : *
898 : * @param context Kerberos context
899 : * @param ctype The checksum type to get the result enctype for
900 : * @param etype The returned encryption, when the matching etype is
901 : * not found, etype is set to ETYPE_NULL.
902 : *
903 : * @return Return an error code for an failure or 0 on success.
904 : * @ingroup krb5_crypto
905 : */
906 :
907 :
908 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
909 221 : krb5_cksumtype_to_enctype(krb5_context context,
910 : krb5_cksumtype ctype,
911 : krb5_enctype *etype)
912 : {
913 0 : int i;
914 :
915 221 : *etype = ETYPE_NULL;
916 :
917 951 : for(i = 0; i < _krb5_num_etypes; i++) {
918 915 : if(_krb5_etypes[i]->keyed_checksum &&
919 843 : _krb5_etypes[i]->keyed_checksum->type == ctype)
920 : {
921 185 : *etype = _krb5_etypes[i]->type;
922 185 : return 0;
923 : }
924 : }
925 :
926 36 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
927 36 : N_("checksum type %d not supported", ""),
928 : (int)ctype);
929 36 : return KRB5_PROG_SUMTYPE_NOSUPP;
930 : }
931 :
932 :
933 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
934 0 : krb5_cksumtype_valid(krb5_context context,
935 : krb5_cksumtype ctype)
936 : {
937 0 : struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
938 0 : if (c == NULL) {
939 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
940 0 : N_("checksum type %d not supported", ""),
941 : ctype);
942 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
943 : }
944 0 : if (c->flags & F_DISABLED) {
945 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
946 0 : N_("checksum type %s is disabled", ""),
947 : c->name);
948 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
949 : }
950 0 : return 0;
951 : }
952 :
953 : static krb5_boolean
954 7279890 : derived_crypto(krb5_context context,
955 : krb5_crypto crypto)
956 : {
957 7279890 : return (crypto->et->flags & F_DERIVED) != 0;
958 : }
959 :
960 : #define CHECKSUMSIZE(C) ((C)->checksumsize)
961 : #define CHECKSUMTYPE(C) ((C)->type)
962 :
963 : static krb5_error_code
964 1069009 : encrypt_internal_derived(krb5_context context,
965 : krb5_crypto crypto,
966 : unsigned usage,
967 : const void *data,
968 : size_t len,
969 : krb5_data *result,
970 : void *ivec)
971 : {
972 14139 : size_t sz, block_sz, checksum_sz, total_sz;
973 14139 : Checksum cksum;
974 14139 : unsigned char *p, *q;
975 14139 : krb5_error_code ret;
976 14139 : struct _krb5_key_data *dkey;
977 1069009 : const struct _krb5_encryption_type *et = crypto->et;
978 :
979 1069009 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
980 :
981 1069009 : sz = et->confoundersize + len;
982 1069009 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
983 1069009 : total_sz = block_sz + checksum_sz;
984 1069009 : p = calloc(1, total_sz);
985 1069009 : if (p == NULL)
986 0 : return krb5_enomem(context);
987 :
988 1069009 : q = p;
989 1069009 : krb5_generate_random_block(q, et->confoundersize); /* XXX */
990 1069009 : q += et->confoundersize;
991 1069009 : memcpy(q, data, len);
992 :
993 1083148 : ret = create_checksum(context,
994 1069009 : et->keyed_checksum,
995 : crypto,
996 1069009 : INTEGRITY_USAGE(usage),
997 : p,
998 : block_sz,
999 : 0,
1000 : &cksum);
1001 1069009 : if(ret == 0 && cksum.checksum.length != checksum_sz) {
1002 0 : free_Checksum (&cksum);
1003 0 : krb5_clear_error_message (context);
1004 0 : ret = KRB5_CRYPTO_INTERNAL;
1005 : }
1006 1069009 : if(ret)
1007 0 : goto fail;
1008 1069009 : memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1009 1069009 : free_Checksum (&cksum);
1010 1069009 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1011 1069009 : if(ret)
1012 0 : goto fail;
1013 1069009 : ret = _key_schedule(context, dkey);
1014 1069009 : if(ret)
1015 0 : goto fail;
1016 1069009 : ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1017 1069009 : if (ret)
1018 0 : goto fail;
1019 1069009 : result->data = p;
1020 1069009 : result->length = total_sz;
1021 1069009 : return 0;
1022 0 : fail:
1023 0 : memset(p, 0, total_sz);
1024 0 : free(p);
1025 0 : return ret;
1026 : }
1027 :
1028 : static krb5_error_code
1029 0 : encrypt_internal_enc_then_cksum(krb5_context context,
1030 : krb5_crypto crypto,
1031 : unsigned usage,
1032 : const void *data,
1033 : size_t len,
1034 : krb5_data *result,
1035 : void *ivec)
1036 : {
1037 0 : size_t sz, block_sz, checksum_sz, total_sz;
1038 0 : Checksum cksum;
1039 0 : unsigned char *p, *q, *ivc = NULL;
1040 0 : krb5_error_code ret;
1041 0 : struct _krb5_key_data *dkey;
1042 0 : const struct _krb5_encryption_type *et = crypto->et;
1043 :
1044 0 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1045 :
1046 0 : sz = et->confoundersize + len;
1047 0 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1048 0 : total_sz = block_sz + checksum_sz;
1049 0 : p = calloc(1, total_sz);
1050 0 : if (p == NULL)
1051 0 : return krb5_enomem(context);
1052 :
1053 0 : q = p;
1054 0 : krb5_generate_random_block(q, et->confoundersize); /* XXX */
1055 0 : q += et->confoundersize;
1056 0 : memcpy(q, data, len);
1057 :
1058 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1059 0 : if(ret)
1060 0 : goto fail;
1061 0 : ret = _key_schedule(context, dkey);
1062 0 : if(ret)
1063 0 : goto fail;
1064 :
1065 : /* XXX EVP style update API would avoid needing to allocate here */
1066 0 : ivc = malloc(et->blocksize + block_sz);
1067 0 : if (ivc == NULL) {
1068 0 : ret = krb5_enomem(context);
1069 0 : goto fail;
1070 : }
1071 0 : if (ivec)
1072 0 : memcpy(ivc, ivec, et->blocksize);
1073 : else
1074 0 : memset(ivc, 0, et->blocksize);
1075 :
1076 0 : ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1077 0 : if (ret)
1078 0 : goto fail;
1079 0 : memcpy(&ivc[et->blocksize], p, block_sz);
1080 :
1081 0 : ret = create_checksum(context,
1082 0 : et->keyed_checksum,
1083 : crypto,
1084 0 : INTEGRITY_USAGE(usage),
1085 : ivc,
1086 0 : et->blocksize + block_sz,
1087 : 0,
1088 : &cksum);
1089 0 : if(ret == 0 && cksum.checksum.length != checksum_sz) {
1090 0 : free_Checksum (&cksum);
1091 0 : krb5_clear_error_message (context);
1092 0 : ret = KRB5_CRYPTO_INTERNAL;
1093 : }
1094 0 : if(ret)
1095 0 : goto fail;
1096 0 : memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1097 0 : free_Checksum (&cksum);
1098 0 : result->data = p;
1099 0 : result->length = total_sz;
1100 0 : free(ivc);
1101 0 : return 0;
1102 0 : fail:
1103 0 : memset_s(p, total_sz, 0, total_sz);
1104 0 : free(p);
1105 0 : free(ivc);
1106 0 : return ret;
1107 : }
1108 :
1109 : static krb5_error_code
1110 0 : encrypt_internal(krb5_context context,
1111 : krb5_crypto crypto,
1112 : const void *data,
1113 : size_t len,
1114 : krb5_data *result,
1115 : void *ivec)
1116 : {
1117 0 : size_t sz, block_sz, checksum_sz;
1118 0 : Checksum cksum;
1119 0 : unsigned char *p, *q;
1120 0 : krb5_error_code ret;
1121 0 : const struct _krb5_encryption_type *et = crypto->et;
1122 :
1123 0 : checksum_sz = CHECKSUMSIZE(et->checksum);
1124 :
1125 0 : sz = et->confoundersize + checksum_sz + len;
1126 0 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1127 0 : p = calloc(1, block_sz);
1128 0 : if (p == NULL)
1129 0 : return krb5_enomem(context);
1130 :
1131 0 : q = p;
1132 0 : krb5_generate_random_block(q, et->confoundersize); /* XXX */
1133 0 : q += et->confoundersize;
1134 0 : memset(q, 0, checksum_sz);
1135 0 : q += checksum_sz;
1136 0 : memcpy(q, data, len);
1137 :
1138 0 : ret = create_checksum(context,
1139 0 : et->checksum,
1140 : crypto,
1141 : 0,
1142 : p,
1143 : block_sz,
1144 : KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM,
1145 : &cksum);
1146 0 : if(ret == 0 && cksum.checksum.length != checksum_sz) {
1147 0 : krb5_clear_error_message (context);
1148 0 : free_Checksum(&cksum);
1149 0 : ret = KRB5_CRYPTO_INTERNAL;
1150 : }
1151 0 : if(ret)
1152 0 : goto fail;
1153 0 : memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
1154 0 : free_Checksum(&cksum);
1155 0 : ret = _key_schedule(context, &crypto->key);
1156 0 : if(ret)
1157 0 : goto fail;
1158 0 : ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
1159 0 : if (ret) {
1160 0 : memset(p, 0, block_sz);
1161 0 : free(p);
1162 0 : return ret;
1163 : }
1164 0 : result->data = p;
1165 0 : result->length = block_sz;
1166 0 : return 0;
1167 0 : fail:
1168 0 : memset(p, 0, block_sz);
1169 0 : free(p);
1170 0 : return ret;
1171 : }
1172 :
1173 : static krb5_error_code
1174 26903 : encrypt_internal_special(krb5_context context,
1175 : krb5_crypto crypto,
1176 : int usage,
1177 : const void *data,
1178 : size_t len,
1179 : krb5_data *result,
1180 : void *ivec)
1181 : {
1182 26903 : struct _krb5_encryption_type *et = crypto->et;
1183 26903 : size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1184 26903 : size_t sz = len + cksum_sz + et->confoundersize;
1185 18 : char *tmp, *p;
1186 18 : krb5_error_code ret;
1187 :
1188 26903 : tmp = malloc (sz);
1189 26903 : if (tmp == NULL)
1190 0 : return krb5_enomem(context);
1191 26903 : p = tmp;
1192 26903 : memset (p, 0, cksum_sz);
1193 26903 : p += cksum_sz;
1194 26903 : krb5_generate_random_block(p, et->confoundersize);
1195 26903 : p += et->confoundersize;
1196 26903 : memcpy (p, data, len);
1197 26903 : ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
1198 26903 : if (ret) {
1199 0 : memset(tmp, 0, sz);
1200 0 : free(tmp);
1201 0 : return ret;
1202 : }
1203 26903 : result->data = tmp;
1204 26903 : result->length = sz;
1205 26903 : return 0;
1206 : }
1207 :
1208 : static krb5_error_code
1209 1118790 : decrypt_internal_derived(krb5_context context,
1210 : krb5_crypto crypto,
1211 : unsigned usage,
1212 : void *data,
1213 : size_t len,
1214 : krb5_data *result,
1215 : void *ivec)
1216 : {
1217 13699 : size_t checksum_sz;
1218 13699 : Checksum cksum;
1219 13699 : unsigned char *p;
1220 13699 : krb5_error_code ret;
1221 13699 : struct _krb5_key_data *dkey;
1222 1118790 : struct _krb5_encryption_type *et = crypto->et;
1223 13699 : unsigned long l;
1224 :
1225 1118790 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1226 1118790 : if (len < checksum_sz + et->confoundersize) {
1227 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1228 0 : N_("Encrypted data shorter then "
1229 : "checksum + confounder", ""));
1230 0 : return KRB5_BAD_MSIZE;
1231 : }
1232 :
1233 1118790 : if (((len - checksum_sz) % et->padsize) != 0) {
1234 0 : krb5_clear_error_message(context);
1235 0 : return KRB5_BAD_MSIZE;
1236 : }
1237 :
1238 1118790 : p = malloc(len);
1239 1118790 : if (len != 0 && p == NULL)
1240 0 : return krb5_enomem(context);
1241 1118790 : memcpy(p, data, len);
1242 :
1243 1118790 : len -= checksum_sz;
1244 :
1245 1118790 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1246 1118790 : if(ret) {
1247 0 : free(p);
1248 0 : return ret;
1249 : }
1250 1118790 : ret = _key_schedule(context, dkey);
1251 1118790 : if(ret) {
1252 0 : free(p);
1253 0 : return ret;
1254 : }
1255 1118790 : ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1256 1118790 : if (ret) {
1257 0 : free(p);
1258 0 : return ret;
1259 : }
1260 :
1261 1118790 : cksum.checksum.data = p + len;
1262 1118790 : cksum.checksum.length = checksum_sz;
1263 1118790 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1264 :
1265 1118790 : ret = verify_checksum(context,
1266 : crypto,
1267 1105091 : INTEGRITY_USAGE(usage),
1268 : p,
1269 : len,
1270 : 0,
1271 : &cksum);
1272 1118790 : if(ret) {
1273 419 : free(p);
1274 419 : return ret;
1275 : }
1276 1118371 : l = len - et->confoundersize;
1277 1118371 : memmove(p, p + et->confoundersize, l);
1278 1118371 : result->data = p;
1279 1118371 : result->length = l;
1280 1118371 : return 0;
1281 : }
1282 :
1283 : static krb5_error_code
1284 0 : decrypt_internal_enc_then_cksum(krb5_context context,
1285 : krb5_crypto crypto,
1286 : unsigned usage,
1287 : void *data,
1288 : size_t len,
1289 : krb5_data *result,
1290 : void *ivec)
1291 : {
1292 0 : size_t checksum_sz;
1293 0 : Checksum cksum;
1294 0 : unsigned char *p;
1295 0 : krb5_error_code ret;
1296 0 : struct _krb5_key_data *dkey;
1297 0 : struct _krb5_encryption_type *et = crypto->et;
1298 0 : unsigned long l;
1299 :
1300 0 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1301 0 : if (len < checksum_sz + et->confoundersize) {
1302 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1303 0 : N_("Encrypted data shorter then "
1304 : "checksum + confounder", ""));
1305 0 : return KRB5_BAD_MSIZE;
1306 : }
1307 :
1308 0 : if (((len - checksum_sz) % et->padsize) != 0) {
1309 0 : krb5_clear_error_message(context);
1310 0 : return KRB5_BAD_MSIZE;
1311 : }
1312 :
1313 0 : len -= checksum_sz;
1314 :
1315 0 : p = malloc(et->blocksize + len);
1316 0 : if (p == NULL)
1317 0 : return krb5_enomem(context);
1318 :
1319 0 : if (ivec)
1320 0 : memcpy(p, ivec, et->blocksize);
1321 : else
1322 0 : memset(p, 0, et->blocksize);
1323 0 : memcpy(&p[et->blocksize], data, len);
1324 :
1325 0 : cksum.checksum.data = (unsigned char *)data + len;
1326 0 : cksum.checksum.length = checksum_sz;
1327 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1328 :
1329 0 : ret = verify_checksum(context,
1330 : crypto,
1331 0 : INTEGRITY_USAGE(usage),
1332 : p,
1333 0 : et->blocksize + len,
1334 : 0,
1335 : &cksum);
1336 0 : if(ret) {
1337 0 : free(p);
1338 0 : return ret;
1339 : }
1340 :
1341 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1342 0 : if(ret) {
1343 0 : free(p);
1344 0 : return ret;
1345 : }
1346 0 : ret = _key_schedule(context, dkey);
1347 0 : if(ret) {
1348 0 : free(p);
1349 0 : return ret;
1350 : }
1351 0 : ret = (*et->encrypt)(context, dkey, &p[et->blocksize], len, 0, usage, ivec);
1352 0 : if (ret) {
1353 0 : free(p);
1354 0 : return ret;
1355 : }
1356 :
1357 0 : l = len - et->confoundersize;
1358 0 : memmove(p, p + et->blocksize + et->confoundersize, l);
1359 0 : result->data = p;
1360 0 : result->length = l;
1361 0 : return 0;
1362 : }
1363 :
1364 : static krb5_error_code
1365 0 : decrypt_internal(krb5_context context,
1366 : krb5_crypto crypto,
1367 : void *data,
1368 : size_t len,
1369 : krb5_data *result,
1370 : void *ivec)
1371 : {
1372 0 : krb5_error_code ret;
1373 0 : unsigned char *p;
1374 0 : Checksum cksum;
1375 0 : size_t checksum_sz, l;
1376 0 : struct _krb5_encryption_type *et = crypto->et;
1377 :
1378 0 : if ((len % et->padsize) != 0) {
1379 0 : krb5_clear_error_message(context);
1380 0 : return KRB5_BAD_MSIZE;
1381 : }
1382 0 : checksum_sz = CHECKSUMSIZE(et->checksum);
1383 0 : if (len < checksum_sz + et->confoundersize) {
1384 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1385 0 : N_("Encrypted data shorter then "
1386 : "checksum + confounder", ""));
1387 0 : return KRB5_BAD_MSIZE;
1388 : }
1389 :
1390 0 : p = malloc(len);
1391 0 : if (len != 0 && p == NULL)
1392 0 : return krb5_enomem(context);
1393 0 : memcpy(p, data, len);
1394 :
1395 0 : ret = _key_schedule(context, &crypto->key);
1396 0 : if(ret) {
1397 0 : free(p);
1398 0 : return ret;
1399 : }
1400 0 : ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1401 0 : if (ret) {
1402 0 : free(p);
1403 0 : return ret;
1404 : }
1405 0 : ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1406 0 : if(ret) {
1407 0 : free(p);
1408 0 : return ret;
1409 : }
1410 0 : memset(p + et->confoundersize, 0, checksum_sz);
1411 0 : cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1412 0 : ret = verify_checksum(context, NULL, 0, p, len,
1413 : KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM, &cksum);
1414 0 : free_Checksum(&cksum);
1415 0 : if(ret) {
1416 0 : free(p);
1417 0 : return ret;
1418 : }
1419 0 : l = len - et->confoundersize - checksum_sz;
1420 0 : memmove(p, p + et->confoundersize + checksum_sz, l);
1421 0 : result->data = p;
1422 0 : result->length = l;
1423 0 : return 0;
1424 : }
1425 :
1426 : static krb5_error_code
1427 21212 : decrypt_internal_special(krb5_context context,
1428 : krb5_crypto crypto,
1429 : int usage,
1430 : void *data,
1431 : size_t len,
1432 : krb5_data *result,
1433 : void *ivec)
1434 : {
1435 21212 : struct _krb5_encryption_type *et = crypto->et;
1436 21212 : size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1437 21212 : size_t sz = len - cksum_sz - et->confoundersize;
1438 18 : unsigned char *p;
1439 18 : krb5_error_code ret;
1440 :
1441 21212 : if ((len % et->padsize) != 0) {
1442 0 : krb5_clear_error_message(context);
1443 0 : return KRB5_BAD_MSIZE;
1444 : }
1445 21212 : if (len < cksum_sz + et->confoundersize) {
1446 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1447 0 : N_("Encrypted data shorter then "
1448 : "checksum + confounder", ""));
1449 0 : return KRB5_BAD_MSIZE;
1450 : }
1451 :
1452 21212 : p = malloc (len);
1453 21212 : if (p == NULL)
1454 0 : return krb5_enomem(context);
1455 21212 : memcpy(p, data, len);
1456 :
1457 21212 : ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1458 21212 : if (ret) {
1459 17 : free(p);
1460 17 : return ret;
1461 : }
1462 :
1463 21195 : memmove (p, p + cksum_sz + et->confoundersize, sz);
1464 21195 : result->data = p;
1465 21195 : result->length = sz;
1466 21195 : return 0;
1467 : }
1468 :
1469 : static krb5_crypto_iov *
1470 4275417 : iov_find(krb5_crypto_iov *data, size_t num_data, unsigned type)
1471 : {
1472 2625 : size_t i;
1473 21681080 : for (i = 0; i < num_data; i++)
1474 20538852 : if (data[i].flags == type)
1475 3130564 : return &data[i];
1476 1140915 : return NULL;
1477 : }
1478 :
1479 : static size_t
1480 1567907 : iov_enc_data_len(krb5_crypto_iov *data, int num_data)
1481 : {
1482 2625 : size_t i, len;
1483 :
1484 12543256 : for (len = 0, i = 0; i < num_data; i++) {
1485 10975349 : if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1486 7839535 : continue;
1487 3135814 : len += data[i].data.length;
1488 : }
1489 :
1490 1567907 : return len;
1491 : }
1492 :
1493 : static size_t
1494 0 : iov_sign_data_len(krb5_crypto_iov *data, int num_data)
1495 : {
1496 : size_t i, len;
1497 :
1498 0 : for (len = 0, i = 0; i < num_data; i++) {
1499 : /* Can't use should_sign, because we must only count data, not
1500 : * header/trailer */
1501 0 : if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
1502 0 : data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
1503 0 : len += data[i].data.length;
1504 : }
1505 :
1506 0 : return len;
1507 : }
1508 :
1509 : static krb5_error_code
1510 0 : iov_coalesce(krb5_context context,
1511 : krb5_data *prefix,
1512 : krb5_crypto_iov *data,
1513 : int num_data,
1514 : krb5_boolean inc_sign_data,
1515 : krb5_data *out)
1516 : {
1517 0 : unsigned char *p, *q;
1518 0 : krb5_crypto_iov *hiv, *piv;
1519 0 : size_t len;
1520 0 : unsigned int i;
1521 :
1522 0 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1523 :
1524 0 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1525 :
1526 0 : len = 0;
1527 0 : if (prefix)
1528 0 : len += prefix->length;
1529 0 : len += hiv->data.length;
1530 0 : if (inc_sign_data)
1531 0 : len += iov_sign_data_len(data, num_data);
1532 : else
1533 0 : len += iov_enc_data_len(data, num_data);
1534 0 : if (piv)
1535 0 : len += piv->data.length;
1536 :
1537 0 : p = q = malloc(len);
1538 0 : if (p == NULL)
1539 0 : return krb5_enomem(context);
1540 :
1541 0 : if (prefix) {
1542 0 : memcpy(q, prefix->data, prefix->length);
1543 0 : q += prefix->length;
1544 : }
1545 0 : memcpy(q, hiv->data.data, hiv->data.length);
1546 0 : q += hiv->data.length;
1547 0 : for (i = 0; i < num_data; i++) {
1548 0 : if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
1549 0 : (inc_sign_data && data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)) {
1550 0 : memcpy(q, data[i].data.data, data[i].data.length);
1551 0 : q += data[i].data.length;
1552 : }
1553 : }
1554 0 : if (piv)
1555 0 : memset(q, 0, piv->data.length);
1556 :
1557 0 : out->length = len;
1558 0 : out->data = p;
1559 :
1560 0 : return 0;
1561 : }
1562 :
1563 : static krb5_error_code
1564 0 : iov_uncoalesce(krb5_context context,
1565 : krb5_data *enc_data,
1566 : krb5_crypto_iov *data,
1567 : int num_data)
1568 : {
1569 0 : unsigned char *q = enc_data->data;
1570 0 : krb5_crypto_iov *hiv, *piv;
1571 0 : unsigned int i;
1572 :
1573 0 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1574 :
1575 0 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1576 :
1577 0 : memcpy(hiv->data.data, q, hiv->data.length);
1578 0 : q += hiv->data.length;
1579 :
1580 0 : for (i = 0; i < num_data; i++) {
1581 0 : if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1582 0 : continue;
1583 0 : memcpy(data[i].data.data, q, data[i].data.length);
1584 0 : q += data[i].data.length;
1585 : }
1586 0 : if (piv)
1587 0 : memcpy(piv->data.data, q, piv->data.length);
1588 :
1589 0 : return 0;
1590 : }
1591 :
1592 : static krb5_error_code
1593 1142228 : iov_pad_validate(const struct _krb5_encryption_type *et,
1594 : krb5_crypto_iov *data,
1595 : int num_data,
1596 : krb5_crypto_iov **ppiv)
1597 : {
1598 1313 : krb5_crypto_iov *piv;
1599 1313 : size_t sz, headersz, block_sz, pad_sz, len;
1600 :
1601 1142228 : len = iov_enc_data_len(data, num_data);
1602 :
1603 1142228 : headersz = et->confoundersize;
1604 :
1605 1142228 : sz = headersz + len;
1606 1142228 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1607 :
1608 1142228 : pad_sz = block_sz - sz;
1609 :
1610 1142228 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1611 : /* its ok to have no TYPE_PADDING if there is no padding */
1612 1142228 : if (piv == NULL && pad_sz != 0)
1613 0 : return KRB5_BAD_MSIZE;
1614 1142228 : if (piv) {
1615 0 : if (piv->data.length < pad_sz)
1616 0 : return KRB5_BAD_MSIZE;
1617 0 : piv->data.length = pad_sz;
1618 0 : if (pad_sz)
1619 0 : memset(piv->data.data, 0, pad_sz);
1620 : else
1621 0 : piv = NULL;
1622 : }
1623 :
1624 1142228 : *ppiv = piv;
1625 1142228 : return 0;
1626 : }
1627 :
1628 : /**
1629 : * Inline encrypt a kerberos message
1630 : *
1631 : * @param context Kerberos context
1632 : * @param crypto Kerberos crypto context
1633 : * @param usage Key usage for this buffer
1634 : * @param data array of buffers to process
1635 : * @param num_data length of array
1636 : * @param ivec initial cbc/cts vector
1637 : *
1638 : * @return Return an error code or 0.
1639 : * @ingroup krb5_crypto
1640 : *
1641 : * Kerberos encrypted data look like this:
1642 : *
1643 : * 1. KRB5_CRYPTO_TYPE_HEADER
1644 : * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1645 : * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1646 : * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1647 : * commonly used headers and trailers.
1648 : * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1649 : * 4. KRB5_CRYPTO_TYPE_TRAILER
1650 : */
1651 :
1652 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1653 1142228 : krb5_encrypt_iov_ivec(krb5_context context,
1654 : krb5_crypto crypto,
1655 : unsigned usage,
1656 : krb5_crypto_iov *data,
1657 : int num_data,
1658 : void *ivec)
1659 : {
1660 1313 : size_t headersz, trailersz;
1661 1313 : Checksum cksum;
1662 1313 : krb5_data enc_data, sign_data;
1663 1313 : krb5_error_code ret;
1664 1313 : struct _krb5_key_data *dkey;
1665 1142228 : const struct _krb5_encryption_type *et = crypto->et;
1666 1313 : krb5_crypto_iov *tiv, *piv, *hiv;
1667 :
1668 1142228 : if (num_data < 0) {
1669 0 : krb5_clear_error_message(context);
1670 0 : return KRB5_CRYPTO_INTERNAL;
1671 : }
1672 :
1673 1142228 : if(!derived_crypto(context, crypto)) {
1674 0 : krb5_clear_error_message(context);
1675 0 : return KRB5_CRYPTO_INTERNAL;
1676 : }
1677 :
1678 1142228 : krb5_data_zero(&enc_data);
1679 1142228 : krb5_data_zero(&sign_data);
1680 :
1681 1142228 : headersz = et->confoundersize;
1682 1142228 : trailersz = CHECKSUMSIZE(et->keyed_checksum);
1683 :
1684 : /* header */
1685 1142228 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1686 1142228 : if (hiv == NULL || hiv->data.length != headersz)
1687 0 : return KRB5_BAD_MSIZE;
1688 1142228 : krb5_generate_random_block(hiv->data.data, hiv->data.length);
1689 :
1690 : /* padding */
1691 1142228 : ret = iov_pad_validate(et, data, num_data, &piv);
1692 1142228 : if(ret)
1693 0 : goto cleanup;
1694 :
1695 : /* trailer */
1696 1142228 : tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1697 1142228 : if (tiv == NULL || tiv->data.length != trailersz) {
1698 0 : ret = KRB5_BAD_MSIZE;
1699 0 : goto cleanup;
1700 : }
1701 :
1702 1142228 : if (et->flags & F_ENC_THEN_CKSUM) {
1703 0 : unsigned char old_ivec[EVP_MAX_IV_LENGTH];
1704 0 : krb5_data ivec_data;
1705 :
1706 0 : heim_assert(et->blocksize <= sizeof(old_ivec),
1707 : "blocksize too big for ivec buffer");
1708 :
1709 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1710 0 : if(ret)
1711 0 : goto cleanup;
1712 :
1713 0 : ret = _key_schedule(context, dkey);
1714 0 : if(ret)
1715 0 : goto cleanup;
1716 :
1717 0 : if (ivec)
1718 0 : memcpy(old_ivec, ivec, et->blocksize);
1719 : else
1720 0 : memset(old_ivec, 0, et->blocksize);
1721 :
1722 0 : if (et->encrypt_iov != NULL) {
1723 0 : ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
1724 : ivec);
1725 0 : if (ret)
1726 0 : goto cleanup;
1727 : } else {
1728 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1729 0 : if (ret)
1730 0 : goto cleanup;
1731 :
1732 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1733 : 1, usage, ivec);
1734 0 : if (ret)
1735 0 : goto cleanup;
1736 :
1737 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1738 0 : if (ret)
1739 0 : goto cleanup;
1740 : }
1741 :
1742 0 : ivec_data.length = et->blocksize;
1743 0 : ivec_data.data = old_ivec;
1744 :
1745 0 : ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
1746 0 : if(ret)
1747 0 : goto cleanup;
1748 :
1749 0 : ret = create_checksum(context,
1750 0 : et->keyed_checksum,
1751 : crypto,
1752 0 : INTEGRITY_USAGE(usage),
1753 : sign_data.data,
1754 : sign_data.length,
1755 : 0,
1756 : &cksum);
1757 :
1758 0 : if(ret == 0 && cksum.checksum.length != trailersz) {
1759 0 : free_Checksum (&cksum);
1760 0 : krb5_clear_error_message (context);
1761 0 : ret = KRB5_CRYPTO_INTERNAL;
1762 : }
1763 0 : if (ret)
1764 0 : goto cleanup;
1765 :
1766 : /* save cksum at end */
1767 0 : memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1768 0 : free_Checksum (&cksum);
1769 :
1770 : } else {
1771 1142228 : cksum.checksum = tiv->data;
1772 1143541 : ret = create_checksum_iov(context,
1773 1142228 : et->keyed_checksum,
1774 : crypto,
1775 1142228 : INTEGRITY_USAGE(usage),
1776 : data,
1777 : num_data,
1778 : 0,
1779 : &cksum);
1780 1142228 : if (ret)
1781 0 : goto cleanup;
1782 :
1783 : /* create_checksum may realloc the derived key space, so any keys
1784 : * obtained before it was called may no longer be valid */
1785 1142228 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1786 1142228 : if(ret)
1787 0 : goto cleanup;
1788 :
1789 1142228 : ret = _key_schedule(context, dkey);
1790 1142228 : if(ret)
1791 0 : goto cleanup;
1792 :
1793 1142228 : if (et->encrypt_iov != NULL) {
1794 1142228 : ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
1795 : ivec);
1796 1142228 : if (ret)
1797 0 : goto cleanup;
1798 : } else {
1799 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1800 0 : if (ret)
1801 0 : goto cleanup;
1802 :
1803 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1804 : 1, usage, ivec);
1805 0 : if (ret)
1806 0 : goto cleanup;
1807 :
1808 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1809 0 : if (ret)
1810 0 : goto cleanup;
1811 : }
1812 : }
1813 :
1814 0 : cleanup:
1815 1142228 : if (enc_data.data) {
1816 0 : memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
1817 0 : krb5_data_free(&enc_data);
1818 : }
1819 1142228 : if (sign_data.data) {
1820 0 : memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
1821 0 : krb5_data_free(&sign_data);
1822 : }
1823 1140915 : return ret;
1824 : }
1825 :
1826 : /**
1827 : * Inline decrypt a Kerberos message.
1828 : *
1829 : * @param context Kerberos context
1830 : * @param crypto Kerberos crypto context
1831 : * @param usage Key usage for this buffer
1832 : * @param data array of buffers to process
1833 : * @param num_data length of array
1834 : * @param ivec initial cbc/cts vector
1835 : *
1836 : * @return Return an error code or 0.
1837 : * @ingroup krb5_crypto
1838 : *
1839 : * 1. KRB5_CRYPTO_TYPE_HEADER
1840 : * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1841 : * any order, however the receiver have to aware of the
1842 : * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1843 : * protocol headers and trailers. The output data will be of same
1844 : * size as the input data or shorter.
1845 : */
1846 :
1847 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1848 425679 : krb5_decrypt_iov_ivec(krb5_context context,
1849 : krb5_crypto crypto,
1850 : unsigned usage,
1851 : krb5_crypto_iov *data,
1852 : unsigned int num_data,
1853 : void *ivec)
1854 : {
1855 1312 : Checksum cksum;
1856 1312 : krb5_data enc_data, sign_data;
1857 1312 : krb5_error_code ret;
1858 1312 : struct _krb5_key_data *dkey;
1859 425679 : struct _krb5_encryption_type *et = crypto->et;
1860 1312 : krb5_crypto_iov *tiv, *hiv;
1861 :
1862 425679 : if(!derived_crypto(context, crypto)) {
1863 0 : krb5_clear_error_message(context);
1864 0 : return KRB5_CRYPTO_INTERNAL;
1865 : }
1866 :
1867 : /* header */
1868 425679 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1869 425679 : if (hiv == NULL || hiv->data.length != et->confoundersize)
1870 0 : return KRB5_BAD_MSIZE;
1871 :
1872 : /* trailer */
1873 425679 : tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1874 425679 : if (tiv->data.length != CHECKSUMSIZE(et->keyed_checksum))
1875 0 : return KRB5_BAD_MSIZE;
1876 :
1877 : /* padding */
1878 426991 : if ((iov_enc_data_len(data, num_data) % et->padsize) != 0) {
1879 0 : krb5_clear_error_message(context);
1880 0 : return KRB5_BAD_MSIZE;
1881 : }
1882 :
1883 425679 : krb5_data_zero(&enc_data);
1884 425679 : krb5_data_zero(&sign_data);
1885 :
1886 425679 : if (!(et->flags & F_ENC_THEN_CKSUM)) {
1887 425679 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1888 425679 : if(ret)
1889 0 : goto cleanup;
1890 :
1891 425679 : ret = _key_schedule(context, dkey);
1892 425679 : if(ret)
1893 0 : goto cleanup;
1894 :
1895 425679 : if (et->encrypt_iov != NULL) {
1896 425679 : ret = (*et->encrypt_iov)(context, dkey, data, num_data,
1897 : 0, usage, ivec);
1898 425679 : if(ret)
1899 0 : goto cleanup;
1900 : } else {
1901 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1902 0 : if(ret)
1903 0 : goto cleanup;
1904 :
1905 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1906 : 0, usage, ivec);
1907 0 : if(ret)
1908 0 : goto cleanup;
1909 :
1910 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1911 0 : if(ret)
1912 0 : goto cleanup;
1913 : }
1914 :
1915 425679 : cksum.checksum.data = tiv->data.data;
1916 425679 : cksum.checksum.length = tiv->data.length;
1917 425679 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1918 :
1919 425679 : ret = verify_checksum_iov(context, crypto, INTEGRITY_USAGE(usage),
1920 : data, num_data, 0, &cksum);
1921 425679 : if(ret)
1922 0 : goto cleanup;
1923 : } else {
1924 0 : krb5_data ivec_data;
1925 0 : static const unsigned char zero_ivec[EVP_MAX_IV_LENGTH];
1926 :
1927 0 : heim_assert(et->blocksize <= sizeof(zero_ivec),
1928 : "blocksize too big for ivec buffer");
1929 :
1930 0 : ivec_data.length = et->blocksize;
1931 0 : ivec_data.data = ivec ? ivec : rk_UNCONST(zero_ivec);
1932 :
1933 0 : ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
1934 0 : if(ret)
1935 0 : goto cleanup;
1936 :
1937 0 : cksum.checksum.data = tiv->data.data;
1938 0 : cksum.checksum.length = tiv->data.length;
1939 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1940 :
1941 0 : ret = verify_checksum(context,
1942 : crypto,
1943 0 : INTEGRITY_USAGE(usage),
1944 : sign_data.data,
1945 : sign_data.length,
1946 : 0,
1947 : &cksum);
1948 0 : if(ret)
1949 0 : goto cleanup;
1950 :
1951 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1952 0 : if(ret)
1953 0 : goto cleanup;
1954 :
1955 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1956 0 : if(ret)
1957 0 : goto cleanup;
1958 :
1959 0 : ret = _key_schedule(context, dkey);
1960 0 : if(ret)
1961 0 : goto cleanup;
1962 :
1963 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1964 : 0, usage, ivec);
1965 0 : if(ret)
1966 0 : goto cleanup;
1967 :
1968 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1969 0 : if(ret)
1970 0 : goto cleanup;
1971 : }
1972 :
1973 425679 : cleanup:
1974 425679 : if (enc_data.data) {
1975 0 : memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
1976 0 : krb5_data_free(&enc_data);
1977 : }
1978 425679 : if (sign_data.data) {
1979 0 : memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
1980 0 : krb5_data_free(&sign_data);
1981 : }
1982 424367 : return ret;
1983 : }
1984 :
1985 : /**
1986 : * Create a Kerberos message checksum.
1987 : *
1988 : * @param context Kerberos context
1989 : * @param crypto Kerberos crypto context
1990 : * @param usage Key usage for this buffer
1991 : * @param data array of buffers to process
1992 : * @param num_data length of array
1993 : * @param type output data
1994 : *
1995 : * @return Return an error code or 0.
1996 : * @ingroup krb5_crypto
1997 : */
1998 :
1999 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2000 0 : krb5_create_checksum_iov(krb5_context context,
2001 : krb5_crypto crypto,
2002 : unsigned usage,
2003 : krb5_crypto_iov *data,
2004 : unsigned int num_data,
2005 : krb5_cksumtype *type)
2006 : {
2007 0 : Checksum cksum;
2008 0 : krb5_crypto_iov *civ;
2009 0 : struct _krb5_checksum_type *ct;
2010 0 : unsigned keyusage;
2011 0 : krb5_error_code ret;
2012 :
2013 0 : civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
2014 0 : if (civ == NULL)
2015 0 : return KRB5_BAD_MSIZE;
2016 :
2017 0 : ct = crypto->et->keyed_checksum;
2018 0 : if (ct == NULL)
2019 0 : ct = crypto->et->checksum;
2020 :
2021 0 : if(ct == NULL) {
2022 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2023 0 : N_("checksum type not found", ""));
2024 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
2025 : }
2026 :
2027 0 : if (arcfour_checksum_p(ct, crypto)) {
2028 0 : keyusage = usage;
2029 0 : _krb5_usage2arcfour(context, &keyusage);
2030 : } else
2031 0 : keyusage = CHECKSUM_USAGE(usage);
2032 :
2033 0 : if (ct->checksumsize > civ->data.length) {
2034 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
2035 0 : N_("Checksum larger then input buffer", ""));
2036 0 : return KRB5_BAD_MSIZE;
2037 : }
2038 :
2039 0 : cksum.checksum = civ->data;
2040 0 : ret = create_checksum_iov(context, ct, crypto, keyusage,
2041 : data, num_data, crypto_flags(crypto), &cksum);
2042 :
2043 0 : if (ret == 0 && type)
2044 0 : *type = cksum.cksumtype;
2045 :
2046 0 : return ret;
2047 : }
2048 :
2049 : /**
2050 : * Verify a Kerberos message checksum.
2051 : *
2052 : * @param context Kerberos context
2053 : * @param crypto Kerberos crypto context
2054 : * @param usage Key usage for this buffer
2055 : * @param data array of buffers to process
2056 : * @param num_data length of array
2057 : * @param type return checksum type if not NULL
2058 : *
2059 : * @return Return an error code or 0.
2060 : * @ingroup krb5_crypto
2061 : */
2062 :
2063 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2064 0 : krb5_verify_checksum_iov(krb5_context context,
2065 : krb5_crypto crypto,
2066 : unsigned usage,
2067 : krb5_crypto_iov *data,
2068 : unsigned int num_data,
2069 : krb5_cksumtype *type)
2070 : {
2071 0 : struct _krb5_encryption_type *et = crypto->et;
2072 0 : struct _krb5_checksum_type *ct;
2073 0 : Checksum cksum;
2074 0 : krb5_crypto_iov *civ;
2075 0 : krb5_error_code ret;
2076 0 : unsigned keyusage;
2077 :
2078 0 : civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
2079 0 : if (civ == NULL)
2080 0 : return KRB5_BAD_MSIZE;
2081 :
2082 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
2083 0 : cksum.checksum.length = civ->data.length;
2084 0 : cksum.checksum.data = civ->data.data;
2085 :
2086 0 : ct = _krb5_find_checksum(cksum.cksumtype);
2087 0 : if(ct == NULL) {
2088 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2089 0 : N_("checksum type %d not supported", ""),
2090 0 : cksum.cksumtype);
2091 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
2092 : }
2093 :
2094 0 : if (arcfour_checksum_p(ct, crypto)) {
2095 0 : keyusage = usage;
2096 0 : _krb5_usage2arcfour(context, &keyusage);
2097 : } else
2098 0 : keyusage = CHECKSUM_USAGE(usage);
2099 :
2100 0 : ret = verify_checksum_iov(context, crypto, keyusage, data, num_data,
2101 : crypto_flags(crypto), &cksum);
2102 :
2103 0 : if (ret == 0 && type)
2104 0 : *type = cksum.cksumtype;
2105 :
2106 0 : return ret;
2107 : }
2108 :
2109 :
2110 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2111 4322601 : krb5_crypto_length(krb5_context context,
2112 : krb5_crypto crypto,
2113 : int type,
2114 : size_t *len)
2115 : {
2116 4322601 : if (!derived_crypto(context, crypto)) {
2117 0 : krb5_set_error_message(context, EINVAL, "not a derived crypto");
2118 0 : return EINVAL;
2119 : }
2120 :
2121 4322601 : switch(type) {
2122 0 : case KRB5_CRYPTO_TYPE_EMPTY:
2123 0 : *len = 0;
2124 0 : return 0;
2125 1582760 : case KRB5_CRYPTO_TYPE_HEADER:
2126 1582760 : *len = crypto->et->blocksize;
2127 1582760 : return 0;
2128 0 : case KRB5_CRYPTO_TYPE_DATA:
2129 : case KRB5_CRYPTO_TYPE_SIGN_ONLY:
2130 : /* len must already been filled in */
2131 0 : return 0;
2132 1157081 : case KRB5_CRYPTO_TYPE_PADDING:
2133 1157081 : if (crypto->et->padsize > 1)
2134 0 : *len = crypto->et->padsize;
2135 : else
2136 1157081 : *len = 0;
2137 1155584 : return 0;
2138 1582760 : case KRB5_CRYPTO_TYPE_TRAILER:
2139 1582760 : if (crypto->et->keyed_checksum)
2140 1582760 : *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
2141 : else
2142 0 : *len = 0;
2143 1579951 : return 0;
2144 0 : case KRB5_CRYPTO_TYPE_CHECKSUM:
2145 0 : if (crypto->et->keyed_checksum)
2146 0 : *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
2147 : else
2148 0 : *len = CHECKSUMSIZE(crypto->et->checksum);
2149 0 : return 0;
2150 : }
2151 0 : krb5_set_error_message(context, EINVAL,
2152 : "%d not a supported type", type);
2153 0 : return EINVAL;
2154 : }
2155 :
2156 :
2157 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2158 0 : krb5_crypto_length_iov(krb5_context context,
2159 : krb5_crypto crypto,
2160 : krb5_crypto_iov *data,
2161 : unsigned int num_data)
2162 : {
2163 0 : krb5_error_code ret;
2164 0 : size_t i;
2165 :
2166 0 : for (i = 0; i < num_data; i++) {
2167 0 : ret = krb5_crypto_length(context, crypto,
2168 0 : data[i].flags,
2169 0 : &data[i].data.length);
2170 0 : if (ret)
2171 0 : return ret;
2172 : }
2173 0 : return 0;
2174 : }
2175 :
2176 :
2177 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2178 1095912 : krb5_encrypt_ivec(krb5_context context,
2179 : krb5_crypto crypto,
2180 : unsigned usage,
2181 : const void *data,
2182 : size_t len,
2183 : krb5_data *result,
2184 : void *ivec)
2185 : {
2186 14157 : krb5_error_code ret;
2187 :
2188 1095912 : switch (crypto->et->flags & F_CRYPTO_MASK) {
2189 1069009 : case F_RFC3961_ENC:
2190 1069009 : ret = encrypt_internal_derived(context, crypto, usage,
2191 : data, len, result, ivec);
2192 1069009 : break;
2193 26903 : case F_SPECIAL:
2194 26903 : ret = encrypt_internal_special (context, crypto, usage,
2195 : data, len, result, ivec);
2196 26903 : break;
2197 0 : case F_ENC_THEN_CKSUM:
2198 0 : ret = encrypt_internal_enc_then_cksum(context, crypto, usage,
2199 : data, len, result, ivec);
2200 0 : break;
2201 0 : default:
2202 0 : ret = encrypt_internal(context, crypto, data, len, result, ivec);
2203 0 : break;
2204 : }
2205 :
2206 1095912 : return ret;
2207 : }
2208 :
2209 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2210 1095912 : krb5_encrypt(krb5_context context,
2211 : krb5_crypto crypto,
2212 : unsigned usage,
2213 : const void *data,
2214 : size_t len,
2215 : krb5_data *result)
2216 : {
2217 1095912 : return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
2218 : }
2219 :
2220 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2221 267693 : krb5_encrypt_EncryptedData(krb5_context context,
2222 : krb5_crypto crypto,
2223 : unsigned usage,
2224 : void *data,
2225 : size_t len,
2226 : int kvno,
2227 : EncryptedData *result)
2228 : {
2229 267693 : result->etype = CRYPTO_ETYPE(crypto);
2230 267693 : if(kvno){
2231 108800 : ALLOC(result->kvno, 1);
2232 108800 : *result->kvno = kvno;
2233 : }else
2234 158893 : result->kvno = NULL;
2235 267693 : return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
2236 : }
2237 :
2238 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2239 1140002 : krb5_decrypt_ivec(krb5_context context,
2240 : krb5_crypto crypto,
2241 : unsigned usage,
2242 : void *data,
2243 : size_t len,
2244 : krb5_data *result,
2245 : void *ivec)
2246 : {
2247 13717 : krb5_error_code ret;
2248 :
2249 1140002 : switch (crypto->et->flags & F_CRYPTO_MASK) {
2250 1118790 : case F_RFC3961_ENC:
2251 1118790 : ret = decrypt_internal_derived(context, crypto, usage,
2252 : data, len, result, ivec);
2253 1118790 : break;
2254 21212 : case F_SPECIAL:
2255 21212 : ret = decrypt_internal_special(context, crypto, usage,
2256 : data, len, result, ivec);
2257 21212 : break;
2258 0 : case F_ENC_THEN_CKSUM:
2259 0 : ret = decrypt_internal_enc_then_cksum(context, crypto, usage,
2260 : data, len, result, ivec);
2261 0 : break;
2262 0 : default:
2263 0 : ret = decrypt_internal(context, crypto, data, len, result, ivec);
2264 0 : break;
2265 : }
2266 :
2267 1140002 : return ret;
2268 : }
2269 :
2270 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2271 1139998 : krb5_decrypt(krb5_context context,
2272 : krb5_crypto crypto,
2273 : unsigned usage,
2274 : void *data,
2275 : size_t len,
2276 : krb5_data *result)
2277 : {
2278 1139998 : return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
2279 : NULL);
2280 : }
2281 :
2282 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2283 447634 : krb5_decrypt_EncryptedData(krb5_context context,
2284 : krb5_crypto crypto,
2285 : unsigned usage,
2286 : const EncryptedData *e,
2287 : krb5_data *result)
2288 : {
2289 895268 : return krb5_decrypt(context, crypto, usage,
2290 447634 : e->cipher.data, e->cipher.length, result);
2291 : }
2292 :
2293 : /************************************************************
2294 : * *
2295 : ************************************************************/
2296 :
2297 : static krb5_error_code
2298 3219701 : derive_key_rfc3961(krb5_context context,
2299 : struct _krb5_encryption_type *et,
2300 : struct _krb5_key_data *key,
2301 : const void *constant,
2302 : size_t len)
2303 : {
2304 :
2305 3219701 : unsigned char *k = NULL;
2306 3219701 : unsigned int nblocks = 0, i;
2307 3219701 : krb5_error_code ret = 0;
2308 3219701 : struct _krb5_key_type *kt = et->keytype;
2309 :
2310 3219701 : if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
2311 3219701 : nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2312 3219701 : k = malloc(nblocks * et->blocksize);
2313 3219701 : if(k == NULL) {
2314 0 : ret = krb5_enomem(context);
2315 0 : goto out;
2316 : }
2317 3219701 : ret = _krb5_n_fold(constant, len, k, et->blocksize);
2318 3219701 : if (ret) {
2319 0 : krb5_enomem(context);
2320 0 : goto out;
2321 : }
2322 :
2323 9631863 : for(i = 0; i < nblocks; i++) {
2324 6412162 : if(i > 0)
2325 3398928 : memcpy(k + i * et->blocksize,
2326 3192461 : k + (i - 1) * et->blocksize,
2327 : et->blocksize);
2328 6412162 : ret = (*et->encrypt)(context, key, k + i * et->blocksize,
2329 : et->blocksize, 1, 0, NULL);
2330 6412162 : if (ret) {
2331 0 : krb5_set_error_message(context, ret, N_("encrypt failed", ""));
2332 0 : goto out;
2333 : }
2334 : }
2335 : } else {
2336 : /* this case is probably broken, but won't be run anyway */
2337 0 : void *c = malloc(len);
2338 0 : size_t res_len = (kt->bits + 7) / 8;
2339 :
2340 0 : if(len != 0 && c == NULL) {
2341 0 : ret = krb5_enomem(context);
2342 0 : goto out;
2343 : }
2344 0 : memcpy(c, constant, len);
2345 0 : ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
2346 0 : if (ret) {
2347 0 : free(c);
2348 0 : krb5_set_error_message(context, ret, N_("encrypt failed", ""));
2349 0 : goto out;
2350 : }
2351 0 : k = malloc(res_len);
2352 0 : if(res_len != 0 && k == NULL) {
2353 0 : free(c);
2354 0 : ret = krb5_enomem(context);
2355 0 : goto out;
2356 : }
2357 0 : ret = _krb5_n_fold(c, len, k, res_len);
2358 0 : free(c);
2359 0 : if (ret) {
2360 0 : krb5_enomem(context);
2361 0 : goto out;
2362 : }
2363 : }
2364 :
2365 3219701 : if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1)
2366 0 : _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
2367 : else
2368 3219701 : memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
2369 :
2370 3219701 : out:
2371 3219701 : if (k) {
2372 3219701 : memset_s(k, nblocks * et->blocksize, 0, nblocks * et->blocksize);
2373 3219701 : free(k);
2374 : }
2375 3219701 : return ret;
2376 : }
2377 :
2378 : static krb5_error_code
2379 0 : derive_key_sp800_hmac(krb5_context context,
2380 : struct _krb5_encryption_type *et,
2381 : struct _krb5_key_data *key,
2382 : const void *constant,
2383 : size_t len)
2384 : {
2385 0 : krb5_error_code ret;
2386 0 : struct _krb5_key_type *kt = et->keytype;
2387 0 : krb5_data label;
2388 0 : const EVP_MD *md = NULL;
2389 0 : const unsigned char *c = constant;
2390 0 : size_t key_len;
2391 0 : krb5_data K1;
2392 :
2393 0 : ret = _krb5_aes_sha2_md_for_enctype(context, kt->type, &md);
2394 0 : if (ret)
2395 0 : return ret;
2396 :
2397 : /*
2398 : * PRF usage: not handled here (output cannot be longer)
2399 : * Integrity usage: truncated hash (half length)
2400 : * Encryption usage: base key length
2401 : */
2402 0 : if (len == 5 && (c[4] == 0x99 || c[4] == 0x55))
2403 0 : key_len = EVP_MD_size(md) / 2;
2404 : else
2405 0 : key_len = kt->size;
2406 :
2407 0 : ret = krb5_data_alloc(&K1, key_len);
2408 0 : if (ret)
2409 0 : return ret;
2410 :
2411 0 : label.data = (void *)constant;
2412 0 : label.length = len;
2413 :
2414 0 : ret = _krb5_SP800_108_HMAC_KDF(context, &key->key->keyvalue,
2415 : &label, NULL, md, &K1);
2416 0 : if (ret == 0) {
2417 0 : if (key->key->keyvalue.length > key_len)
2418 0 : key->key->keyvalue.length = key_len;
2419 0 : memcpy(key->key->keyvalue.data, K1.data, key_len);
2420 : }
2421 :
2422 0 : memset_s(K1.data, K1.length, 0, K1.length);
2423 0 : krb5_data_free(&K1);
2424 :
2425 0 : return ret;
2426 : }
2427 :
2428 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2429 3219701 : _krb5_derive_key(krb5_context context,
2430 : struct _krb5_encryption_type *et,
2431 : struct _krb5_key_data *key,
2432 : const void *constant,
2433 : size_t len)
2434 : {
2435 103346 : krb5_error_code ret;
2436 :
2437 3219701 : ret = _key_schedule(context, key);
2438 3219701 : if(ret)
2439 0 : return ret;
2440 :
2441 3219701 : switch (et->flags & F_KDF_MASK) {
2442 3219701 : case F_RFC3961_KDF:
2443 3219701 : ret = derive_key_rfc3961(context, et, key, constant, len);
2444 3219701 : break;
2445 0 : case F_SP800_108_HMAC_KDF:
2446 0 : ret = derive_key_sp800_hmac(context, et, key, constant, len);
2447 0 : break;
2448 0 : default:
2449 0 : ret = KRB5_CRYPTO_INTERNAL;
2450 0 : krb5_set_error_message(context, ret,
2451 0 : N_("derive_key() called with unknown keytype (%u)", ""),
2452 0 : et->keytype->type);
2453 0 : break;
2454 : }
2455 :
2456 3219701 : if (key->schedule) {
2457 3219701 : free_key_schedule(context, key, et);
2458 3219701 : key->schedule = NULL;
2459 : }
2460 :
2461 3116355 : return ret;
2462 : }
2463 :
2464 : static struct _krb5_key_data *
2465 2426595 : _new_derived_key(krb5_crypto crypto, unsigned usage)
2466 : {
2467 2426595 : struct _krb5_key_usage *d = crypto->key_usage;
2468 2426595 : d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2469 2426595 : if(d == NULL)
2470 0 : return NULL;
2471 2426595 : crypto->key_usage = d;
2472 2426595 : d += crypto->num_key_usage++;
2473 2426595 : memset(d, 0, sizeof(*d));
2474 2426595 : d->usage = usage;
2475 2426595 : return &d->key;
2476 : }
2477 :
2478 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2479 706544 : krb5_derive_key(krb5_context context,
2480 : const krb5_keyblock *key,
2481 : krb5_enctype etype,
2482 : const void *constant,
2483 : size_t constant_len,
2484 : krb5_keyblock **derived_key)
2485 : {
2486 26528 : krb5_error_code ret;
2487 26528 : struct _krb5_encryption_type *et;
2488 26528 : struct _krb5_key_data d;
2489 :
2490 706544 : *derived_key = NULL;
2491 :
2492 706544 : et = _krb5_find_enctype (etype);
2493 706544 : if (et == NULL) {
2494 0 : return unsupported_enctype (context, etype);
2495 : }
2496 :
2497 706544 : ret = krb5_copy_keyblock(context, key, &d.key);
2498 706544 : if (ret)
2499 0 : return ret;
2500 :
2501 706544 : d.schedule = NULL;
2502 706544 : ret = _krb5_derive_key(context, et, &d, constant, constant_len);
2503 706544 : if (ret == 0)
2504 706544 : ret = krb5_copy_keyblock(context, d.key, derived_key);
2505 706544 : _krb5_free_key_data(context, &d, et);
2506 706544 : return ret;
2507 : }
2508 :
2509 : static krb5_error_code
2510 8579992 : _get_derived_key(krb5_context context,
2511 : krb5_crypto crypto,
2512 : unsigned usage,
2513 : struct _krb5_key_data **key)
2514 : {
2515 82686 : int i;
2516 82686 : struct _krb5_key_data *d;
2517 82686 : unsigned char constant[5];
2518 :
2519 8579992 : *key = NULL;
2520 27530285 : for(i = 0; i < crypto->num_key_usage; i++)
2521 25103690 : if(crypto->key_usage[i].usage == usage) {
2522 6153397 : *key = &crypto->key_usage[i].key;
2523 6153397 : return 0;
2524 : }
2525 2426595 : d = _new_derived_key(crypto, usage);
2526 2426595 : if (d == NULL)
2527 0 : return krb5_enomem(context);
2528 2426595 : *key = d;
2529 2426595 : krb5_copy_keyblock(context, crypto->key.key, &d->key);
2530 2426595 : _krb5_put_int(constant, usage, sizeof(constant));
2531 2426595 : return _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2532 : }
2533 :
2534 : /**
2535 : * Create a crypto context used for all encryption and signature
2536 : * operation. The encryption type to use is taken from the key, but
2537 : * can be overridden with the enctype parameter. This can be useful
2538 : * for encryptions types which is compatiable (DES for example).
2539 : *
2540 : * To free the crypto context, use krb5_crypto_destroy().
2541 : *
2542 : * @param context Kerberos context
2543 : * @param key the key block information with all key data
2544 : * @param etype the encryption type
2545 : * @param crypto the resulting crypto context
2546 : *
2547 : * @return Return an error code or 0.
2548 : *
2549 : * @ingroup krb5_crypto
2550 : */
2551 :
2552 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2553 2005551 : krb5_crypto_init(krb5_context context,
2554 : const krb5_keyblock *key,
2555 : krb5_enctype etype,
2556 : krb5_crypto *crypto)
2557 : {
2558 58798 : krb5_error_code ret;
2559 2005551 : ALLOC(*crypto, 1);
2560 2005551 : if (*crypto == NULL)
2561 0 : return krb5_enomem(context);
2562 2005551 : if(etype == ETYPE_NULL)
2563 1847301 : etype = key->keytype;
2564 2005551 : (*crypto)->et = _krb5_find_enctype(etype);
2565 2005551 : if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2566 0 : free(*crypto);
2567 0 : *crypto = NULL;
2568 0 : return unsupported_enctype(context, etype);
2569 : }
2570 2005551 : if((*crypto)->et->keytype->size != key->keyvalue.length) {
2571 0 : free(*crypto);
2572 0 : *crypto = NULL;
2573 0 : krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2574 : "encryption key has bad length");
2575 0 : return KRB5_BAD_KEYSIZE;
2576 : }
2577 2005551 : ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2578 2005551 : if(ret) {
2579 0 : free(*crypto);
2580 0 : *crypto = NULL;
2581 0 : return ret;
2582 : }
2583 2005551 : (*crypto)->key.schedule = NULL;
2584 2005551 : (*crypto)->num_key_usage = 0;
2585 2005551 : (*crypto)->key_usage = NULL;
2586 2005551 : (*crypto)->flags = 0;
2587 2005551 : return 0;
2588 : }
2589 :
2590 : static void
2591 5815328 : free_key_schedule(krb5_context context,
2592 : struct _krb5_key_data *key,
2593 : struct _krb5_encryption_type *et)
2594 : {
2595 5815328 : if (et->keytype->cleanup)
2596 5815328 : (*et->keytype->cleanup)(context, key);
2597 5815328 : memset(key->schedule->data, 0, key->schedule->length);
2598 5815328 : krb5_free_data(context, key->schedule);
2599 5815328 : }
2600 :
2601 : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
2602 5225203 : _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2603 : struct _krb5_encryption_type *et)
2604 : {
2605 5225203 : krb5_free_keyblock(context, key->key);
2606 5225203 : if(key->schedule) {
2607 2595627 : free_key_schedule(context, key, et);
2608 2595627 : key->schedule = NULL;
2609 : }
2610 5225203 : }
2611 :
2612 : static void
2613 2426595 : free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2614 : struct _krb5_encryption_type *et)
2615 : {
2616 2426595 : _krb5_free_key_data(context, &ku->key, et);
2617 2351417 : }
2618 :
2619 : /**
2620 : * Free a crypto context created by krb5_crypto_init().
2621 : *
2622 : * @param context Kerberos context
2623 : * @param crypto crypto context to free
2624 : *
2625 : * @return Return an error code or 0.
2626 : *
2627 : * @ingroup krb5_crypto
2628 : */
2629 :
2630 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2631 2005502 : krb5_crypto_destroy(krb5_context context,
2632 : krb5_crypto crypto)
2633 : {
2634 58793 : int i;
2635 :
2636 4432097 : for(i = 0; i < crypto->num_key_usage; i++)
2637 2426595 : free_key_usage(context, &crypto->key_usage[i], crypto->et);
2638 2005502 : free(crypto->key_usage);
2639 2005502 : _krb5_free_key_data(context, &crypto->key, crypto->et);
2640 :
2641 2005502 : if (crypto->mdctx)
2642 538264 : EVP_MD_CTX_destroy(crypto->mdctx);
2643 :
2644 2005502 : if (crypto->hmacctx)
2645 1193564 : HMAC_CTX_free(crypto->hmacctx);
2646 :
2647 2005502 : free (crypto);
2648 2005502 : return 0;
2649 : }
2650 :
2651 : /**
2652 : * Return the blocksize used algorithm referenced by the crypto context
2653 : *
2654 : * @param context Kerberos context
2655 : * @param crypto crypto context to query
2656 : * @param blocksize the resulting blocksize
2657 : *
2658 : * @return Return an error code or 0.
2659 : *
2660 : * @ingroup krb5_crypto
2661 : */
2662 :
2663 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2664 1157081 : krb5_crypto_getblocksize(krb5_context context,
2665 : krb5_crypto crypto,
2666 : size_t *blocksize)
2667 : {
2668 1157081 : *blocksize = crypto->et->blocksize;
2669 1157081 : return 0;
2670 : }
2671 :
2672 : /**
2673 : * Return the encryption type used by the crypto context
2674 : *
2675 : * @param context Kerberos context
2676 : * @param crypto crypto context to query
2677 : * @param enctype the resulting encryption type
2678 : *
2679 : * @return Return an error code or 0.
2680 : *
2681 : * @ingroup krb5_crypto
2682 : */
2683 :
2684 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2685 225 : krb5_crypto_getenctype(krb5_context context,
2686 : krb5_crypto crypto,
2687 : krb5_enctype *enctype)
2688 : {
2689 225 : *enctype = crypto->et->type;
2690 225 : return 0;
2691 : }
2692 :
2693 : /**
2694 : * Return the padding size used by the crypto context
2695 : *
2696 : * @param context Kerberos context
2697 : * @param crypto crypto context to query
2698 : * @param padsize the return padding size
2699 : *
2700 : * @return Return an error code or 0.
2701 : *
2702 : * @ingroup krb5_crypto
2703 : */
2704 :
2705 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2706 692512 : krb5_crypto_getpadsize(krb5_context context,
2707 : krb5_crypto crypto,
2708 : size_t *padsize)
2709 : {
2710 692512 : *padsize = crypto->et->padsize;
2711 692512 : return 0;
2712 : }
2713 :
2714 : /**
2715 : * Return the confounder size used by the crypto context
2716 : *
2717 : * @param context Kerberos context
2718 : * @param crypto crypto context to query
2719 : * @param confoundersize the returned confounder size
2720 : *
2721 : * @return Return an error code or 0.
2722 : *
2723 : * @ingroup krb5_crypto
2724 : */
2725 :
2726 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2727 0 : krb5_crypto_getconfoundersize(krb5_context context,
2728 : krb5_crypto crypto,
2729 : size_t *confoundersize)
2730 : {
2731 0 : *confoundersize = crypto->et->confoundersize;
2732 0 : return 0;
2733 : }
2734 :
2735 :
2736 : /**
2737 : * Disable encryption type
2738 : *
2739 : * @param context Kerberos 5 context
2740 : * @param enctype encryption type to disable
2741 : *
2742 : * @return Return an error code or 0.
2743 : *
2744 : * @ingroup krb5_crypto
2745 : */
2746 :
2747 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2748 0 : krb5_enctype_disable(krb5_context context,
2749 : krb5_enctype enctype)
2750 : {
2751 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2752 0 : if(et == NULL) {
2753 0 : if (context)
2754 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2755 0 : N_("encryption type %d not supported", ""),
2756 : enctype);
2757 0 : return KRB5_PROG_ETYPE_NOSUPP;
2758 : }
2759 0 : et->flags |= F_DISABLED;
2760 0 : return 0;
2761 : }
2762 :
2763 : /**
2764 : * Enable encryption type
2765 : *
2766 : * @param context Kerberos 5 context
2767 : * @param enctype encryption type to enable
2768 : *
2769 : * @return Return an error code or 0.
2770 : *
2771 : * @ingroup krb5_crypto
2772 : */
2773 :
2774 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2775 0 : krb5_enctype_enable(krb5_context context,
2776 : krb5_enctype enctype)
2777 : {
2778 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2779 0 : if(et == NULL) {
2780 0 : if (context)
2781 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2782 0 : N_("encryption type %d not supported", ""),
2783 : enctype);
2784 0 : return KRB5_PROG_ETYPE_NOSUPP;
2785 : }
2786 0 : et->flags &= ~F_DISABLED;
2787 0 : return 0;
2788 : }
2789 :
2790 : /**
2791 : * Enable or disable all weak encryption types
2792 : *
2793 : * @param context Kerberos 5 context
2794 : * @param enable true to enable, false to disable
2795 : *
2796 : * @return Return an error code or 0.
2797 : *
2798 : * @ingroup krb5_crypto
2799 : */
2800 :
2801 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2802 0 : krb5_allow_weak_crypto(krb5_context context,
2803 : krb5_boolean enable)
2804 : {
2805 0 : int i;
2806 :
2807 0 : for(i = 0; i < _krb5_num_etypes; i++)
2808 0 : if(_krb5_etypes[i]->flags & F_WEAK) {
2809 0 : if(enable)
2810 0 : _krb5_etypes[i]->flags &= ~F_DISABLED;
2811 : else
2812 0 : _krb5_etypes[i]->flags |= F_DISABLED;
2813 : }
2814 0 : return 0;
2815 : }
2816 :
2817 : /**
2818 : * Returns is the encryption is strong or weak
2819 : *
2820 : * @param context Kerberos 5 context
2821 : * @param enctype encryption type to probe
2822 : *
2823 : * @return Returns true if encryption type is weak or is not supported.
2824 : *
2825 : * @ingroup krb5_crypto
2826 : */
2827 :
2828 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2829 3424 : krb5_is_enctype_weak(krb5_context context, krb5_enctype enctype)
2830 : {
2831 3424 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2832 3424 : if(et == NULL || (et->flags & F_WEAK))
2833 43 : return TRUE;
2834 3381 : return FALSE;
2835 : }
2836 :
2837 : /**
2838 : * Returns whether the encryption type is new or old
2839 : *
2840 : * @param context Kerberos 5 context
2841 : * @param enctype encryption type to probe
2842 : *
2843 : * @return Returns true if encryption type is old or is not supported.
2844 : *
2845 : * @ingroup krb5_crypto
2846 : */
2847 :
2848 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2849 19461 : krb5_is_enctype_old(krb5_context context, krb5_enctype enctype)
2850 : {
2851 19461 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2852 19461 : if (!et || (et->flags & F_OLD))
2853 1477 : return TRUE;
2854 17399 : return FALSE;
2855 : }
2856 :
2857 : /**
2858 : * Returns whether the encryption type should use randomly generated salts
2859 : *
2860 : * @param context Kerberos 5 context
2861 : * @param enctype encryption type to probe
2862 : *
2863 : * @return Returns true if generated salts should have random component
2864 : *
2865 : * @ingroup krb5_crypto
2866 : */
2867 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2868 0 : _krb5_enctype_requires_random_salt(krb5_context context,
2869 : krb5_enctype enctype)
2870 : {
2871 0 : struct _krb5_encryption_type *et;
2872 :
2873 0 : et = _krb5_find_enctype (enctype);
2874 :
2875 0 : return et && (et->flags & F_SP800_108_HMAC_KDF);
2876 : }
2877 :
2878 : static size_t
2879 0 : wrapped_length (krb5_context context,
2880 : krb5_crypto crypto,
2881 : size_t data_len)
2882 : {
2883 0 : struct _krb5_encryption_type *et = crypto->et;
2884 0 : size_t padsize = et->padsize;
2885 0 : size_t checksumsize = CHECKSUMSIZE(et->checksum);
2886 0 : size_t res;
2887 :
2888 0 : res = et->confoundersize + checksumsize + data_len;
2889 0 : res = (res + padsize - 1) / padsize * padsize;
2890 0 : return res;
2891 : }
2892 :
2893 : static size_t
2894 1389382 : wrapped_length_dervied (krb5_context context,
2895 : krb5_crypto crypto,
2896 : size_t data_len)
2897 : {
2898 1389382 : struct _krb5_encryption_type *et = crypto->et;
2899 1389382 : size_t padsize = et->padsize;
2900 8006 : size_t res;
2901 :
2902 1389382 : res = et->confoundersize + data_len;
2903 1389382 : res = (res + padsize - 1) / padsize * padsize;
2904 1389382 : if (et->keyed_checksum)
2905 1389382 : res += et->keyed_checksum->checksumsize;
2906 : else
2907 0 : res += et->checksum->checksumsize;
2908 1389382 : return res;
2909 : }
2910 :
2911 : /*
2912 : * Return the size of an encrypted packet of length `data_len'
2913 : */
2914 :
2915 : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2916 1389382 : krb5_get_wrapped_length (krb5_context context,
2917 : krb5_crypto crypto,
2918 : size_t data_len)
2919 : {
2920 1389382 : if (derived_crypto (context, crypto))
2921 1397388 : return wrapped_length_dervied (context, crypto, data_len);
2922 : else
2923 0 : return wrapped_length (context, crypto, data_len);
2924 : }
2925 :
2926 : /*
2927 : * Return the size of an encrypted packet of length `data_len'
2928 : */
2929 :
2930 : static size_t
2931 0 : crypto_overhead (krb5_context context,
2932 : krb5_crypto crypto)
2933 : {
2934 0 : struct _krb5_encryption_type *et = crypto->et;
2935 0 : size_t res;
2936 :
2937 0 : res = CHECKSUMSIZE(et->checksum);
2938 0 : res += et->confoundersize;
2939 0 : if (et->padsize > 1)
2940 0 : res += et->padsize;
2941 0 : return res;
2942 : }
2943 :
2944 : static size_t
2945 0 : crypto_overhead_dervied (krb5_context context,
2946 : krb5_crypto crypto)
2947 : {
2948 0 : struct _krb5_encryption_type *et = crypto->et;
2949 0 : size_t res;
2950 :
2951 0 : if (et->keyed_checksum)
2952 0 : res = CHECKSUMSIZE(et->keyed_checksum);
2953 : else
2954 0 : res = CHECKSUMSIZE(et->checksum);
2955 0 : res += et->confoundersize;
2956 0 : if (et->padsize > 1)
2957 0 : res += et->padsize;
2958 0 : return res;
2959 : }
2960 :
2961 : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2962 0 : krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2963 : {
2964 0 : if (derived_crypto (context, crypto))
2965 0 : return crypto_overhead_dervied (context, crypto);
2966 : else
2967 0 : return crypto_overhead (context, crypto);
2968 : }
2969 :
2970 : /**
2971 : * Converts the random bytestring to a protocol key according to
2972 : * Kerberos crypto frame work. It may be assumed that all the bits of
2973 : * the input string are equally random, even though the entropy
2974 : * present in the random source may be limited.
2975 : *
2976 : * @param context Kerberos 5 context
2977 : * @param type the enctype resulting key will be of
2978 : * @param data input random data to convert to a key
2979 : * @param size size of input random data, at least krb5_enctype_keysize() long
2980 : * @param key key, output key, free with krb5_free_keyblock_contents()
2981 : *
2982 : * @return Return an error code or 0.
2983 : *
2984 : * @ingroup krb5_crypto
2985 : */
2986 :
2987 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2988 180574 : krb5_random_to_key(krb5_context context,
2989 : krb5_enctype type,
2990 : const void *data,
2991 : size_t size,
2992 : krb5_keyblock *key)
2993 : {
2994 6632 : krb5_error_code ret;
2995 180574 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2996 180574 : if(et == NULL) {
2997 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2998 0 : N_("encryption type %d not supported", ""),
2999 : type);
3000 0 : return KRB5_PROG_ETYPE_NOSUPP;
3001 : }
3002 180574 : if ((et->keytype->bits + 7) / 8 > size) {
3003 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3004 0 : N_("encryption key %s needs %d bytes "
3005 : "of random to make an encryption key "
3006 : "out of it", ""),
3007 0 : et->name, (int)et->keytype->size);
3008 0 : return KRB5_PROG_ETYPE_NOSUPP;
3009 : }
3010 180574 : ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
3011 180574 : if(ret)
3012 0 : return ret;
3013 180574 : key->keytype = type;
3014 180574 : if (et->keytype->random_to_key)
3015 0 : (*et->keytype->random_to_key)(context, key, data, size);
3016 : else
3017 180574 : memcpy(key->keyvalue.data, data, et->keytype->size);
3018 :
3019 173942 : return 0;
3020 : }
3021 :
3022 :
3023 :
3024 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3025 0 : krb5_crypto_prf_length(krb5_context context,
3026 : krb5_enctype type,
3027 : size_t *length)
3028 : {
3029 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
3030 :
3031 0 : if(et == NULL || et->prf_length == 0) {
3032 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3033 0 : N_("encryption type %d not supported", ""),
3034 : type);
3035 0 : return KRB5_PROG_ETYPE_NOSUPP;
3036 : }
3037 :
3038 0 : *length = et->prf_length;
3039 0 : return 0;
3040 : }
3041 :
3042 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3043 714348 : krb5_crypto_prf(krb5_context context,
3044 : const krb5_crypto crypto,
3045 : const krb5_data *input,
3046 : krb5_data *output)
3047 : {
3048 714348 : struct _krb5_encryption_type *et = crypto->et;
3049 :
3050 714348 : krb5_data_zero(output);
3051 :
3052 714348 : if(et->prf == NULL) {
3053 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3054 : "kerberos prf for %s not supported",
3055 : et->name);
3056 0 : return KRB5_PROG_ETYPE_NOSUPP;
3057 : }
3058 :
3059 714348 : return (*et->prf)(context, crypto, input, output);
3060 : }
3061 :
3062 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3063 361074 : krb5_crypto_prfplus(krb5_context context,
3064 : const krb5_crypto crypto,
3065 : const krb5_data *input,
3066 : size_t length,
3067 : krb5_data *output)
3068 : {
3069 13264 : krb5_error_code ret;
3070 13264 : krb5_data input2;
3071 361074 : unsigned char i = 1;
3072 13264 : unsigned char *p;
3073 :
3074 361074 : krb5_data_zero(&input2);
3075 361074 : krb5_data_zero(output);
3076 :
3077 361074 : krb5_clear_error_message(context);
3078 :
3079 361074 : ret = krb5_data_alloc(output, length);
3080 361074 : if (ret) goto out;
3081 361074 : ret = krb5_data_alloc(&input2, input->length + 1);
3082 361074 : if (ret) goto out;
3083 :
3084 361074 : krb5_clear_error_message(context);
3085 :
3086 361074 : memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
3087 :
3088 361074 : p = output->data;
3089 :
3090 1075422 : while (length) {
3091 26528 : krb5_data block;
3092 :
3093 714348 : ((unsigned char *)input2.data)[0] = i++;
3094 :
3095 714348 : ret = krb5_crypto_prf(context, crypto, &input2, &block);
3096 714348 : if (ret)
3097 0 : goto out;
3098 :
3099 714348 : if (block.length < length) {
3100 353274 : memcpy(p, block.data, block.length);
3101 353274 : length -= block.length;
3102 : } else {
3103 361074 : memcpy(p, block.data, length);
3104 361074 : length = 0;
3105 : }
3106 714348 : p += block.length;
3107 714348 : krb5_data_free(&block);
3108 : }
3109 :
3110 361074 : out:
3111 361074 : krb5_data_free(&input2);
3112 361074 : if (ret)
3113 0 : krb5_data_free(output);
3114 361074 : return ret;
3115 : }
3116 :
3117 : /**
3118 : * The FX-CF2 key derivation function, used in FAST and preauth framework.
3119 : *
3120 : * @param context Kerberos 5 context
3121 : * @param crypto1 first key to combine
3122 : * @param crypto2 second key to combine
3123 : * @param pepper1 factor to combine with first key to guarantee uniqueness
3124 : * @param pepper2 factor to combine with second key to guarantee uniqueness
3125 : * @param enctype the encryption type of the resulting key
3126 : * @param res allocated key, free with krb5_free_keyblock_contents()
3127 : *
3128 : * @return Return an error code or 0.
3129 : *
3130 : * @ingroup krb5_crypto
3131 : */
3132 :
3133 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3134 180537 : krb5_crypto_fx_cf2(krb5_context context,
3135 : const krb5_crypto crypto1,
3136 : const krb5_crypto crypto2,
3137 : krb5_data *pepper1,
3138 : krb5_data *pepper2,
3139 : krb5_enctype enctype,
3140 : krb5_keyblock *res)
3141 : {
3142 6632 : krb5_error_code ret;
3143 6632 : krb5_data os1, os2;
3144 6632 : size_t i, keysize;
3145 :
3146 180537 : memset(res, 0, sizeof(*res));
3147 180537 : krb5_data_zero(&os1);
3148 180537 : krb5_data_zero(&os2);
3149 :
3150 180537 : ret = krb5_enctype_keybits(context, enctype, &keysize);
3151 180537 : if (ret)
3152 0 : return ret;
3153 180537 : keysize = (keysize + 7) / 8;
3154 :
3155 180537 : ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
3156 180537 : if (ret)
3157 0 : goto out;
3158 180537 : ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
3159 180537 : if (ret)
3160 0 : goto out;
3161 :
3162 180537 : res->keytype = enctype;
3163 : {
3164 180537 : unsigned char *p1 = os1.data, *p2 = os2.data;
3165 5895321 : for (i = 0; i < keysize; i++)
3166 5714784 : p1[i] ^= p2[i];
3167 : }
3168 180537 : ret = krb5_random_to_key(context, enctype, os1.data, keysize, res);
3169 180537 : out:
3170 180537 : krb5_data_free(&os1);
3171 180537 : krb5_data_free(&os2);
3172 :
3173 180537 : return ret;
3174 : }
3175 :
3176 : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
3177 105538 : _krb5_crypto_set_flags(krb5_context context,
3178 : krb5_crypto crypto,
3179 : krb5_flags flags)
3180 : {
3181 105538 : crypto->flags |= flags;
3182 105538 : }
3183 :
3184 : #ifndef HEIMDAL_SMALLER
3185 :
3186 : /**
3187 : * Deprecated: keytypes don't exist, they are really enctypes.
3188 : *
3189 : * @ingroup krb5_deprecated
3190 : */
3191 :
3192 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3193 0 : krb5_keytype_to_enctypes (krb5_context context,
3194 : krb5_keytype keytype,
3195 : unsigned *len,
3196 : krb5_enctype **val)
3197 : KRB5_DEPRECATED_FUNCTION("Use X instead")
3198 : {
3199 0 : int i;
3200 0 : unsigned n = 0;
3201 0 : krb5_enctype *ret;
3202 :
3203 0 : for (i = _krb5_num_etypes - 1; i >= 0; --i) {
3204 0 : if (_krb5_etypes[i]->keytype->type == keytype
3205 0 : && !(_krb5_etypes[i]->flags & F_PSEUDO)
3206 0 : && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
3207 0 : ++n;
3208 : }
3209 0 : if (n == 0) {
3210 0 : krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
3211 : "Keytype has no mapping");
3212 0 : return KRB5_PROG_KEYTYPE_NOSUPP;
3213 : }
3214 :
3215 0 : ret = malloc(n * sizeof(*ret));
3216 0 : if (ret == NULL && n != 0)
3217 0 : return krb5_enomem(context);
3218 0 : n = 0;
3219 0 : for (i = _krb5_num_etypes - 1; i >= 0; --i) {
3220 0 : if (_krb5_etypes[i]->keytype->type == keytype
3221 0 : && !(_krb5_etypes[i]->flags & F_PSEUDO)
3222 0 : && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
3223 0 : ret[n++] = _krb5_etypes[i]->type;
3224 : }
3225 0 : *len = n;
3226 0 : *val = ret;
3227 0 : return 0;
3228 : }
3229 :
3230 : /**
3231 : * Deprecated: keytypes don't exist, they are really enctypes.
3232 : *
3233 : * @ingroup krb5_deprecated
3234 : */
3235 :
3236 : /* if two enctypes have compatible keys */
3237 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
3238 0 : krb5_enctypes_compatible_keys(krb5_context context,
3239 : krb5_enctype etype1,
3240 : krb5_enctype etype2)
3241 : KRB5_DEPRECATED_FUNCTION("Use X instead")
3242 : {
3243 0 : struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
3244 0 : struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
3245 0 : return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
3246 : }
3247 :
3248 : #endif /* HEIMDAL_SMALLER */
|