Coverage Report

Created: 2025-12-31 06:20

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