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 135984 : unsupported_enctype(krb5_context context, krb5_enctype etype)
63 : {
64 : krb5_error_code ret;
65 : char *name;
66 :
67 135984 : ret = krb5_enctype_to_string(context, etype, &name);
68 135984 : if (ret)
69 135984 : 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 591863 : krb5_enctype_keysize(krb5_context context,
84 : krb5_enctype type,
85 : size_t *keysize)
86 : {
87 591863 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
88 591863 : if(et == NULL) {
89 0 : return unsupported_enctype (context, type);
90 : }
91 591863 : *keysize = et->keytype->size;
92 591863 : return 0;
93 : }
94 :
95 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
96 131047 : krb5_enctype_keybits(krb5_context context,
97 : krb5_enctype type,
98 : size_t *keybits)
99 : {
100 131047 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
101 131047 : if(et == NULL) {
102 0 : return unsupported_enctype (context, type);
103 : }
104 131047 : *keybits = et->keytype->bits;
105 131047 : return 0;
106 : }
107 :
108 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
109 186269 : krb5_generate_random_keyblock(krb5_context context,
110 : krb5_enctype type,
111 : krb5_keyblock *key)
112 : {
113 : krb5_error_code ret;
114 186269 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
115 186269 : if(et == NULL) {
116 0 : return unsupported_enctype (context, type);
117 : }
118 186269 : ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
119 186269 : if(ret)
120 0 : return ret;
121 186269 : key->keytype = type;
122 186269 : if(et->keytype->random_key)
123 0 : (*et->keytype->random_key)(context, key);
124 : else
125 186269 : krb5_generate_random_block(key->keyvalue.data,
126 : key->keyvalue.length);
127 186269 : return 0;
128 : }
129 :
130 : static krb5_error_code
131 9510564 : _key_schedule(krb5_context context,
132 : struct _krb5_key_data *key)
133 : {
134 : krb5_error_code ret;
135 : struct _krb5_encryption_type *et;
136 : struct _krb5_key_type *kt;
137 :
138 9510564 : if (key->schedule != NULL)
139 5192773 : return 0;
140 :
141 4317791 : et = _krb5_find_enctype(key->key->keytype);
142 :
143 4317791 : if (et == NULL) {
144 0 : return unsupported_enctype (context,
145 0 : key->key->keytype);
146 : }
147 :
148 4317791 : kt = et->keytype;
149 :
150 4317791 : if(kt->schedule == NULL)
151 0 : return 0;
152 4317791 : ALLOC(key->schedule, 1);
153 4317791 : if (key->schedule == NULL)
154 0 : return krb5_enomem(context);
155 4317791 : ret = krb5_data_alloc(key->schedule, kt->schedule_size);
156 4317791 : if(ret) {
157 0 : free(key->schedule);
158 0 : key->schedule = NULL;
159 0 : return ret;
160 : }
161 4317791 : (*kt->schedule)(context, kt, key);
162 4317791 : return 0;
163 : }
164 :
165 : /************************************************************
166 : * *
167 : ************************************************************/
168 :
169 : static krb5_error_code
170 526619 : 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 526619 : 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 526619 : 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 526619 : 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 958994 : _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 : unsigned char *ipad, *opad;
221 : unsigned char *key;
222 : struct krb5_crypto_iov *working;
223 : size_t key_len;
224 : size_t i;
225 :
226 958994 : ipad = malloc(cm->blocksize);
227 958994 : if (ipad == NULL)
228 0 : return ENOMEM;
229 :
230 958994 : opad = malloc(cm->blocksize + cm->checksumsize);
231 958994 : if (opad == NULL) {
232 0 : free(ipad);
233 0 : return ENOMEM;
234 : }
235 :
236 958994 : working = calloc(niov + 1, sizeof(struct krb5_crypto_iov));
237 958994 : if (working == NULL) {
238 0 : free(ipad);
239 0 : free(opad);
240 0 : return ENOMEM;
241 : }
242 :
243 958994 : memset(ipad, 0x36, cm->blocksize);
244 958994 : memset(opad, 0x5c, cm->blocksize);
245 :
246 958994 : 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 958994 : key = keyblock->key->keyvalue.data;
260 958994 : key_len = keyblock->key->keyvalue.length;
261 : }
262 16302914 : for(i = 0; i < key_len; i++){
263 15343920 : ipad[i] ^= key[i];
264 15343920 : opad[i] ^= key[i];
265 : }
266 :
267 958994 : working[0].data.data = ipad;
268 958994 : working[0].data.length = cm->blocksize;
269 958994 : working[0].flags = KRB5_CRYPTO_TYPE_DATA;
270 1917988 : for (i = 0; i < niov; i++)
271 958994 : working[i + 1] = iov[i];
272 :
273 958994 : (*cm->checksum)(context, crypto, keyblock, usage, working, niov + 1, result);
274 958994 : memcpy(opad + cm->blocksize, result->checksum.data,
275 : result->checksum.length);
276 :
277 958994 : working[0].data.data = opad;
278 958994 : working[0].data.length = cm->blocksize + cm->checksumsize;
279 958994 : working[0].flags = KRB5_CRYPTO_TYPE_DATA;
280 958994 : (*cm->checksum)(context, crypto, keyblock, usage, working, 1, result);
281 958994 : memset(ipad, 0, cm->blocksize);
282 958994 : free(ipad);
283 958994 : memset(opad, 0, cm->blocksize + cm->checksumsize);
284 958994 : free(opad);
285 958994 : free(working);
286 :
287 958994 : return 0;
288 : }
289 :
290 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
291 958994 : _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 : struct krb5_crypto_iov iov[1];
301 :
302 958994 : iov[0].data.data = (void *) data;
303 958994 : iov[0].data.length = len;
304 958994 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
305 958994 : 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 487394 : 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 487394 : struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
319 : struct _krb5_key_data kd;
320 :
321 : krb5_error_code ret;
322 :
323 487394 : 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 487394 : kd.key = key;
331 487394 : kd.schedule = NULL;
332 :
333 487394 : ret = _krb5_internal_hmac(context, NULL, c, data, len, usage, &kd, result);
334 :
335 487394 : if (kd.schedule)
336 0 : krb5_free_data(context, kd.schedule);
337 :
338 487394 : return ret;
339 : }
340 :
341 : krb5_error_code
342 2303992 : _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 : krb5_error_code ret;
351 : unsigned char hmac[EVP_MAX_MD_SIZE];
352 2303992 : unsigned int hmaclen = sizeof(hmac);
353 :
354 2303992 : ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
355 : EVP_sha1(), NULL);
356 2303992 : if (ret)
357 0 : return ret;
358 :
359 2303992 : heim_assert(result->checksum.length <= hmaclen,
360 : "SHA1 checksum too short");
361 2303992 : memcpy(result->checksum.data, hmac, result->checksum.length);
362 :
363 2303992 : return 0;
364 : }
365 :
366 : krb5_error_code
367 1570650 : _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 : krb5_error_code ret;
376 : unsigned char hmac[EVP_MAX_MD_SIZE];
377 1570650 : unsigned int hmaclen = sizeof(hmac);
378 : krb5_data data;
379 :
380 1570650 : ret = _krb5_evp_hmac_iov(context, crypto, key, iov, niov, hmac, &hmaclen,
381 : EVP_sha1(), NULL);
382 1570650 : if (ret)
383 0 : return ret;
384 :
385 1570650 : data.data = hmac;
386 1570650 : data.length = min(hmaclen, verify->checksum.length);
387 :
388 1570650 : if(krb5_data_ct_cmp(&data, &verify->checksum) != 0)
389 325 : return KRB5KRB_AP_ERR_BAD_INTEGRITY;
390 :
391 1570325 : 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 3622928 : _krb5_find_checksum(krb5_cksumtype type)
412 : {
413 : int i;
414 22616542 : for(i = 0; i < _krb5_num_checksums; i++)
415 22616528 : if(_krb5_checksum_types[i]->type == type)
416 3622914 : return _krb5_checksum_types[i];
417 14 : return NULL;
418 : }
419 :
420 : static krb5_error_code
421 4016558 : 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 4016558 : krb5_error_code ret = 0;
428 4016558 : struct _krb5_checksum_type *kct = NULL;
429 :
430 4016558 : 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 4016558 : kct = crypto->et->keyed_checksum;
438 4016558 : if (kct == NULL || kct->type != ct->type) {
439 208 : 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 4016454 : if(ct->flags & F_DERIVED)
448 3874642 : ret = _get_derived_key(context, crypto, usage, key);
449 141812 : else if(ct->flags & F_VARIANT) {
450 : 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 141812 : *key = &crypto->key;
462 : }
463 4016454 : if(ret == 0)
464 4016454 : ret = _key_schedule(context, *key);
465 4016454 : return ret;
466 : }
467 :
468 : static krb5_error_code
469 2449014 : 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 : krb5_error_code ret;
479 : struct _krb5_key_data *dkey;
480 :
481 2449014 : if (ct->flags & F_DISABLED) {
482 0 : krb5_clear_error_message (context);
483 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
484 : }
485 2449014 : if (ct->flags & F_KEYED) {
486 2444286 : ret = get_checksum_key(context, crypto, usage, ct, &dkey);
487 2444286 : if (ret)
488 0 : return ret;
489 4728 : } else if ((flags & KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM) == 0) {
490 0 : return EINVAL;
491 : } else
492 4728 : dkey = NULL;
493 :
494 2449014 : result->cksumtype = ct->type;
495 :
496 2449014 : return (*ct->checksum)(context, crypto, dkey, usage, iov, niov, result);
497 : }
498 :
499 : static krb5_error_code
500 1390704 : 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 : int ret;
510 : struct krb5_crypto_iov iov[1];
511 :
512 1390704 : ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
513 1390704 : if (ret)
514 0 : return ret;
515 :
516 1390704 : iov[0].data.data = data;
517 1390704 : iov[0].data.length = len;
518 1390704 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
519 :
520 1390704 : return create_checksum_iov(context, ct, crypto, usage, iov, 1, flags, result);
521 : }
522 :
523 : static int
524 908439 : arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
525 : {
526 1050355 : return (ct->type == CKSUMTYPE_HMAC_MD5) &&
527 141916 : (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
528 : }
529 :
530 : static inline krb5_flags
531 908439 : crypto_flags(krb5_crypto crypto)
532 : {
533 : /* If caller didn't specify a key, unkeyed checksums are the only option */
534 908439 : if (crypto == NULL)
535 77 : return KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM;
536 : else
537 908362 : return crypto->flags;
538 : }
539 :
540 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
541 553802 : 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 553802 : struct _krb5_checksum_type *ct = NULL;
550 : unsigned keyusage;
551 :
552 : /* type 0 -> pick from crypto */
553 553802 : if (type) {
554 4728 : ct = _krb5_find_checksum(type);
555 549074 : } else if (crypto) {
556 549074 : ct = crypto->et->keyed_checksum;
557 549074 : if (ct == NULL)
558 0 : ct = crypto->et->checksum;
559 : }
560 :
561 553802 : 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 553802 : if (arcfour_checksum_p(ct, crypto)) {
569 140294 : keyusage = usage;
570 140294 : _krb5_usage2arcfour(context, &keyusage);
571 : } else
572 413508 : keyusage = CHECKSUM_USAGE(usage);
573 :
574 553802 : return create_checksum(context, ct, crypto, keyusage, data, len,
575 : crypto_flags(crypto), result);
576 : }
577 :
578 : static krb5_error_code
579 1575974 : 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 : krb5_error_code ret;
588 : struct _krb5_key_data *dkey;
589 : Checksum c;
590 : struct _krb5_checksum_type *ct;
591 :
592 1575974 : ct = _krb5_find_checksum(cksum->cksumtype);
593 1575974 : 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 1575974 : 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 1575974 : if (ct->flags & F_KEYED) {
610 1572272 : ret = get_checksum_key(context, crypto, usage, ct, &dkey);
611 1572272 : if (ret)
612 104 : return ret;
613 3702 : } 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_BAD_INTEGRITY,
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 3702 : 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 1575870 : if(ct->verify) {
629 1570650 : ret = (*ct->verify)(context, crypto, dkey, usage, iov, niov, cksum);
630 1570650 : if (ret)
631 975 : krb5_set_error_message(context, ret,
632 325 : N_("Decrypt integrity check failed for checksum "
633 : "type %s, key type %s", ""),
634 325 : ct->name, (crypto != NULL)? crypto->et->name : "(none)");
635 1570650 : return ret;
636 : }
637 :
638 5220 : ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
639 5220 : if (ret)
640 0 : return ret;
641 :
642 5220 : ret = (*ct->checksum)(context, crypto, dkey, usage, iov, niov, &c);
643 5220 : if (ret) {
644 0 : krb5_data_free(&c.checksum);
645 0 : return ret;
646 : }
647 :
648 5220 : if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
649 27 : ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
650 81 : krb5_set_error_message(context, ret,
651 27 : N_("Decrypt integrity check failed for checksum "
652 : "type %s, key type %s", ""),
653 27 : ct->name, crypto ? crypto->et->name : "(unkeyed)");
654 : } else {
655 5193 : ret = 0;
656 : }
657 5220 : krb5_data_free (&c.checksum);
658 5220 : return ret;
659 : }
660 :
661 : static krb5_error_code
662 1239141 : 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 : struct krb5_crypto_iov iov[1];
671 :
672 1239141 : iov[0].data.data = data;
673 1239141 : iov[0].data.length = len;
674 1239141 : iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
675 :
676 1239141 : return verify_checksum_iov(context, crypto, usage, iov, 1, flags, cksum);
677 : }
678 :
679 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
680 354639 : 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 : struct _krb5_checksum_type *ct;
688 : unsigned keyusage;
689 :
690 354639 : ct = _krb5_find_checksum(cksum->cksumtype);
691 354639 : 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 354637 : if (arcfour_checksum_p(ct, crypto)) {
699 1518 : keyusage = usage;
700 1518 : _krb5_usage2arcfour(context, &keyusage);
701 : } else
702 353119 : keyusage = CHECKSUM_USAGE(usage);
703 :
704 354637 : 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 841971 : krb5_crypto_get_checksum_type(krb5_context context,
710 : krb5_crypto crypto,
711 : krb5_cksumtype *type)
712 : {
713 841971 : struct _krb5_checksum_type *ct = NULL;
714 :
715 841971 : if (crypto != NULL) {
716 841971 : ct = crypto->et->keyed_checksum;
717 841971 : if (ct == NULL)
718 0 : ct = crypto->et->checksum;
719 : }
720 :
721 841971 : 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 841971 : *type = ct->type;
728 :
729 841971 : return 0;
730 : }
731 :
732 :
733 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
734 755204 : krb5_checksumsize(krb5_context context,
735 : krb5_cksumtype type,
736 : size_t *size)
737 : {
738 755204 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
739 755204 : if(ct == NULL) {
740 10 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
741 10 : N_("checksum type %d not supported", ""),
742 : type);
743 10 : return KRB5_PROG_SUMTYPE_NOSUPP;
744 : }
745 755194 : *size = ct->checksumsize;
746 755194 : return 0;
747 : }
748 :
749 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
750 190633 : krb5_checksum_is_keyed(krb5_context context,
751 : krb5_cksumtype type)
752 : {
753 190633 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
754 190633 : 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 190631 : return ct->flags & F_KEYED;
762 : }
763 :
764 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
765 37242 : krb5_checksum_is_collision_proof(krb5_context context,
766 : krb5_cksumtype type)
767 : {
768 37242 : struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
769 37242 : 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 37242 : 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 9244327 : _krb5_find_enctype(krb5_enctype type)
801 : {
802 : int i;
803 34075715 : for(i = 0; i < _krb5_num_etypes; i++)
804 33803629 : if(_krb5_etypes[i]->type == type)
805 8972241 : return _krb5_etypes[i];
806 272086 : return NULL;
807 : }
808 :
809 :
810 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
811 579887 : krb5_enctype_to_string(krb5_context context,
812 : krb5_enctype etype,
813 : char **string)
814 : {
815 : struct _krb5_encryption_type *e;
816 579887 : e = _krb5_find_enctype(etype);
817 579887 : if(e == NULL) {
818 135990 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
819 135990 : N_("encryption type %d not supported", ""),
820 : etype);
821 135990 : *string = NULL;
822 135990 : return KRB5_PROG_ETYPE_NOSUPP;
823 : }
824 443897 : *string = strdup(e->name);
825 443897 : if (*string == NULL)
826 0 : return krb5_enomem(context);
827 443897 : return 0;
828 : }
829 :
830 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
831 391770 : krb5_string_to_enctype(krb5_context context,
832 : const char *string,
833 : krb5_enctype *etype)
834 : {
835 : int i;
836 3777566 : for(i = 0; i < _krb5_num_etypes; i++) {
837 3517658 : if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
838 131862 : *etype = _krb5_etypes[i]->type;
839 131862 : return 0;
840 : }
841 5210864 : if(_krb5_etypes[i]->alias != NULL &&
842 1825068 : strcasecmp(_krb5_etypes[i]->alias, string) == 0){
843 0 : *etype = _krb5_etypes[i]->type;
844 0 : return 0;
845 : }
846 : }
847 259908 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
848 259908 : N_("encryption type %s not supported", ""),
849 : string);
850 259908 : return KRB5_PROG_ETYPE_NOSUPP;
851 : }
852 :
853 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
854 28926 : krb5_enctype_to_keytype(krb5_context context,
855 : krb5_enctype etype,
856 : krb5_keytype *keytype)
857 : {
858 28926 : struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
859 28926 : if(e == NULL) {
860 0 : return unsupported_enctype (context, etype);
861 : }
862 28926 : *keytype = e->keytype->type; /* XXX */
863 28926 : 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 1120922 : krb5_enctype_valid(krb5_context context,
878 : krb5_enctype etype)
879 : {
880 1120922 : struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
881 1120922 : if(e && (e->flags & F_DISABLED) == 0)
882 984938 : return 0;
883 135984 : if (context == NULL)
884 0 : return KRB5_PROG_ETYPE_NOSUPP;
885 135984 : if(e == NULL) {
886 135984 : 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 90 : krb5_cksumtype_to_enctype(krb5_context context,
910 : krb5_cksumtype ctype,
911 : krb5_enctype *etype)
912 : {
913 : int i;
914 :
915 90 : *etype = ETYPE_NULL;
916 :
917 494 : for(i = 0; i < _krb5_num_etypes; i++) {
918 876 : if(_krb5_etypes[i]->keyed_checksum &&
919 410 : _krb5_etypes[i]->keyed_checksum->type == ctype)
920 : {
921 62 : *etype = _krb5_etypes[i]->type;
922 62 : return 0;
923 : }
924 : }
925 :
926 28 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
927 28 : N_("checksum type %d not supported", ""),
928 : (int)ctype);
929 28 : 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 6377966 : derived_crypto(krb5_context context,
955 : krb5_crypto crypto)
956 : {
957 6377966 : 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 836902 : 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 : size_t sz, block_sz, checksum_sz, total_sz;
973 : Checksum cksum;
974 : unsigned char *p, *q;
975 : krb5_error_code ret;
976 : struct _krb5_key_data *dkey;
977 836902 : const struct _krb5_encryption_type *et = crypto->et;
978 :
979 836902 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
980 :
981 836902 : sz = et->confoundersize + len;
982 836902 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
983 836902 : total_sz = block_sz + checksum_sz;
984 836902 : p = calloc(1, total_sz);
985 836902 : if (p == NULL)
986 0 : return krb5_enomem(context);
987 :
988 836902 : q = p;
989 836902 : krb5_generate_random_block(q, et->confoundersize); /* XXX */
990 836902 : q += et->confoundersize;
991 836902 : memcpy(q, data, len);
992 :
993 836902 : ret = create_checksum(context,
994 : et->keyed_checksum,
995 : crypto,
996 836902 : INTEGRITY_USAGE(usage),
997 : p,
998 : block_sz,
999 : 0,
1000 : &cksum);
1001 836902 : 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 836902 : if(ret)
1007 0 : goto fail;
1008 836902 : memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
1009 836902 : free_Checksum (&cksum);
1010 836902 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1011 836902 : if(ret)
1012 0 : goto fail;
1013 836902 : ret = _key_schedule(context, dkey);
1014 836902 : if(ret)
1015 0 : goto fail;
1016 836902 : ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1017 836902 : if (ret)
1018 0 : goto fail;
1019 836902 : result->data = p;
1020 836902 : result->length = total_sz;
1021 836902 : 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 : size_t sz, block_sz, checksum_sz, total_sz;
1038 : Checksum cksum;
1039 0 : unsigned char *p, *q, *ivc = NULL;
1040 : krb5_error_code ret;
1041 : 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 : 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 : size_t sz, block_sz, checksum_sz;
1118 : Checksum cksum;
1119 : unsigned char *p, *q;
1120 : 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 : 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 24544 : 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 24544 : struct _krb5_encryption_type *et = crypto->et;
1183 24544 : size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1184 24544 : size_t sz = len + cksum_sz + et->confoundersize;
1185 : char *tmp, *p;
1186 : krb5_error_code ret;
1187 :
1188 24544 : tmp = malloc (sz);
1189 24544 : if (tmp == NULL)
1190 0 : return krb5_enomem(context);
1191 24544 : p = tmp;
1192 24544 : memset (p, 0, cksum_sz);
1193 24544 : p += cksum_sz;
1194 24544 : krb5_generate_random_block(p, et->confoundersize);
1195 24544 : p += et->confoundersize;
1196 24544 : memcpy (p, data, len);
1197 24544 : ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
1198 24544 : if (ret) {
1199 0 : memset(tmp, 0, sz);
1200 0 : free(tmp);
1201 0 : return ret;
1202 : }
1203 24544 : result->data = tmp;
1204 24544 : result->length = sz;
1205 24544 : return 0;
1206 : }
1207 :
1208 : static krb5_error_code
1209 884504 : 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 : size_t checksum_sz;
1218 : Checksum cksum;
1219 : unsigned char *p;
1220 : krb5_error_code ret;
1221 : struct _krb5_key_data *dkey;
1222 884504 : struct _krb5_encryption_type *et = crypto->et;
1223 : unsigned long l;
1224 :
1225 884504 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1226 884504 : 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 + confunder", ""));
1230 0 : return KRB5_BAD_MSIZE;
1231 : }
1232 :
1233 884504 : if (((len - checksum_sz) % et->padsize) != 0) {
1234 0 : krb5_clear_error_message(context);
1235 0 : return KRB5_BAD_MSIZE;
1236 : }
1237 :
1238 884504 : p = malloc(len);
1239 884504 : if (len != 0 && p == NULL)
1240 0 : return krb5_enomem(context);
1241 884504 : memcpy(p, data, len);
1242 :
1243 884504 : len -= checksum_sz;
1244 :
1245 884504 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1246 884504 : if(ret) {
1247 0 : free(p);
1248 0 : return ret;
1249 : }
1250 884504 : ret = _key_schedule(context, dkey);
1251 884504 : if(ret) {
1252 0 : free(p);
1253 0 : return ret;
1254 : }
1255 884504 : ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1256 884504 : if (ret) {
1257 0 : free(p);
1258 0 : return ret;
1259 : }
1260 :
1261 884504 : cksum.checksum.data = p + len;
1262 884504 : cksum.checksum.length = checksum_sz;
1263 884504 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1264 :
1265 884504 : ret = verify_checksum(context,
1266 : crypto,
1267 884504 : INTEGRITY_USAGE(usage),
1268 : p,
1269 : len,
1270 : 0,
1271 : &cksum);
1272 884504 : if(ret) {
1273 279 : free(p);
1274 279 : return ret;
1275 : }
1276 884225 : l = len - et->confoundersize;
1277 884225 : memmove(p, p + et->confoundersize, l);
1278 884225 : result->data = realloc(p, l);
1279 884225 : if(result->data == NULL && l != 0) {
1280 0 : free(p);
1281 0 : return krb5_enomem(context);
1282 : }
1283 884225 : result->length = l;
1284 884225 : return 0;
1285 : }
1286 :
1287 : static krb5_error_code
1288 0 : decrypt_internal_enc_then_cksum(krb5_context context,
1289 : krb5_crypto crypto,
1290 : unsigned usage,
1291 : void *data,
1292 : size_t len,
1293 : krb5_data *result,
1294 : void *ivec)
1295 : {
1296 : size_t checksum_sz;
1297 : Checksum cksum;
1298 : unsigned char *p;
1299 : krb5_error_code ret;
1300 : struct _krb5_key_data *dkey;
1301 0 : struct _krb5_encryption_type *et = crypto->et;
1302 : unsigned long l;
1303 :
1304 0 : checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
1305 0 : if (len < checksum_sz + et->confoundersize) {
1306 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1307 0 : N_("Encrypted data shorter then "
1308 : "checksum + confunder", ""));
1309 0 : return KRB5_BAD_MSIZE;
1310 : }
1311 :
1312 0 : if (((len - checksum_sz) % et->padsize) != 0) {
1313 0 : krb5_clear_error_message(context);
1314 0 : return KRB5_BAD_MSIZE;
1315 : }
1316 :
1317 0 : len -= checksum_sz;
1318 :
1319 0 : p = malloc(et->blocksize + len);
1320 0 : if (p == NULL)
1321 0 : return krb5_enomem(context);
1322 :
1323 0 : if (ivec)
1324 0 : memcpy(p, ivec, et->blocksize);
1325 : else
1326 0 : memset(p, 0, et->blocksize);
1327 0 : memcpy(&p[et->blocksize], data, len);
1328 :
1329 0 : cksum.checksum.data = (unsigned char *)data + len;
1330 0 : cksum.checksum.length = checksum_sz;
1331 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1332 :
1333 0 : ret = verify_checksum(context,
1334 : crypto,
1335 0 : INTEGRITY_USAGE(usage),
1336 : p,
1337 0 : et->blocksize + len,
1338 : 0,
1339 : &cksum);
1340 0 : if(ret) {
1341 0 : free(p);
1342 0 : return ret;
1343 : }
1344 :
1345 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1346 0 : if(ret) {
1347 0 : free(p);
1348 0 : return ret;
1349 : }
1350 0 : ret = _key_schedule(context, dkey);
1351 0 : if(ret) {
1352 0 : free(p);
1353 0 : return ret;
1354 : }
1355 0 : ret = (*et->encrypt)(context, dkey, &p[et->blocksize], len, 0, usage, ivec);
1356 0 : if (ret) {
1357 0 : free(p);
1358 0 : return ret;
1359 : }
1360 :
1361 0 : l = len - et->confoundersize;
1362 0 : memmove(p, p + et->blocksize + et->confoundersize, l);
1363 0 : result->data = realloc(p, l);
1364 0 : if(result->data == NULL && l != 0) {
1365 0 : free(p);
1366 0 : return krb5_enomem(context);
1367 : }
1368 0 : result->length = l;
1369 0 : return 0;
1370 : }
1371 :
1372 : static krb5_error_code
1373 0 : decrypt_internal(krb5_context context,
1374 : krb5_crypto crypto,
1375 : void *data,
1376 : size_t len,
1377 : krb5_data *result,
1378 : void *ivec)
1379 : {
1380 : krb5_error_code ret;
1381 : unsigned char *p;
1382 : Checksum cksum;
1383 : size_t checksum_sz, l;
1384 0 : struct _krb5_encryption_type *et = crypto->et;
1385 :
1386 0 : if ((len % et->padsize) != 0) {
1387 0 : krb5_clear_error_message(context);
1388 0 : return KRB5_BAD_MSIZE;
1389 : }
1390 0 : checksum_sz = CHECKSUMSIZE(et->checksum);
1391 0 : if (len < checksum_sz + et->confoundersize) {
1392 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1393 0 : N_("Encrypted data shorter then "
1394 : "checksum + confunder", ""));
1395 0 : return KRB5_BAD_MSIZE;
1396 : }
1397 :
1398 0 : p = malloc(len);
1399 0 : if (len != 0 && p == NULL)
1400 0 : return krb5_enomem(context);
1401 0 : memcpy(p, data, len);
1402 :
1403 0 : ret = _key_schedule(context, &crypto->key);
1404 0 : if(ret) {
1405 0 : free(p);
1406 0 : return ret;
1407 : }
1408 0 : ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1409 0 : if (ret) {
1410 0 : free(p);
1411 0 : return ret;
1412 : }
1413 0 : ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1414 0 : if(ret) {
1415 0 : free(p);
1416 0 : return ret;
1417 : }
1418 0 : memset(p + et->confoundersize, 0, checksum_sz);
1419 0 : cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1420 0 : ret = verify_checksum(context, NULL, 0, p, len,
1421 : KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM, &cksum);
1422 0 : free_Checksum(&cksum);
1423 0 : if(ret) {
1424 0 : free(p);
1425 0 : return ret;
1426 : }
1427 0 : l = len - et->confoundersize - checksum_sz;
1428 0 : memmove(p, p + et->confoundersize + checksum_sz, l);
1429 0 : result->data = realloc(p, l);
1430 0 : if(result->data == NULL && l != 0) {
1431 0 : free(p);
1432 0 : return krb5_enomem(context);
1433 : }
1434 0 : result->length = l;
1435 0 : return 0;
1436 : }
1437 :
1438 : static krb5_error_code
1439 20510 : decrypt_internal_special(krb5_context context,
1440 : krb5_crypto crypto,
1441 : int usage,
1442 : void *data,
1443 : size_t len,
1444 : krb5_data *result,
1445 : void *ivec)
1446 : {
1447 20510 : struct _krb5_encryption_type *et = crypto->et;
1448 20510 : size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1449 20510 : size_t sz = len - cksum_sz - et->confoundersize;
1450 : unsigned char *p;
1451 : krb5_error_code ret;
1452 :
1453 20510 : if ((len % et->padsize) != 0) {
1454 0 : krb5_clear_error_message(context);
1455 0 : return KRB5_BAD_MSIZE;
1456 : }
1457 20510 : if (len < cksum_sz + et->confoundersize) {
1458 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
1459 0 : N_("Encrypted data shorter then "
1460 : "checksum + confunder", ""));
1461 0 : return KRB5_BAD_MSIZE;
1462 : }
1463 :
1464 20510 : p = malloc (len);
1465 20510 : if (p == NULL)
1466 0 : return krb5_enomem(context);
1467 20510 : memcpy(p, data, len);
1468 :
1469 20510 : ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1470 20510 : if (ret) {
1471 16 : free(p);
1472 16 : return ret;
1473 : }
1474 :
1475 20494 : memmove (p, p + cksum_sz + et->confoundersize, sz);
1476 20494 : result->data = realloc(p, sz);
1477 20494 : if(result->data == NULL && sz != 0) {
1478 0 : free(p);
1479 0 : return krb5_enomem(context);
1480 : }
1481 20494 : result->length = sz;
1482 20494 : return 0;
1483 : }
1484 :
1485 : static krb5_crypto_iov *
1486 3848596 : iov_find(krb5_crypto_iov *data, size_t num_data, unsigned type)
1487 : {
1488 : size_t i;
1489 19627624 : for (i = 0; i < num_data; i++)
1490 18569314 : if (data[i].flags == type)
1491 2790286 : return &data[i];
1492 1058310 : return NULL;
1493 : }
1494 :
1495 : static size_t
1496 1395143 : iov_enc_data_len(krb5_crypto_iov *data, int num_data)
1497 : {
1498 : size_t i, len;
1499 :
1500 11161144 : for (len = 0, i = 0; i < num_data; i++) {
1501 9766001 : if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1502 6975715 : continue;
1503 2790286 : len += data[i].data.length;
1504 : }
1505 :
1506 1395143 : return len;
1507 : }
1508 :
1509 : static size_t
1510 0 : iov_sign_data_len(krb5_crypto_iov *data, int num_data)
1511 : {
1512 : size_t i, len;
1513 :
1514 0 : for (len = 0, i = 0; i < num_data; i++) {
1515 : /* Can't use should_sign, because we must only count data, not
1516 : * header/trailer */
1517 0 : if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
1518 0 : data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)
1519 0 : len += data[i].data.length;
1520 : }
1521 :
1522 0 : return len;
1523 : }
1524 :
1525 : static krb5_error_code
1526 0 : iov_coalesce(krb5_context context,
1527 : krb5_data *prefix,
1528 : krb5_crypto_iov *data,
1529 : int num_data,
1530 : krb5_boolean inc_sign_data,
1531 : krb5_data *out)
1532 : {
1533 : unsigned char *p, *q;
1534 : krb5_crypto_iov *hiv, *piv;
1535 : size_t len;
1536 : unsigned int i;
1537 :
1538 0 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1539 :
1540 0 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1541 :
1542 0 : len = 0;
1543 0 : if (prefix)
1544 0 : len += prefix->length;
1545 0 : len += hiv->data.length;
1546 0 : if (inc_sign_data)
1547 0 : len += iov_sign_data_len(data, num_data);
1548 : else
1549 0 : len += iov_enc_data_len(data, num_data);
1550 0 : if (piv)
1551 0 : len += piv->data.length;
1552 :
1553 0 : p = q = malloc(len);
1554 0 : if (p == NULL)
1555 0 : return krb5_enomem(context);
1556 :
1557 0 : if (prefix) {
1558 0 : memcpy(q, prefix->data, prefix->length);
1559 0 : q += prefix->length;
1560 : }
1561 0 : memcpy(q, hiv->data.data, hiv->data.length);
1562 0 : q += hiv->data.length;
1563 0 : for (i = 0; i < num_data; i++) {
1564 0 : if (data[i].flags == KRB5_CRYPTO_TYPE_DATA ||
1565 0 : (inc_sign_data && data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)) {
1566 0 : memcpy(q, data[i].data.data, data[i].data.length);
1567 0 : q += data[i].data.length;
1568 : }
1569 : }
1570 0 : if (piv)
1571 0 : memset(q, 0, piv->data.length);
1572 :
1573 0 : out->length = len;
1574 0 : out->data = p;
1575 :
1576 0 : return 0;
1577 : }
1578 :
1579 : static krb5_error_code
1580 0 : iov_uncoalesce(krb5_context context,
1581 : krb5_data *enc_data,
1582 : krb5_crypto_iov *data,
1583 : int num_data)
1584 : {
1585 0 : unsigned char *q = enc_data->data;
1586 : krb5_crypto_iov *hiv, *piv;
1587 : unsigned int i;
1588 :
1589 0 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1590 :
1591 0 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1592 :
1593 0 : memcpy(hiv->data.data, q, hiv->data.length);
1594 0 : q += hiv->data.length;
1595 :
1596 0 : for (i = 0; i < num_data; i++) {
1597 0 : if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1598 0 : continue;
1599 0 : memcpy(data[i].data.data, q, data[i].data.length);
1600 0 : q += data[i].data.length;
1601 : }
1602 0 : if (piv)
1603 0 : memcpy(piv->data.data, q, piv->data.length);
1604 :
1605 0 : return 0;
1606 : }
1607 :
1608 : static krb5_error_code
1609 1058310 : iov_pad_validate(const struct _krb5_encryption_type *et,
1610 : krb5_crypto_iov *data,
1611 : int num_data,
1612 : krb5_crypto_iov **ppiv)
1613 : {
1614 : krb5_crypto_iov *piv;
1615 : size_t sz, headersz, block_sz, pad_sz, len;
1616 :
1617 1058310 : len = iov_enc_data_len(data, num_data);
1618 :
1619 1058310 : headersz = et->confoundersize;
1620 :
1621 1058310 : sz = headersz + len;
1622 1058310 : block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1623 :
1624 1058310 : pad_sz = block_sz - sz;
1625 :
1626 1058310 : piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1627 : /* its ok to have no TYPE_PADDING if there is no padding */
1628 1058310 : if (piv == NULL && pad_sz != 0)
1629 0 : return KRB5_BAD_MSIZE;
1630 1058310 : if (piv) {
1631 0 : if (piv->data.length < pad_sz)
1632 0 : return KRB5_BAD_MSIZE;
1633 0 : piv->data.length = pad_sz;
1634 0 : if (pad_sz)
1635 0 : memset(piv->data.data, 0, pad_sz);
1636 : else
1637 0 : piv = NULL;
1638 : }
1639 :
1640 1058310 : *ppiv = piv;
1641 1058310 : return 0;
1642 : }
1643 :
1644 : /**
1645 : * Inline encrypt a kerberos message
1646 : *
1647 : * @param context Kerberos context
1648 : * @param crypto Kerberos crypto context
1649 : * @param usage Key usage for this buffer
1650 : * @param data array of buffers to process
1651 : * @param num_data length of array
1652 : * @param ivec initial cbc/cts vector
1653 : *
1654 : * @return Return an error code or 0.
1655 : * @ingroup krb5_crypto
1656 : *
1657 : * Kerberos encrypted data look like this:
1658 : *
1659 : * 1. KRB5_CRYPTO_TYPE_HEADER
1660 : * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1661 : * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1662 : * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1663 : * commonly used headers and trailers.
1664 : * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1665 : * 4. KRB5_CRYPTO_TYPE_TRAILER
1666 : */
1667 :
1668 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1669 1058310 : krb5_encrypt_iov_ivec(krb5_context context,
1670 : krb5_crypto crypto,
1671 : unsigned usage,
1672 : krb5_crypto_iov *data,
1673 : int num_data,
1674 : void *ivec)
1675 : {
1676 : size_t headersz, trailersz;
1677 : Checksum cksum;
1678 : krb5_data enc_data, sign_data;
1679 : krb5_error_code ret;
1680 : struct _krb5_key_data *dkey;
1681 1058310 : const struct _krb5_encryption_type *et = crypto->et;
1682 : krb5_crypto_iov *tiv, *piv, *hiv;
1683 :
1684 1058310 : if (num_data < 0) {
1685 0 : krb5_clear_error_message(context);
1686 0 : return KRB5_CRYPTO_INTERNAL;
1687 : }
1688 :
1689 1058310 : if(!derived_crypto(context, crypto)) {
1690 0 : krb5_clear_error_message(context);
1691 0 : return KRB5_CRYPTO_INTERNAL;
1692 : }
1693 :
1694 1058310 : krb5_data_zero(&enc_data);
1695 1058310 : krb5_data_zero(&sign_data);
1696 :
1697 1058310 : headersz = et->confoundersize;
1698 1058310 : trailersz = CHECKSUMSIZE(et->keyed_checksum);
1699 :
1700 : /* header */
1701 1058310 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1702 1058310 : if (hiv == NULL || hiv->data.length != headersz)
1703 0 : return KRB5_BAD_MSIZE;
1704 1058310 : krb5_generate_random_block(hiv->data.data, hiv->data.length);
1705 :
1706 : /* padding */
1707 1058310 : ret = iov_pad_validate(et, data, num_data, &piv);
1708 1058310 : if(ret)
1709 0 : goto cleanup;
1710 :
1711 : /* trailer */
1712 1058310 : tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1713 1058310 : if (tiv == NULL || tiv->data.length != trailersz) {
1714 0 : ret = KRB5_BAD_MSIZE;
1715 0 : goto cleanup;
1716 : }
1717 :
1718 1058310 : if (et->flags & F_ENC_THEN_CKSUM) {
1719 : unsigned char old_ivec[EVP_MAX_IV_LENGTH];
1720 : krb5_data ivec_data;
1721 :
1722 0 : heim_assert(et->blocksize <= sizeof(old_ivec),
1723 : "blocksize too big for ivec buffer");
1724 :
1725 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1726 0 : if(ret)
1727 0 : goto cleanup;
1728 :
1729 0 : ret = _key_schedule(context, dkey);
1730 0 : if(ret)
1731 0 : goto cleanup;
1732 :
1733 0 : if (ivec)
1734 0 : memcpy(old_ivec, ivec, et->blocksize);
1735 : else
1736 0 : memset(old_ivec, 0, et->blocksize);
1737 :
1738 0 : if (et->encrypt_iov != NULL) {
1739 0 : ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
1740 : ivec);
1741 0 : if (ret)
1742 0 : goto cleanup;
1743 : } else {
1744 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1745 0 : if (ret)
1746 0 : goto cleanup;
1747 :
1748 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1749 : 1, usage, ivec);
1750 0 : if (ret)
1751 0 : goto cleanup;
1752 :
1753 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1754 0 : if (ret)
1755 0 : goto cleanup;
1756 : }
1757 :
1758 0 : ivec_data.length = et->blocksize;
1759 0 : ivec_data.data = old_ivec;
1760 :
1761 0 : ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
1762 0 : if(ret)
1763 0 : goto cleanup;
1764 :
1765 0 : ret = create_checksum(context,
1766 : et->keyed_checksum,
1767 : crypto,
1768 0 : INTEGRITY_USAGE(usage),
1769 : sign_data.data,
1770 : sign_data.length,
1771 : 0,
1772 : &cksum);
1773 :
1774 0 : if(ret == 0 && cksum.checksum.length != trailersz) {
1775 0 : free_Checksum (&cksum);
1776 0 : krb5_clear_error_message (context);
1777 0 : ret = KRB5_CRYPTO_INTERNAL;
1778 : }
1779 0 : if (ret)
1780 0 : goto cleanup;
1781 :
1782 : /* save cksum at end */
1783 0 : memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1784 0 : free_Checksum (&cksum);
1785 :
1786 : } else {
1787 1058310 : cksum.checksum = tiv->data;
1788 1058310 : ret = create_checksum_iov(context,
1789 : et->keyed_checksum,
1790 : crypto,
1791 1058310 : INTEGRITY_USAGE(usage),
1792 : data,
1793 : num_data,
1794 : 0,
1795 : &cksum);
1796 1058310 : if (ret)
1797 0 : goto cleanup;
1798 :
1799 : /* create_checksum may realloc the derived key space, so any keys
1800 : * obtained before it was called may no longer be valid */
1801 1058310 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1802 1058310 : if(ret)
1803 0 : goto cleanup;
1804 :
1805 1058310 : ret = _key_schedule(context, dkey);
1806 1058310 : if(ret)
1807 0 : goto cleanup;
1808 :
1809 1058310 : if (et->encrypt_iov != NULL) {
1810 1058310 : ret = (*et->encrypt_iov)(context, dkey, data, num_data, 1, usage,
1811 : ivec);
1812 1058310 : if (ret)
1813 0 : goto cleanup;
1814 : } else {
1815 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1816 0 : if (ret)
1817 0 : goto cleanup;
1818 :
1819 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1820 : 1, usage, ivec);
1821 0 : if (ret)
1822 0 : goto cleanup;
1823 :
1824 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1825 0 : if (ret)
1826 0 : goto cleanup;
1827 : }
1828 : }
1829 :
1830 1058310 : cleanup:
1831 1058310 : if (enc_data.data) {
1832 0 : memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
1833 0 : krb5_data_free(&enc_data);
1834 : }
1835 1058310 : if (sign_data.data) {
1836 0 : memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
1837 0 : krb5_data_free(&sign_data);
1838 : }
1839 1058310 : return ret;
1840 : }
1841 :
1842 : /**
1843 : * Inline decrypt a Kerberos message.
1844 : *
1845 : * @param context Kerberos context
1846 : * @param crypto Kerberos crypto context
1847 : * @param usage Key usage for this buffer
1848 : * @param data array of buffers to process
1849 : * @param num_data length of array
1850 : * @param ivec initial cbc/cts vector
1851 : *
1852 : * @return Return an error code or 0.
1853 : * @ingroup krb5_crypto
1854 : *
1855 : * 1. KRB5_CRYPTO_TYPE_HEADER
1856 : * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1857 : * any order, however the receiver have to aware of the
1858 : * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1859 : * protocol headers and trailers. The output data will be of same
1860 : * size as the input data or shorter.
1861 : */
1862 :
1863 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1864 336833 : krb5_decrypt_iov_ivec(krb5_context context,
1865 : krb5_crypto crypto,
1866 : unsigned usage,
1867 : krb5_crypto_iov *data,
1868 : unsigned int num_data,
1869 : void *ivec)
1870 : {
1871 : Checksum cksum;
1872 : krb5_data enc_data, sign_data;
1873 : krb5_error_code ret;
1874 : struct _krb5_key_data *dkey;
1875 336833 : struct _krb5_encryption_type *et = crypto->et;
1876 : krb5_crypto_iov *tiv, *hiv;
1877 :
1878 336833 : if(!derived_crypto(context, crypto)) {
1879 0 : krb5_clear_error_message(context);
1880 0 : return KRB5_CRYPTO_INTERNAL;
1881 : }
1882 :
1883 : /* header */
1884 336833 : hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1885 336833 : if (hiv == NULL || hiv->data.length != et->confoundersize)
1886 0 : return KRB5_BAD_MSIZE;
1887 :
1888 : /* trailer */
1889 336833 : tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1890 336833 : if (tiv->data.length != CHECKSUMSIZE(et->keyed_checksum))
1891 0 : return KRB5_BAD_MSIZE;
1892 :
1893 : /* padding */
1894 336833 : if ((iov_enc_data_len(data, num_data) % et->padsize) != 0) {
1895 0 : krb5_clear_error_message(context);
1896 0 : return KRB5_BAD_MSIZE;
1897 : }
1898 :
1899 336833 : krb5_data_zero(&enc_data);
1900 336833 : krb5_data_zero(&sign_data);
1901 :
1902 336833 : if (!(et->flags & F_ENC_THEN_CKSUM)) {
1903 336833 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1904 336833 : if(ret)
1905 0 : goto cleanup;
1906 :
1907 336833 : ret = _key_schedule(context, dkey);
1908 336833 : if(ret)
1909 0 : goto cleanup;
1910 :
1911 336833 : if (et->encrypt_iov != NULL) {
1912 336833 : ret = (*et->encrypt_iov)(context, dkey, data, num_data,
1913 : 0, usage, ivec);
1914 336833 : if(ret)
1915 0 : goto cleanup;
1916 : } else {
1917 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1918 0 : if(ret)
1919 0 : goto cleanup;
1920 :
1921 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1922 : 0, usage, ivec);
1923 0 : if(ret)
1924 0 : goto cleanup;
1925 :
1926 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1927 0 : if(ret)
1928 0 : goto cleanup;
1929 : }
1930 :
1931 336833 : cksum.checksum.data = tiv->data.data;
1932 336833 : cksum.checksum.length = tiv->data.length;
1933 336833 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1934 :
1935 336833 : ret = verify_checksum_iov(context, crypto, INTEGRITY_USAGE(usage),
1936 : data, num_data, 0, &cksum);
1937 336833 : if(ret)
1938 0 : goto cleanup;
1939 : } else {
1940 : krb5_data ivec_data;
1941 : static unsigned char zero_ivec[EVP_MAX_IV_LENGTH];
1942 :
1943 0 : heim_assert(et->blocksize <= sizeof(zero_ivec),
1944 : "blocksize too big for ivec buffer");
1945 :
1946 0 : ivec_data.length = et->blocksize;
1947 0 : ivec_data.data = ivec ? ivec : zero_ivec;
1948 :
1949 0 : ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data);
1950 0 : if(ret)
1951 0 : goto cleanup;
1952 :
1953 0 : cksum.checksum.data = tiv->data.data;
1954 0 : cksum.checksum.length = tiv->data.length;
1955 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1956 :
1957 0 : ret = verify_checksum(context,
1958 : crypto,
1959 0 : INTEGRITY_USAGE(usage),
1960 : sign_data.data,
1961 : sign_data.length,
1962 : 0,
1963 : &cksum);
1964 0 : if(ret)
1965 0 : goto cleanup;
1966 :
1967 0 : ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data);
1968 0 : if(ret)
1969 0 : goto cleanup;
1970 :
1971 0 : ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1972 0 : if(ret)
1973 0 : goto cleanup;
1974 :
1975 0 : ret = _key_schedule(context, dkey);
1976 0 : if(ret)
1977 0 : goto cleanup;
1978 :
1979 0 : ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length,
1980 : 0, usage, ivec);
1981 0 : if(ret)
1982 0 : goto cleanup;
1983 :
1984 0 : ret = iov_uncoalesce(context, &enc_data, data, num_data);
1985 0 : if(ret)
1986 0 : goto cleanup;
1987 : }
1988 :
1989 336833 : cleanup:
1990 336833 : if (enc_data.data) {
1991 0 : memset_s(enc_data.data, enc_data.length, 0, enc_data.length);
1992 0 : krb5_data_free(&enc_data);
1993 : }
1994 336833 : if (sign_data.data) {
1995 0 : memset_s(sign_data.data, sign_data.length, 0, sign_data.length);
1996 0 : krb5_data_free(&sign_data);
1997 : }
1998 336833 : return ret;
1999 : }
2000 :
2001 : /**
2002 : * Create a Kerberos message checksum.
2003 : *
2004 : * @param context Kerberos context
2005 : * @param crypto Kerberos crypto context
2006 : * @param usage Key usage for this buffer
2007 : * @param data array of buffers to process
2008 : * @param num_data length of array
2009 : * @param type output data
2010 : *
2011 : * @return Return an error code or 0.
2012 : * @ingroup krb5_crypto
2013 : */
2014 :
2015 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2016 0 : krb5_create_checksum_iov(krb5_context context,
2017 : krb5_crypto crypto,
2018 : unsigned usage,
2019 : krb5_crypto_iov *data,
2020 : unsigned int num_data,
2021 : krb5_cksumtype *type)
2022 : {
2023 : Checksum cksum;
2024 : krb5_crypto_iov *civ;
2025 : struct _krb5_checksum_type *ct;
2026 : unsigned keyusage;
2027 : krb5_error_code ret;
2028 :
2029 0 : civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
2030 0 : if (civ == NULL)
2031 0 : return KRB5_BAD_MSIZE;
2032 :
2033 0 : ct = crypto->et->keyed_checksum;
2034 0 : if (ct == NULL)
2035 0 : ct = crypto->et->checksum;
2036 :
2037 0 : if(ct == NULL) {
2038 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2039 0 : N_("checksum type not found", ""));
2040 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
2041 : }
2042 :
2043 0 : if (arcfour_checksum_p(ct, crypto)) {
2044 0 : keyusage = usage;
2045 0 : _krb5_usage2arcfour(context, &keyusage);
2046 : } else
2047 0 : keyusage = CHECKSUM_USAGE(usage);
2048 :
2049 0 : if (ct->checksumsize > civ->data.length) {
2050 0 : krb5_set_error_message(context, KRB5_BAD_MSIZE,
2051 0 : N_("Checksum larger then input buffer", ""));
2052 0 : return KRB5_BAD_MSIZE;
2053 : }
2054 :
2055 0 : cksum.checksum = civ->data;
2056 0 : ret = create_checksum_iov(context, ct, crypto, keyusage,
2057 : data, num_data, crypto_flags(crypto), &cksum);
2058 :
2059 0 : if (ret == 0 && type)
2060 0 : *type = cksum.cksumtype;
2061 :
2062 0 : return ret;
2063 : }
2064 :
2065 : /**
2066 : * Verify a Kerberos message checksum.
2067 : *
2068 : * @param context Kerberos context
2069 : * @param crypto Kerberos crypto context
2070 : * @param usage Key usage for this buffer
2071 : * @param data array of buffers to process
2072 : * @param num_data length of array
2073 : * @param type return checksum type if not NULL
2074 : *
2075 : * @return Return an error code or 0.
2076 : * @ingroup krb5_crypto
2077 : */
2078 :
2079 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2080 0 : krb5_verify_checksum_iov(krb5_context context,
2081 : krb5_crypto crypto,
2082 : unsigned usage,
2083 : krb5_crypto_iov *data,
2084 : unsigned int num_data,
2085 : krb5_cksumtype *type)
2086 : {
2087 0 : struct _krb5_encryption_type *et = crypto->et;
2088 : struct _krb5_checksum_type *ct;
2089 : Checksum cksum;
2090 : krb5_crypto_iov *civ;
2091 : krb5_error_code ret;
2092 : unsigned keyusage;
2093 :
2094 0 : civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
2095 0 : if (civ == NULL)
2096 0 : return KRB5_BAD_MSIZE;
2097 :
2098 0 : cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
2099 0 : cksum.checksum.length = civ->data.length;
2100 0 : cksum.checksum.data = civ->data.data;
2101 :
2102 0 : ct = _krb5_find_checksum(cksum.cksumtype);
2103 0 : if(ct == NULL) {
2104 0 : krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2105 0 : N_("checksum type %d not supported", ""),
2106 0 : cksum.cksumtype);
2107 0 : return KRB5_PROG_SUMTYPE_NOSUPP;
2108 : }
2109 :
2110 0 : if (arcfour_checksum_p(ct, crypto)) {
2111 0 : keyusage = usage;
2112 0 : _krb5_usage2arcfour(context, &keyusage);
2113 : } else
2114 0 : keyusage = CHECKSUM_USAGE(usage);
2115 :
2116 0 : ret = verify_checksum_iov(context, crypto, keyusage, data, num_data,
2117 : crypto_flags(crypto), &cksum);
2118 :
2119 0 : if (ret == 0 && type)
2120 0 : *type = cksum.cksumtype;
2121 :
2122 0 : return ret;
2123 : }
2124 :
2125 :
2126 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2127 3888067 : krb5_crypto_length(krb5_context context,
2128 : krb5_crypto crypto,
2129 : int type,
2130 : size_t *len)
2131 : {
2132 3888067 : if (!derived_crypto(context, crypto)) {
2133 0 : krb5_set_error_message(context, EINVAL, "not a derived crypto");
2134 0 : return EINVAL;
2135 : }
2136 :
2137 3888067 : switch(type) {
2138 0 : case KRB5_CRYPTO_TYPE_EMPTY:
2139 0 : *len = 0;
2140 0 : return 0;
2141 1408300 : case KRB5_CRYPTO_TYPE_HEADER:
2142 1408300 : *len = crypto->et->blocksize;
2143 1408300 : return 0;
2144 0 : case KRB5_CRYPTO_TYPE_DATA:
2145 : case KRB5_CRYPTO_TYPE_SIGN_ONLY:
2146 : /* len must already been filled in */
2147 0 : return 0;
2148 1071467 : case KRB5_CRYPTO_TYPE_PADDING:
2149 1071467 : if (crypto->et->padsize > 1)
2150 0 : *len = crypto->et->padsize;
2151 : else
2152 1071467 : *len = 0;
2153 1071467 : return 0;
2154 1408300 : case KRB5_CRYPTO_TYPE_TRAILER:
2155 1408300 : if (crypto->et->keyed_checksum)
2156 1408300 : *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
2157 : else
2158 0 : *len = 0;
2159 1408300 : return 0;
2160 0 : case KRB5_CRYPTO_TYPE_CHECKSUM:
2161 0 : if (crypto->et->keyed_checksum)
2162 0 : *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
2163 : else
2164 0 : *len = CHECKSUMSIZE(crypto->et->checksum);
2165 0 : return 0;
2166 : }
2167 0 : krb5_set_error_message(context, EINVAL,
2168 : "%d not a supported type", type);
2169 0 : return EINVAL;
2170 : }
2171 :
2172 :
2173 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2174 0 : krb5_crypto_length_iov(krb5_context context,
2175 : krb5_crypto crypto,
2176 : krb5_crypto_iov *data,
2177 : unsigned int num_data)
2178 : {
2179 : krb5_error_code ret;
2180 : size_t i;
2181 :
2182 0 : for (i = 0; i < num_data; i++) {
2183 0 : ret = krb5_crypto_length(context, crypto,
2184 0 : data[i].flags,
2185 0 : &data[i].data.length);
2186 0 : if (ret)
2187 0 : return ret;
2188 : }
2189 0 : return 0;
2190 : }
2191 :
2192 :
2193 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2194 861446 : krb5_encrypt_ivec(krb5_context context,
2195 : krb5_crypto crypto,
2196 : unsigned usage,
2197 : const void *data,
2198 : size_t len,
2199 : krb5_data *result,
2200 : void *ivec)
2201 : {
2202 : krb5_error_code ret;
2203 :
2204 861446 : switch (crypto->et->flags & F_CRYPTO_MASK) {
2205 836902 : case F_RFC3961_ENC:
2206 836902 : ret = encrypt_internal_derived(context, crypto, usage,
2207 : data, len, result, ivec);
2208 836902 : break;
2209 24544 : case F_SPECIAL:
2210 24544 : ret = encrypt_internal_special (context, crypto, usage,
2211 : data, len, result, ivec);
2212 24544 : break;
2213 0 : case F_ENC_THEN_CKSUM:
2214 0 : ret = encrypt_internal_enc_then_cksum(context, crypto, usage,
2215 : data, len, result, ivec);
2216 0 : break;
2217 0 : default:
2218 0 : ret = encrypt_internal(context, crypto, data, len, result, ivec);
2219 0 : break;
2220 : }
2221 :
2222 861446 : return ret;
2223 : }
2224 :
2225 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2226 861446 : krb5_encrypt(krb5_context context,
2227 : krb5_crypto crypto,
2228 : unsigned usage,
2229 : const void *data,
2230 : size_t len,
2231 : krb5_data *result)
2232 : {
2233 861446 : return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
2234 : }
2235 :
2236 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2237 187371 : krb5_encrypt_EncryptedData(krb5_context context,
2238 : krb5_crypto crypto,
2239 : unsigned usage,
2240 : void *data,
2241 : size_t len,
2242 : int kvno,
2243 : EncryptedData *result)
2244 : {
2245 187371 : result->etype = CRYPTO_ETYPE(crypto);
2246 187371 : if(kvno){
2247 71814 : ALLOC(result->kvno, 1);
2248 71814 : *result->kvno = kvno;
2249 : }else
2250 115557 : result->kvno = NULL;
2251 187371 : return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
2252 : }
2253 :
2254 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2255 905014 : krb5_decrypt_ivec(krb5_context context,
2256 : krb5_crypto crypto,
2257 : unsigned usage,
2258 : void *data,
2259 : size_t len,
2260 : krb5_data *result,
2261 : void *ivec)
2262 : {
2263 : krb5_error_code ret;
2264 :
2265 905014 : switch (crypto->et->flags & F_CRYPTO_MASK) {
2266 884504 : case F_RFC3961_ENC:
2267 884504 : ret = decrypt_internal_derived(context, crypto, usage,
2268 : data, len, result, ivec);
2269 884504 : break;
2270 20510 : case F_SPECIAL:
2271 20510 : ret = decrypt_internal_special(context, crypto, usage,
2272 : data, len, result, ivec);
2273 20510 : break;
2274 0 : case F_ENC_THEN_CKSUM:
2275 0 : ret = decrypt_internal_enc_then_cksum(context, crypto, usage,
2276 : data, len, result, ivec);
2277 0 : break;
2278 0 : default:
2279 0 : ret = decrypt_internal(context, crypto, data, len, result, ivec);
2280 0 : break;
2281 : }
2282 :
2283 905014 : return ret;
2284 : }
2285 :
2286 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2287 905014 : krb5_decrypt(krb5_context context,
2288 : krb5_crypto crypto,
2289 : unsigned usage,
2290 : void *data,
2291 : size_t len,
2292 : krb5_data *result)
2293 : {
2294 905014 : return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
2295 : NULL);
2296 : }
2297 :
2298 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2299 340639 : krb5_decrypt_EncryptedData(krb5_context context,
2300 : krb5_crypto crypto,
2301 : unsigned usage,
2302 : const EncryptedData *e,
2303 : krb5_data *result)
2304 : {
2305 340639 : return krb5_decrypt(context, crypto, usage,
2306 : e->cipher.data, e->cipher.length, result);
2307 : }
2308 :
2309 : /************************************************************
2310 : * *
2311 : ************************************************************/
2312 :
2313 : static krb5_error_code
2314 2377561 : derive_key_rfc3961(krb5_context context,
2315 : struct _krb5_encryption_type *et,
2316 : struct _krb5_key_data *key,
2317 : const void *constant,
2318 : size_t len)
2319 : {
2320 :
2321 2377561 : unsigned char *k = NULL;
2322 2377561 : unsigned int nblocks = 0, i;
2323 2377561 : krb5_error_code ret = 0;
2324 2377561 : struct _krb5_key_type *kt = et->keytype;
2325 :
2326 4755122 : if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
2327 2377561 : nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2328 2377561 : k = malloc(nblocks * et->blocksize);
2329 2377561 : if(k == NULL) {
2330 0 : ret = krb5_enomem(context);
2331 0 : goto out;
2332 : }
2333 2377561 : ret = _krb5_n_fold(constant, len, k, et->blocksize);
2334 2377561 : if (ret) {
2335 0 : krb5_enomem(context);
2336 0 : goto out;
2337 : }
2338 :
2339 7110672 : for(i = 0; i < nblocks; i++) {
2340 4733111 : if(i > 0)
2341 4711100 : memcpy(k + i * et->blocksize,
2342 2355550 : k + (i - 1) * et->blocksize,
2343 : et->blocksize);
2344 4733111 : ret = (*et->encrypt)(context, key, k + i * et->blocksize,
2345 : et->blocksize, 1, 0, NULL);
2346 4733111 : if (ret) {
2347 0 : krb5_set_error_message(context, ret, N_("encrypt failed", ""));
2348 0 : goto out;
2349 : }
2350 : }
2351 : } else {
2352 : /* this case is probably broken, but won't be run anyway */
2353 0 : void *c = malloc(len);
2354 0 : size_t res_len = (kt->bits + 7) / 8;
2355 :
2356 0 : if(len != 0 && c == NULL) {
2357 0 : ret = krb5_enomem(context);
2358 0 : goto out;
2359 : }
2360 0 : memcpy(c, constant, len);
2361 0 : ret = (*et->encrypt)(context, key, c, len, 1, 0, NULL);
2362 0 : if (ret) {
2363 0 : free(c);
2364 0 : krb5_set_error_message(context, ret, N_("encrypt failed", ""));
2365 0 : goto out;
2366 : }
2367 0 : k = malloc(res_len);
2368 0 : if(res_len != 0 && k == NULL) {
2369 0 : free(c);
2370 0 : ret = krb5_enomem(context);
2371 0 : goto out;
2372 : }
2373 0 : ret = _krb5_n_fold(c, len, k, res_len);
2374 0 : free(c);
2375 0 : if (ret) {
2376 0 : krb5_enomem(context);
2377 0 : goto out;
2378 : }
2379 : }
2380 :
2381 2377561 : if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1)
2382 0 : _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
2383 : else
2384 2377561 : memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
2385 :
2386 2377561 : out:
2387 2377561 : if (k) {
2388 2377561 : memset_s(k, nblocks * et->blocksize, 0, nblocks * et->blocksize);
2389 2377561 : free(k);
2390 : }
2391 2377561 : return ret;
2392 : }
2393 :
2394 : static krb5_error_code
2395 0 : derive_key_sp800_hmac(krb5_context context,
2396 : struct _krb5_encryption_type *et,
2397 : struct _krb5_key_data *key,
2398 : const void *constant,
2399 : size_t len)
2400 : {
2401 : krb5_error_code ret;
2402 0 : struct _krb5_key_type *kt = et->keytype;
2403 : krb5_data label;
2404 0 : const EVP_MD *md = NULL;
2405 0 : const unsigned char *c = constant;
2406 : size_t key_len;
2407 : krb5_data K1;
2408 :
2409 0 : ret = _krb5_aes_sha2_md_for_enctype(context, kt->type, &md);
2410 0 : if (ret)
2411 0 : return ret;
2412 :
2413 : /*
2414 : * PRF usage: not handled here (output cannot be longer)
2415 : * Integrity usage: truncated hash (half length)
2416 : * Encryption usage: base key length
2417 : */
2418 0 : if (len == 5 && (c[4] == 0x99 || c[4] == 0x55))
2419 0 : key_len = EVP_MD_size(md) / 2;
2420 : else
2421 0 : key_len = kt->size;
2422 :
2423 0 : ret = krb5_data_alloc(&K1, key_len);
2424 0 : if (ret)
2425 0 : return ret;
2426 :
2427 0 : label.data = (void *)constant;
2428 0 : label.length = len;
2429 :
2430 0 : ret = _krb5_SP800_108_HMAC_KDF(context, &key->key->keyvalue,
2431 : &label, NULL, md, &K1);
2432 0 : if (ret == 0) {
2433 0 : if (key->key->keyvalue.length > key_len)
2434 0 : key->key->keyvalue.length = key_len;
2435 0 : memcpy(key->key->keyvalue.data, K1.data, key_len);
2436 : }
2437 :
2438 0 : memset_s(K1.data, K1.length, 0, K1.length);
2439 0 : krb5_data_free(&K1);
2440 :
2441 0 : return ret;
2442 : }
2443 :
2444 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2445 2377561 : _krb5_derive_key(krb5_context context,
2446 : struct _krb5_encryption_type *et,
2447 : struct _krb5_key_data *key,
2448 : const void *constant,
2449 : size_t len)
2450 : {
2451 : krb5_error_code ret;
2452 :
2453 2377561 : ret = _key_schedule(context, key);
2454 2377561 : if(ret)
2455 0 : return ret;
2456 :
2457 2377561 : switch (et->flags & F_KDF_MASK) {
2458 2377561 : case F_RFC3961_KDF:
2459 2377561 : ret = derive_key_rfc3961(context, et, key, constant, len);
2460 2377561 : break;
2461 0 : case F_SP800_108_HMAC_KDF:
2462 0 : ret = derive_key_sp800_hmac(context, et, key, constant, len);
2463 0 : break;
2464 0 : default:
2465 0 : ret = KRB5_CRYPTO_INTERNAL;
2466 0 : krb5_set_error_message(context, ret,
2467 0 : N_("derive_key() called with unknown keytype (%u)", ""),
2468 0 : et->keytype->type);
2469 0 : break;
2470 : }
2471 :
2472 2377561 : if (key->schedule) {
2473 2377561 : free_key_schedule(context, key, et);
2474 2377561 : key->schedule = NULL;
2475 : }
2476 :
2477 2377561 : return ret;
2478 : }
2479 :
2480 : static struct _krb5_key_data *
2481 1798528 : _new_derived_key(krb5_crypto crypto, unsigned usage)
2482 : {
2483 1798528 : struct _krb5_key_usage *d = crypto->key_usage;
2484 1798528 : d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2485 1798528 : if(d == NULL)
2486 0 : return NULL;
2487 1798528 : crypto->key_usage = d;
2488 1798528 : d += crypto->num_key_usage++;
2489 1798528 : memset(d, 0, sizeof(*d));
2490 1798528 : d->usage = usage;
2491 1798528 : return &d->key;
2492 : }
2493 :
2494 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2495 511178 : krb5_derive_key(krb5_context context,
2496 : const krb5_keyblock *key,
2497 : krb5_enctype etype,
2498 : const void *constant,
2499 : size_t constant_len,
2500 : krb5_keyblock **derived_key)
2501 : {
2502 : krb5_error_code ret;
2503 : struct _krb5_encryption_type *et;
2504 : struct _krb5_key_data d;
2505 :
2506 511178 : *derived_key = NULL;
2507 :
2508 511178 : et = _krb5_find_enctype (etype);
2509 511178 : if (et == NULL) {
2510 0 : return unsupported_enctype (context, etype);
2511 : }
2512 :
2513 511178 : ret = krb5_copy_keyblock(context, key, &d.key);
2514 511178 : if (ret)
2515 0 : return ret;
2516 :
2517 511178 : d.schedule = NULL;
2518 511178 : ret = _krb5_derive_key(context, et, &d, constant, constant_len);
2519 511178 : if (ret == 0)
2520 511178 : ret = krb5_copy_keyblock(context, d.key, derived_key);
2521 511178 : _krb5_free_key_data(context, &d, et);
2522 511178 : return ret;
2523 : }
2524 :
2525 : static krb5_error_code
2526 6991191 : _get_derived_key(krb5_context context,
2527 : krb5_crypto crypto,
2528 : unsigned usage,
2529 : struct _krb5_key_data **key)
2530 : {
2531 : int i;
2532 : struct _krb5_key_data *d;
2533 : unsigned char constant[5];
2534 :
2535 6991191 : *key = NULL;
2536 23489078 : for(i = 0; i < crypto->num_key_usage; i++)
2537 21690550 : if(crypto->key_usage[i].usage == usage) {
2538 5192663 : *key = &crypto->key_usage[i].key;
2539 5192663 : return 0;
2540 : }
2541 1798528 : d = _new_derived_key(crypto, usage);
2542 1798528 : if (d == NULL)
2543 0 : return krb5_enomem(context);
2544 1798528 : *key = d;
2545 1798528 : krb5_copy_keyblock(context, crypto->key.key, &d->key);
2546 1798528 : _krb5_put_int(constant, usage, sizeof(constant));
2547 1798528 : return _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2548 : }
2549 :
2550 : /**
2551 : * Create a crypto context used for all encryption and signature
2552 : * operation. The encryption type to use is taken from the key, but
2553 : * can be overridden with the enctype parameter. This can be useful
2554 : * for encryptions types which is compatiable (DES for example).
2555 : *
2556 : * To free the crypto context, use krb5_crypto_destroy().
2557 : *
2558 : * @param context Kerberos context
2559 : * @param key the key block information with all key data
2560 : * @param etype the encryption type
2561 : * @param crypto the resulting crypto context
2562 : *
2563 : * @return Return an error code or 0.
2564 : *
2565 : * @ingroup krb5_crypto
2566 : */
2567 :
2568 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2569 1494323 : krb5_crypto_init(krb5_context context,
2570 : const krb5_keyblock *key,
2571 : krb5_enctype etype,
2572 : krb5_crypto *crypto)
2573 : {
2574 : krb5_error_code ret;
2575 1494323 : ALLOC(*crypto, 1);
2576 1494323 : if (*crypto == NULL)
2577 0 : return krb5_enomem(context);
2578 1494323 : if(etype == ETYPE_NULL)
2579 1379701 : etype = key->keytype;
2580 1494323 : (*crypto)->et = _krb5_find_enctype(etype);
2581 1494323 : if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2582 0 : free(*crypto);
2583 0 : *crypto = NULL;
2584 0 : return unsupported_enctype(context, etype);
2585 : }
2586 1494323 : if((*crypto)->et->keytype->size != key->keyvalue.length) {
2587 0 : free(*crypto);
2588 0 : *crypto = NULL;
2589 0 : krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2590 : "encryption key has bad length");
2591 0 : return KRB5_BAD_KEYSIZE;
2592 : }
2593 1494323 : ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2594 1494323 : if(ret) {
2595 0 : free(*crypto);
2596 0 : *crypto = NULL;
2597 0 : return ret;
2598 : }
2599 1494323 : (*crypto)->key.schedule = NULL;
2600 1494323 : (*crypto)->num_key_usage = 0;
2601 1494323 : (*crypto)->key_usage = NULL;
2602 1494323 : (*crypto)->flags = 0;
2603 1494323 : return 0;
2604 : }
2605 :
2606 : static void
2607 4317791 : free_key_schedule(krb5_context context,
2608 : struct _krb5_key_data *key,
2609 : struct _krb5_encryption_type *et)
2610 : {
2611 4317791 : if (et->keytype->cleanup)
2612 4317791 : (*et->keytype->cleanup)(context, key);
2613 4317791 : memset(key->schedule->data, 0, key->schedule->length);
2614 4317791 : krb5_free_data(context, key->schedule);
2615 4317791 : }
2616 :
2617 : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
2618 3871846 : _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2619 : struct _krb5_encryption_type *et)
2620 : {
2621 3871846 : krb5_free_keyblock(context, key->key);
2622 3871846 : if(key->schedule) {
2623 1940230 : free_key_schedule(context, key, et);
2624 1940230 : key->schedule = NULL;
2625 : }
2626 3871846 : }
2627 :
2628 : static void
2629 1798528 : free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2630 : struct _krb5_encryption_type *et)
2631 : {
2632 1798528 : _krb5_free_key_data(context, &ku->key, et);
2633 1798528 : }
2634 :
2635 : /**
2636 : * Free a crypto context created by krb5_crypto_init().
2637 : *
2638 : * @param context Kerberos context
2639 : * @param crypto crypto context to free
2640 : *
2641 : * @return Return an error code or 0.
2642 : *
2643 : * @ingroup krb5_crypto
2644 : */
2645 :
2646 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2647 1494285 : krb5_crypto_destroy(krb5_context context,
2648 : krb5_crypto crypto)
2649 : {
2650 : int i;
2651 :
2652 3292813 : for(i = 0; i < crypto->num_key_usage; i++)
2653 1798528 : free_key_usage(context, &crypto->key_usage[i], crypto->et);
2654 1494285 : free(crypto->key_usage);
2655 1494285 : _krb5_free_key_data(context, &crypto->key, crypto->et);
2656 :
2657 1494285 : if (crypto->mdctx)
2658 413324 : EVP_MD_CTX_destroy(crypto->mdctx);
2659 :
2660 1494285 : if (crypto->hmacctx)
2661 874579 : HMAC_CTX_free(crypto->hmacctx);
2662 :
2663 1494285 : free (crypto);
2664 1494285 : return 0;
2665 : }
2666 :
2667 : /**
2668 : * Return the blocksize used algorithm referenced by the crypto context
2669 : *
2670 : * @param context Kerberos context
2671 : * @param crypto crypto context to query
2672 : * @param blocksize the resulting blocksize
2673 : *
2674 : * @return Return an error code or 0.
2675 : *
2676 : * @ingroup krb5_crypto
2677 : */
2678 :
2679 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2680 1071467 : krb5_crypto_getblocksize(krb5_context context,
2681 : krb5_crypto crypto,
2682 : size_t *blocksize)
2683 : {
2684 1071467 : *blocksize = crypto->et->blocksize;
2685 1071467 : return 0;
2686 : }
2687 :
2688 : /**
2689 : * Return the encryption type used by the crypto context
2690 : *
2691 : * @param context Kerberos context
2692 : * @param crypto crypto context to query
2693 : * @param enctype the resulting encryption type
2694 : *
2695 : * @return Return an error code or 0.
2696 : *
2697 : * @ingroup krb5_crypto
2698 : */
2699 :
2700 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2701 1 : krb5_crypto_getenctype(krb5_context context,
2702 : krb5_crypto crypto,
2703 : krb5_enctype *enctype)
2704 : {
2705 1 : *enctype = crypto->et->type;
2706 1 : return 0;
2707 : }
2708 :
2709 : /**
2710 : * Return the padding size used by the crypto context
2711 : *
2712 : * @param context Kerberos context
2713 : * @param crypto crypto context to query
2714 : * @param padsize the return padding size
2715 : *
2716 : * @return Return an error code or 0.
2717 : *
2718 : * @ingroup krb5_crypto
2719 : */
2720 :
2721 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2722 564375 : krb5_crypto_getpadsize(krb5_context context,
2723 : krb5_crypto crypto,
2724 : size_t *padsize)
2725 : {
2726 564375 : *padsize = crypto->et->padsize;
2727 564375 : return 0;
2728 : }
2729 :
2730 : /**
2731 : * Return the confounder size used by the crypto context
2732 : *
2733 : * @param context Kerberos context
2734 : * @param crypto crypto context to query
2735 : * @param confoundersize the returned confounder size
2736 : *
2737 : * @return Return an error code or 0.
2738 : *
2739 : * @ingroup krb5_crypto
2740 : */
2741 :
2742 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2743 0 : krb5_crypto_getconfoundersize(krb5_context context,
2744 : krb5_crypto crypto,
2745 : size_t *confoundersize)
2746 : {
2747 0 : *confoundersize = crypto->et->confoundersize;
2748 0 : return 0;
2749 : }
2750 :
2751 :
2752 : /**
2753 : * Disable encryption type
2754 : *
2755 : * @param context Kerberos 5 context
2756 : * @param enctype encryption type to disable
2757 : *
2758 : * @return Return an error code or 0.
2759 : *
2760 : * @ingroup krb5_crypto
2761 : */
2762 :
2763 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2764 0 : krb5_enctype_disable(krb5_context context,
2765 : krb5_enctype enctype)
2766 : {
2767 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2768 0 : if(et == NULL) {
2769 0 : if (context)
2770 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2771 0 : N_("encryption type %d not supported", ""),
2772 : enctype);
2773 0 : return KRB5_PROG_ETYPE_NOSUPP;
2774 : }
2775 0 : et->flags |= F_DISABLED;
2776 0 : return 0;
2777 : }
2778 :
2779 : /**
2780 : * Enable encryption type
2781 : *
2782 : * @param context Kerberos 5 context
2783 : * @param enctype encryption type to enable
2784 : *
2785 : * @return Return an error code or 0.
2786 : *
2787 : * @ingroup krb5_crypto
2788 : */
2789 :
2790 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2791 0 : krb5_enctype_enable(krb5_context context,
2792 : krb5_enctype enctype)
2793 : {
2794 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2795 0 : if(et == NULL) {
2796 0 : if (context)
2797 0 : krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2798 0 : N_("encryption type %d not supported", ""),
2799 : enctype);
2800 0 : return KRB5_PROG_ETYPE_NOSUPP;
2801 : }
2802 0 : et->flags &= ~F_DISABLED;
2803 0 : return 0;
2804 : }
2805 :
2806 : /**
2807 : * Enable or disable all weak encryption types
2808 : *
2809 : * @param context Kerberos 5 context
2810 : * @param enable true to enable, false to disable
2811 : *
2812 : * @return Return an error code or 0.
2813 : *
2814 : * @ingroup krb5_crypto
2815 : */
2816 :
2817 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2818 0 : krb5_allow_weak_crypto(krb5_context context,
2819 : krb5_boolean enable)
2820 : {
2821 : int i;
2822 :
2823 0 : for(i = 0; i < _krb5_num_etypes; i++)
2824 0 : if(_krb5_etypes[i]->flags & F_WEAK) {
2825 0 : if(enable)
2826 0 : _krb5_etypes[i]->flags &= ~F_DISABLED;
2827 : else
2828 0 : _krb5_etypes[i]->flags |= F_DISABLED;
2829 : }
2830 0 : return 0;
2831 : }
2832 :
2833 : /**
2834 : * Returns is the encryption is strong or weak
2835 : *
2836 : * @param context Kerberos 5 context
2837 : * @param enctype encryption type to probe
2838 : *
2839 : * @return Returns true if encryption type is weak or is not supported.
2840 : *
2841 : * @ingroup krb5_crypto
2842 : */
2843 :
2844 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2845 2013 : krb5_is_enctype_weak(krb5_context context, krb5_enctype enctype)
2846 : {
2847 2013 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2848 2013 : if(et == NULL || (et->flags & F_WEAK))
2849 43 : return TRUE;
2850 1970 : return FALSE;
2851 : }
2852 :
2853 : /**
2854 : * Returns whether the encryption type is new or old
2855 : *
2856 : * @param context Kerberos 5 context
2857 : * @param enctype encryption type to probe
2858 : *
2859 : * @return Returns true if encryption type is old or is not supported.
2860 : *
2861 : * @ingroup krb5_crypto
2862 : */
2863 :
2864 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2865 12170 : krb5_is_enctype_old(krb5_context context, krb5_enctype enctype)
2866 : {
2867 12170 : struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2868 12170 : if (!et || (et->flags & F_OLD))
2869 1100 : return TRUE;
2870 11070 : return FALSE;
2871 : }
2872 :
2873 : /**
2874 : * Returns whether the encryption type should use randomly generated salts
2875 : *
2876 : * @param context Kerberos 5 context
2877 : * @param enctype encryption type to probe
2878 : *
2879 : * @return Returns true if generated salts should have random component
2880 : *
2881 : * @ingroup krb5_crypto
2882 : */
2883 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2884 0 : _krb5_enctype_requires_random_salt(krb5_context context,
2885 : krb5_enctype enctype)
2886 : {
2887 : struct _krb5_encryption_type *et;
2888 :
2889 0 : et = _krb5_find_enctype (enctype);
2890 :
2891 0 : return et && (et->flags & F_SP800_108_HMAC_KDF);
2892 : }
2893 :
2894 : static size_t
2895 0 : wrapped_length (krb5_context context,
2896 : krb5_crypto crypto,
2897 : size_t data_len)
2898 : {
2899 0 : struct _krb5_encryption_type *et = crypto->et;
2900 0 : size_t padsize = et->padsize;
2901 0 : size_t checksumsize = CHECKSUMSIZE(et->checksum);
2902 : size_t res;
2903 :
2904 0 : res = et->confoundersize + checksumsize + data_len;
2905 0 : res = (res + padsize - 1) / padsize * padsize;
2906 0 : return res;
2907 : }
2908 :
2909 : static size_t
2910 1094756 : wrapped_length_dervied (krb5_context context,
2911 : krb5_crypto crypto,
2912 : size_t data_len)
2913 : {
2914 1094756 : struct _krb5_encryption_type *et = crypto->et;
2915 1094756 : size_t padsize = et->padsize;
2916 : size_t res;
2917 :
2918 1094756 : res = et->confoundersize + data_len;
2919 1094756 : res = (res + padsize - 1) / padsize * padsize;
2920 1094756 : if (et->keyed_checksum)
2921 1094756 : res += et->keyed_checksum->checksumsize;
2922 : else
2923 0 : res += et->checksum->checksumsize;
2924 1094756 : return res;
2925 : }
2926 :
2927 : /*
2928 : * Return the size of an encrypted packet of length `data_len'
2929 : */
2930 :
2931 : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2932 1094756 : krb5_get_wrapped_length (krb5_context context,
2933 : krb5_crypto crypto,
2934 : size_t data_len)
2935 : {
2936 1094756 : if (derived_crypto (context, crypto))
2937 1094756 : return wrapped_length_dervied (context, crypto, data_len);
2938 : else
2939 0 : return wrapped_length (context, crypto, data_len);
2940 : }
2941 :
2942 : /*
2943 : * Return the size of an encrypted packet of length `data_len'
2944 : */
2945 :
2946 : static size_t
2947 0 : crypto_overhead (krb5_context context,
2948 : krb5_crypto crypto)
2949 : {
2950 0 : struct _krb5_encryption_type *et = crypto->et;
2951 : size_t res;
2952 :
2953 0 : res = CHECKSUMSIZE(et->checksum);
2954 0 : res += et->confoundersize;
2955 0 : if (et->padsize > 1)
2956 0 : res += et->padsize;
2957 0 : return res;
2958 : }
2959 :
2960 : static size_t
2961 0 : crypto_overhead_dervied (krb5_context context,
2962 : krb5_crypto crypto)
2963 : {
2964 0 : struct _krb5_encryption_type *et = crypto->et;
2965 : size_t res;
2966 :
2967 0 : if (et->keyed_checksum)
2968 0 : res = CHECKSUMSIZE(et->keyed_checksum);
2969 : else
2970 0 : res = CHECKSUMSIZE(et->checksum);
2971 0 : res += et->confoundersize;
2972 0 : if (et->padsize > 1)
2973 0 : res += et->padsize;
2974 0 : return res;
2975 : }
2976 :
2977 : KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2978 0 : krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2979 : {
2980 0 : if (derived_crypto (context, crypto))
2981 0 : return crypto_overhead_dervied (context, crypto);
2982 : else
2983 0 : return crypto_overhead (context, crypto);
2984 : }
2985 :
2986 : /**
2987 : * Converts the random bytestring to a protocol key according to
2988 : * Kerberos crypto frame work. It may be assumed that all the bits of
2989 : * the input string are equally random, even though the entropy
2990 : * present in the random source may be limited.
2991 : *
2992 : * @param context Kerberos 5 context
2993 : * @param type the enctype resulting key will be of
2994 : * @param data input random data to convert to a key
2995 : * @param size size of input random data, at least krb5_enctype_keysize() long
2996 : * @param key key, output key, free with krb5_free_keyblock_contents()
2997 : *
2998 : * @return Return an error code or 0.
2999 : *
3000 : * @ingroup krb5_crypto
3001 : */
3002 :
3003 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3004 131047 : krb5_random_to_key(krb5_context context,
3005 : krb5_enctype type,
3006 : const void *data,
3007 : size_t size,
3008 : krb5_keyblock *key)
3009 : {
3010 : krb5_error_code ret;
3011 131047 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
3012 131047 : if(et == NULL) {
3013 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3014 0 : N_("encryption type %d not supported", ""),
3015 : type);
3016 0 : return KRB5_PROG_ETYPE_NOSUPP;
3017 : }
3018 131047 : if ((et->keytype->bits + 7) / 8 > size) {
3019 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3020 0 : N_("encryption key %s needs %d bytes "
3021 : "of random to make an encryption key "
3022 : "out of it", ""),
3023 0 : et->name, (int)et->keytype->size);
3024 0 : return KRB5_PROG_ETYPE_NOSUPP;
3025 : }
3026 131047 : ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
3027 131047 : if(ret)
3028 0 : return ret;
3029 131047 : key->keytype = type;
3030 131047 : if (et->keytype->random_to_key)
3031 0 : (*et->keytype->random_to_key)(context, key, data, size);
3032 : else
3033 131047 : memcpy(key->keyvalue.data, data, et->keytype->size);
3034 :
3035 131047 : return 0;
3036 : }
3037 :
3038 :
3039 :
3040 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3041 0 : krb5_crypto_prf_length(krb5_context context,
3042 : krb5_enctype type,
3043 : size_t *length)
3044 : {
3045 0 : struct _krb5_encryption_type *et = _krb5_find_enctype(type);
3046 :
3047 0 : if(et == NULL || et->prf_length == 0) {
3048 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3049 0 : N_("encryption type %d not supported", ""),
3050 : type);
3051 0 : return KRB5_PROG_ETYPE_NOSUPP;
3052 : }
3053 :
3054 0 : *length = et->prf_length;
3055 0 : return 0;
3056 : }
3057 :
3058 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3059 518860 : krb5_crypto_prf(krb5_context context,
3060 : const krb5_crypto crypto,
3061 : const krb5_data *input,
3062 : krb5_data *output)
3063 : {
3064 518860 : struct _krb5_encryption_type *et = crypto->et;
3065 :
3066 518860 : krb5_data_zero(output);
3067 :
3068 518860 : if(et->prf == NULL) {
3069 0 : krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
3070 : "kerberos prf for %s not supported",
3071 : et->name);
3072 0 : return KRB5_PROG_ETYPE_NOSUPP;
3073 : }
3074 :
3075 518860 : return (*et->prf)(context, crypto, input, output);
3076 : }
3077 :
3078 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3079 263271 : krb5_crypto_prfplus(krb5_context context,
3080 : const krb5_crypto crypto,
3081 : const krb5_data *input,
3082 : size_t length,
3083 : krb5_data *output)
3084 : {
3085 : krb5_error_code ret;
3086 : krb5_data input2;
3087 263271 : unsigned char i = 1;
3088 : unsigned char *p;
3089 :
3090 263271 : krb5_data_zero(&input2);
3091 263271 : krb5_data_zero(output);
3092 :
3093 263271 : krb5_clear_error_message(context);
3094 :
3095 263271 : ret = krb5_data_alloc(output, length);
3096 263271 : if (ret) goto out;
3097 263271 : ret = krb5_data_alloc(&input2, input->length + 1);
3098 263271 : if (ret) goto out;
3099 :
3100 263271 : krb5_clear_error_message(context);
3101 :
3102 263271 : memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
3103 :
3104 263271 : p = output->data;
3105 :
3106 1045402 : while (length) {
3107 : krb5_data block;
3108 :
3109 518860 : ((unsigned char *)input2.data)[0] = i++;
3110 :
3111 518860 : ret = krb5_crypto_prf(context, crypto, &input2, &block);
3112 518860 : if (ret)
3113 0 : goto out;
3114 :
3115 518860 : if (block.length < length) {
3116 255589 : memcpy(p, block.data, block.length);
3117 255589 : length -= block.length;
3118 : } else {
3119 263271 : memcpy(p, block.data, length);
3120 263271 : length = 0;
3121 : }
3122 518860 : p += block.length;
3123 518860 : krb5_data_free(&block);
3124 : }
3125 :
3126 263271 : out:
3127 263271 : krb5_data_free(&input2);
3128 263271 : if (ret)
3129 0 : krb5_data_free(output);
3130 263271 : return ret;
3131 : }
3132 :
3133 : /**
3134 : * The FX-CF2 key derivation function, used in FAST and preauth framework.
3135 : *
3136 : * @param context Kerberos 5 context
3137 : * @param crypto1 first key to combine
3138 : * @param crypto2 second key to combine
3139 : * @param pepper1 factor to combine with first key to garante uniqueness
3140 : * @param pepper2 factor to combine with second key to garante uniqueness
3141 : * @param enctype the encryption type of the resulting key
3142 : * @param res allocated key, free with krb5_free_keyblock_contents()
3143 : *
3144 : * @return Return an error code or 0.
3145 : *
3146 : * @ingroup krb5_crypto
3147 : */
3148 :
3149 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3150 131047 : krb5_crypto_fx_cf2(krb5_context context,
3151 : const krb5_crypto crypto1,
3152 : const krb5_crypto crypto2,
3153 : krb5_data *pepper1,
3154 : krb5_data *pepper2,
3155 : krb5_enctype enctype,
3156 : krb5_keyblock *res)
3157 : {
3158 : krb5_error_code ret;
3159 : krb5_data os1, os2;
3160 : size_t i, keysize;
3161 :
3162 131047 : memset(res, 0, sizeof(*res));
3163 131047 : krb5_data_zero(&os1);
3164 131047 : krb5_data_zero(&os2);
3165 :
3166 131047 : ret = krb5_enctype_keybits(context, enctype, &keysize);
3167 131047 : if (ret)
3168 0 : return ret;
3169 131047 : keysize = (keysize + 7) / 8;
3170 :
3171 131047 : ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
3172 131047 : if (ret)
3173 0 : goto out;
3174 131047 : ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
3175 131047 : if (ret)
3176 0 : goto out;
3177 :
3178 131047 : res->keytype = enctype;
3179 : {
3180 131047 : unsigned char *p1 = os1.data, *p2 = os2.data;
3181 4263095 : for (i = 0; i < keysize; i++)
3182 4132048 : p1[i] ^= p2[i];
3183 : }
3184 131047 : ret = krb5_random_to_key(context, enctype, os1.data, keysize, res);
3185 131047 : out:
3186 131047 : krb5_data_free(&os1);
3187 131047 : krb5_data_free(&os2);
3188 :
3189 131047 : return ret;
3190 : }
3191 :
3192 : KRB5_LIB_FUNCTION void KRB5_LIB_CALL
3193 79524 : _krb5_crypto_set_flags(krb5_context context,
3194 : krb5_crypto crypto,
3195 : krb5_flags flags)
3196 : {
3197 79524 : crypto->flags |= flags;
3198 79524 : }
3199 :
3200 : #ifndef HEIMDAL_SMALLER
3201 :
3202 : /**
3203 : * Deprecated: keytypes doesn't exists, they are really enctypes.
3204 : *
3205 : * @ingroup krb5_deprecated
3206 : */
3207 :
3208 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3209 0 : krb5_keytype_to_enctypes (krb5_context context,
3210 : krb5_keytype keytype,
3211 : unsigned *len,
3212 : krb5_enctype **val)
3213 : KRB5_DEPRECATED_FUNCTION("Use X instead")
3214 : {
3215 : int i;
3216 0 : unsigned n = 0;
3217 : krb5_enctype *ret;
3218 :
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 : ++n;
3224 : }
3225 0 : if (n == 0) {
3226 0 : krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
3227 : "Keytype have no mapping");
3228 0 : return KRB5_PROG_KEYTYPE_NOSUPP;
3229 : }
3230 :
3231 0 : ret = malloc(n * sizeof(*ret));
3232 0 : if (ret == NULL && n != 0)
3233 0 : return krb5_enomem(context);
3234 0 : n = 0;
3235 0 : for (i = _krb5_num_etypes - 1; i >= 0; --i) {
3236 0 : if (_krb5_etypes[i]->keytype->type == keytype
3237 0 : && !(_krb5_etypes[i]->flags & F_PSEUDO)
3238 0 : && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
3239 0 : ret[n++] = _krb5_etypes[i]->type;
3240 : }
3241 0 : *len = n;
3242 0 : *val = ret;
3243 0 : return 0;
3244 : }
3245 :
3246 : /**
3247 : * Deprecated: keytypes doesn't exists, they are really enctypes.
3248 : *
3249 : * @ingroup krb5_deprecated
3250 : */
3251 :
3252 : /* if two enctypes have compatible keys */
3253 : KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
3254 0 : krb5_enctypes_compatible_keys(krb5_context context,
3255 : krb5_enctype etype1,
3256 : krb5_enctype etype2)
3257 : KRB5_DEPRECATED_FUNCTION("Use X instead")
3258 : {
3259 0 : struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
3260 0 : struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
3261 0 : return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
3262 : }
3263 :
3264 : #endif /* HEIMDAL_SMALLER */
|