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