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