~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/krb5/crypto.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
RCSID("$Id$");
 
36
#include <pkinit_asn1.h>
 
37
 
 
38
#undef __attribute__
 
39
#define __attribute__(X)
 
40
 
 
41
#define WEAK_ENCTYPES 1
 
42
 
 
43
#ifndef HEIMDAL_SMALLER
 
44
#define DES3_OLD_ENCTYPE 1
 
45
#endif
 
46
 
 
47
 
 
48
#ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */
 
49
const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void);
 
50
const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void);
 
51
#define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts
 
52
#define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts
 
53
#endif
 
54
 
 
55
struct key_data {
 
56
    krb5_keyblock *key;
 
57
    krb5_data *schedule;
 
58
};
 
59
 
 
60
struct key_usage {
 
61
    unsigned usage;
 
62
    struct key_data key;
 
63
};
 
64
 
 
65
struct krb5_crypto_data {
 
66
    struct encryption_type *et;
 
67
    struct key_data key;
 
68
    int num_key_usage;
 
69
    struct key_usage *key_usage;
 
70
};
 
71
 
 
72
#define CRYPTO_ETYPE(C) ((C)->et->type)
 
73
 
 
74
/* bits for `flags' below */
 
75
#define F_KEYED          1      /* checksum is keyed */
 
76
#define F_CPROOF         2      /* checksum is collision proof */
 
77
#define F_DERIVED        4      /* uses derived keys */
 
78
#define F_VARIANT        8      /* uses `variant' keys (6.4.3) */
 
79
#define F_PSEUDO        16      /* not a real protocol type */
 
80
#define F_SPECIAL       32      /* backwards */
 
81
#define F_DISABLED      64      /* enctype/checksum disabled */
 
82
 
 
83
struct salt_type {
 
84
    krb5_salttype type;
 
85
    const char *name;
 
86
    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
 
87
                                     krb5_salt, krb5_data, krb5_keyblock*);
 
88
};
 
89
 
 
90
struct key_type {
 
91
    krb5_keytype type; /* XXX */
 
92
    const char *name;
 
93
    size_t bits;
 
94
    size_t size;
 
95
    size_t schedule_size;
 
96
    void (*random_key)(krb5_context, krb5_keyblock*);
 
97
    void (*schedule)(krb5_context, struct key_type *, struct key_data *);
 
98
    struct salt_type *string_to_key;
 
99
    void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
 
100
    void (*cleanup)(krb5_context, struct key_data *);
 
101
    const EVP_CIPHER *(*evp)(void);
 
102
};
 
103
 
 
104
struct checksum_type {
 
105
    krb5_cksumtype type;
 
106
    const char *name;
 
107
    size_t blocksize;
 
108
    size_t checksumsize;
 
109
    unsigned flags;
 
110
    krb5_enctype (*checksum)(krb5_context context,
 
111
                             struct key_data *key,
 
112
                             const void *buf, size_t len,
 
113
                             unsigned usage,
 
114
                             Checksum *csum);
 
115
    krb5_error_code (*verify)(krb5_context context,
 
116
                              struct key_data *key,
 
117
                              const void *buf, size_t len,
 
118
                              unsigned usage,
 
119
                              Checksum *csum);
 
120
};
 
121
 
 
122
struct encryption_type {
 
123
    krb5_enctype type;
 
124
    const char *name;
 
125
    size_t blocksize;
 
126
    size_t padsize;
 
127
    size_t confoundersize;
 
128
    struct key_type *keytype;
 
129
    struct checksum_type *checksum;
 
130
    struct checksum_type *keyed_checksum;
 
131
    unsigned flags;
 
132
    krb5_error_code (*encrypt)(krb5_context context,
 
133
                               struct key_data *key,
 
134
                               void *data, size_t len,
 
135
                               krb5_boolean encryptp,
 
136
                               int usage,
 
137
                               void *ivec);
 
138
    size_t prf_length;
 
139
    krb5_error_code (*prf)(krb5_context,
 
140
                           krb5_crypto, const krb5_data *, krb5_data *);
 
141
};
 
142
 
 
143
#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
 
144
#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
 
145
#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
 
146
 
 
147
static struct checksum_type *_find_checksum(krb5_cksumtype type);
 
148
static struct encryption_type *_find_enctype(krb5_enctype type);
 
149
static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
 
150
                                        unsigned, struct key_data**);
 
151
static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
 
152
static krb5_error_code derive_key(krb5_context context,
 
153
                                  struct encryption_type *et,
 
154
                                  struct key_data *key,
 
155
                                  const void *constant,
 
156
                                  size_t len);
 
157
static krb5_error_code hmac(krb5_context context,
 
158
                            struct checksum_type *cm,
 
159
                            const void *data,
 
160
                            size_t len,
 
161
                            unsigned usage,
 
162
                            struct key_data *keyblock,
 
163
                            Checksum *result);
 
164
static void free_key_data(krb5_context,
 
165
                          struct key_data *,
 
166
                          struct encryption_type *);
 
167
static krb5_error_code usage2arcfour (krb5_context, unsigned *);
 
168
static void xor (DES_cblock *, const unsigned char *);
 
169
 
 
170
/************************************************************
 
171
 *                                                          *
 
172
 ************************************************************/
 
173
 
 
174
struct evp_schedule {
 
175
    EVP_CIPHER_CTX ectx;
 
176
    EVP_CIPHER_CTX dctx;
 
177
};
 
178
 
 
179
 
 
180
static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
 
181
 
 
182
#ifdef WEAK_ENCTYPES
 
183
static void
 
184
krb5_DES_random_key(krb5_context context,
 
185
                    krb5_keyblock *key)
 
186
{
 
187
    DES_cblock *k = key->keyvalue.data;
 
188
    do {
 
189
        krb5_generate_random_block(k, sizeof(DES_cblock));
 
190
        DES_set_odd_parity(k);
 
191
    } while(DES_is_weak_key(k));
 
192
}
 
193
 
 
194
static void
 
195
krb5_DES_schedule_old(krb5_context context,
 
196
                      struct key_type *kt,
 
197
                      struct key_data *key)
 
198
{
 
199
    DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
 
200
}
 
201
 
 
202
#ifdef ENABLE_AFS_STRING_TO_KEY
 
203
 
 
204
/* This defines the Andrew string_to_key function.  It accepts a password
 
205
 * string as input and converts it via a one-way encryption algorithm to a DES
 
206
 * encryption key.  It is compatible with the original Andrew authentication
 
207
 * service password database.
 
208
 */
 
209
 
 
210
/*
 
211
 * Short passwords, i.e 8 characters or less.
 
212
 */
 
213
static void
 
214
krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
 
215
                                 krb5_data cell,
 
216
                                 DES_cblock *key)
 
217
{
 
218
    char  password[8+1];        /* crypt is limited to 8 chars anyway */
 
219
    int   i;
 
220
 
 
221
    for(i = 0; i < 8; i++) {
 
222
        char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
 
223
            ((i < cell.length) ?
 
224
             tolower(((unsigned char*)cell.data)[i]) : 0);
 
225
        password[i] = c ? c : 'X';
 
226
    }
 
227
    password[8] = '\0';
 
228
 
 
229
    memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
 
230
 
 
231
    /* parity is inserted into the LSB so left shift each byte up one
 
232
       bit. This allows ascii characters with a zero MSB to retain as
 
233
       much significance as possible. */
 
234
    for (i = 0; i < sizeof(DES_cblock); i++)
 
235
        ((unsigned char*)key)[i] <<= 1;
 
236
    DES_set_odd_parity (key);
 
237
}
 
238
 
 
239
/*
 
240
 * Long passwords, i.e 9 characters or more.
 
241
 */
 
242
static void
 
243
krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
 
244
                                      krb5_data cell,
 
245
                                      DES_cblock *key)
 
246
{
 
247
    DES_key_schedule schedule;
 
248
    DES_cblock temp_key;
 
249
    DES_cblock ivec;
 
250
    char password[512];
 
251
    size_t passlen;
 
252
 
 
253
    memcpy(password, pw.data, min(pw.length, sizeof(password)));
 
254
    if(pw.length < sizeof(password)) {
 
255
        int len = min(cell.length, sizeof(password) - pw.length);
 
256
        int i;
 
257
 
 
258
        memcpy(password + pw.length, cell.data, len);
 
259
        for (i = pw.length; i < pw.length + len; ++i)
 
260
            password[i] = tolower((unsigned char)password[i]);
 
261
    }
 
262
    passlen = min(sizeof(password), pw.length + cell.length);
 
263
    memcpy(&ivec, "kerberos", 8);
 
264
    memcpy(&temp_key, "kerberos", 8);
 
265
    DES_set_odd_parity (&temp_key);
 
266
    DES_set_key_unchecked (&temp_key, &schedule);
 
267
    DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
 
268
 
 
269
    memcpy(&temp_key, &ivec, 8);
 
270
    DES_set_odd_parity (&temp_key);
 
271
    DES_set_key_unchecked (&temp_key, &schedule);
 
272
    DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
 
273
    memset(&schedule, 0, sizeof(schedule));
 
274
    memset(&temp_key, 0, sizeof(temp_key));
 
275
    memset(&ivec, 0, sizeof(ivec));
 
276
    memset(password, 0, sizeof(password));
 
277
 
 
278
    DES_set_odd_parity (key);
 
279
}
 
280
 
 
281
static krb5_error_code
 
282
DES_AFS3_string_to_key(krb5_context context,
 
283
                       krb5_enctype enctype,
 
284
                       krb5_data password,
 
285
                       krb5_salt salt,
 
286
                       krb5_data opaque,
 
287
                       krb5_keyblock *key)
 
288
{
 
289
    DES_cblock tmp;
 
290
    if(password.length > 8)
 
291
        krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
 
292
    else
 
293
        krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
 
294
    key->keytype = enctype;
 
295
    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 
296
    memset(&key, 0, sizeof(key));
 
297
    return 0;
 
298
}
 
299
#endif /* ENABLE_AFS_STRING_TO_KEY */
 
300
 
 
301
static void
 
302
DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
 
303
{
 
304
    DES_key_schedule schedule;
 
305
    int i;
 
306
    int reverse = 0;
 
307
    unsigned char *p;
 
308
 
 
309
    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
 
310
                             0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
 
311
    memset(key, 0, 8);
 
312
 
 
313
    p = (unsigned char*)key;
 
314
    for (i = 0; i < length; i++) {
 
315
        unsigned char tmp = data[i];
 
316
        if (!reverse)
 
317
            *p++ ^= (tmp << 1);
 
318
        else
 
319
            *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
 
320
        if((i % 8) == 7)
 
321
            reverse = !reverse;
 
322
    }
 
323
    DES_set_odd_parity(key);
 
324
    if(DES_is_weak_key(key))
 
325
        (*key)[7] ^= 0xF0;
 
326
    DES_set_key_unchecked(key, &schedule);
 
327
    DES_cbc_cksum((void*)data, key, length, &schedule, key);
 
328
    memset(&schedule, 0, sizeof(schedule));
 
329
    DES_set_odd_parity(key);
 
330
    if(DES_is_weak_key(key))
 
331
        (*key)[7] ^= 0xF0;
 
332
}
 
333
 
 
334
static krb5_error_code
 
335
krb5_DES_string_to_key(krb5_context context,
 
336
                       krb5_enctype enctype,
 
337
                       krb5_data password,
 
338
                       krb5_salt salt,
 
339
                       krb5_data opaque,
 
340
                       krb5_keyblock *key)
 
341
{
 
342
    unsigned char *s;
 
343
    size_t len;
 
344
    DES_cblock tmp;
 
345
 
 
346
#ifdef ENABLE_AFS_STRING_TO_KEY
 
347
    if (opaque.length == 1) {
 
348
        unsigned long v;
 
349
        _krb5_get_int(opaque.data, &v, 1);
 
350
        if (v == 1)
 
351
            return DES_AFS3_string_to_key(context, enctype, password,
 
352
                                          salt, opaque, key);
 
353
    }
 
354
#endif
 
355
 
 
356
    len = password.length + salt.saltvalue.length;
 
357
    s = malloc(len);
 
358
    if(len > 0 && s == NULL) {
 
359
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
360
        return ENOMEM;
 
361
    }
 
362
    memcpy(s, password.data, password.length);
 
363
    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
 
364
    DES_string_to_key_int(s, len, &tmp);
 
365
    key->keytype = enctype;
 
366
    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
 
367
    memset(&tmp, 0, sizeof(tmp));
 
368
    memset(s, 0, len);
 
369
    free(s);
 
370
    return 0;
 
371
}
 
372
 
 
373
static void
 
374
krb5_DES_random_to_key(krb5_context context,
 
375
                       krb5_keyblock *key,
 
376
                       const void *data,
 
377
                       size_t size)
 
378
{
 
379
    DES_cblock *k = key->keyvalue.data;
 
380
    memcpy(k, data, key->keyvalue.length);
 
381
    DES_set_odd_parity(k);
 
382
    if(DES_is_weak_key(k))
 
383
        xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 
384
}
 
385
#endif
 
386
 
 
387
/*
 
388
 *
 
389
 */
 
390
 
 
391
static void
 
392
DES3_random_key(krb5_context context,
 
393
                krb5_keyblock *key)
 
394
{
 
395
    DES_cblock *k = key->keyvalue.data;
 
396
    do {
 
397
        krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
 
398
        DES_set_odd_parity(&k[0]);
 
399
        DES_set_odd_parity(&k[1]);
 
400
        DES_set_odd_parity(&k[2]);
 
401
    } while(DES_is_weak_key(&k[0]) ||
 
402
            DES_is_weak_key(&k[1]) ||
 
403
            DES_is_weak_key(&k[2]));
 
404
}
 
405
 
 
406
/*
 
407
 * A = A xor B. A & B are 8 bytes.
 
408
 */
 
409
 
 
410
static void
 
411
xor (DES_cblock *key, const unsigned char *b)
 
412
{
 
413
    unsigned char *a = (unsigned char*)key;
 
414
    a[0] ^= b[0];
 
415
    a[1] ^= b[1];
 
416
    a[2] ^= b[2];
 
417
    a[3] ^= b[3];
 
418
    a[4] ^= b[4];
 
419
    a[5] ^= b[5];
 
420
    a[6] ^= b[6];
 
421
    a[7] ^= b[7];
 
422
}
 
423
 
 
424
#ifdef DES3_OLD_ENCTYPE
 
425
static krb5_error_code
 
426
DES3_string_to_key(krb5_context context,
 
427
                   krb5_enctype enctype,
 
428
                   krb5_data password,
 
429
                   krb5_salt salt,
 
430
                   krb5_data opaque,
 
431
                   krb5_keyblock *key)
 
432
{
 
433
    char *str;
 
434
    size_t len;
 
435
    unsigned char tmp[24];
 
436
    DES_cblock keys[3];
 
437
    krb5_error_code ret;
 
438
 
 
439
    len = password.length + salt.saltvalue.length;
 
440
    str = malloc(len);
 
441
    if(len != 0 && str == NULL) {
 
442
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
443
        return ENOMEM;
 
444
    }
 
445
    memcpy(str, password.data, password.length);
 
446
    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
 
447
    {
 
448
        DES_cblock ivec;
 
449
        DES_key_schedule s[3];
 
450
        int i;
 
451
        
 
452
        ret = _krb5_n_fold(str, len, tmp, 24);
 
453
        if (ret) {
 
454
            memset(str, 0, len);
 
455
            free(str);
 
456
            krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
457
            return ret;
 
458
        }
 
459
        
 
460
        for(i = 0; i < 3; i++){
 
461
            memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
 
462
            DES_set_odd_parity(keys + i);
 
463
            if(DES_is_weak_key(keys + i))
 
464
                xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 
465
            DES_set_key_unchecked(keys + i, &s[i]);
 
466
        }
 
467
        memset(&ivec, 0, sizeof(ivec));
 
468
        DES_ede3_cbc_encrypt(tmp,
 
469
                             tmp, sizeof(tmp),
 
470
                             &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
 
471
        memset(s, 0, sizeof(s));
 
472
        memset(&ivec, 0, sizeof(ivec));
 
473
        for(i = 0; i < 3; i++){
 
474
            memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
 
475
            DES_set_odd_parity(keys + i);
 
476
            if(DES_is_weak_key(keys + i))
 
477
                xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 
478
        }
 
479
        memset(tmp, 0, sizeof(tmp));
 
480
    }
 
481
    key->keytype = enctype;
 
482
    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
 
483
    memset(keys, 0, sizeof(keys));
 
484
    memset(str, 0, len);
 
485
    free(str);
 
486
    return 0;
 
487
}
 
488
#endif
 
489
 
 
490
static krb5_error_code
 
491
DES3_string_to_key_derived(krb5_context context,
 
492
                           krb5_enctype enctype,
 
493
                           krb5_data password,
 
494
                           krb5_salt salt,
 
495
                           krb5_data opaque,
 
496
                           krb5_keyblock *key)
 
497
{
 
498
    krb5_error_code ret;
 
499
    size_t len = password.length + salt.saltvalue.length;
 
500
    char *s;
 
501
 
 
502
    s = malloc(len);
 
503
    if(len != 0 && s == NULL) {
 
504
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
505
        return ENOMEM;
 
506
    }
 
507
    memcpy(s, password.data, password.length);
 
508
    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
 
509
    ret = krb5_string_to_key_derived(context,
 
510
                                     s,
 
511
                                     len,
 
512
                                     enctype,
 
513
                                     key);
 
514
    memset(s, 0, len);
 
515
    free(s);
 
516
    return ret;
 
517
}
 
518
 
 
519
static void
 
520
DES3_random_to_key(krb5_context context,
 
521
                   krb5_keyblock *key,
 
522
                   const void *data,
 
523
                   size_t size)
 
524
{
 
525
    unsigned char *x = key->keyvalue.data;
 
526
    const u_char *q = data;
 
527
    DES_cblock *k;
 
528
    int i, j;
 
529
 
 
530
    memset(x, 0, sizeof(x));
 
531
    for (i = 0; i < 3; ++i) {
 
532
        unsigned char foo;
 
533
        for (j = 0; j < 7; ++j) {
 
534
            unsigned char b = q[7 * i + j];
 
535
 
 
536
            x[8 * i + j] = b;
 
537
        }
 
538
        foo = 0;
 
539
        for (j = 6; j >= 0; --j) {
 
540
            foo |= q[7 * i + j] & 1;
 
541
            foo <<= 1;
 
542
        }
 
543
        x[8 * i + 7] = foo;
 
544
    }
 
545
    k = key->keyvalue.data;
 
546
    for (i = 0; i < 3; i++) {
 
547
        DES_set_odd_parity(&k[i]);
 
548
        if(DES_is_weak_key(&k[i]))
 
549
            xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
 
550
    }
 
551
}
 
552
 
 
553
/*
 
554
 * ARCFOUR
 
555
 */
 
556
 
 
557
static void
 
558
ARCFOUR_schedule(krb5_context context,
 
559
                 struct key_type *kt,
 
560
                 struct key_data *kd)
 
561
{
 
562
    RC4_set_key (kd->schedule->data,
 
563
                 kd->key->keyvalue.length, kd->key->keyvalue.data);
 
564
}
 
565
 
 
566
static krb5_error_code
 
567
ARCFOUR_string_to_key(krb5_context context,
 
568
                      krb5_enctype enctype,
 
569
                      krb5_data password,
 
570
                      krb5_salt salt,
 
571
                      krb5_data opaque,
 
572
                      krb5_keyblock *key)
 
573
{
 
574
    krb5_error_code ret;
 
575
    uint16_t *s = NULL;
 
576
    size_t len, i;
 
577
    EVP_MD_CTX *m;
 
578
 
 
579
    m = EVP_MD_CTX_create();
 
580
    if (m == NULL) {
 
581
        ret = ENOMEM;
 
582
        krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
583
        goto out;
 
584
    }
 
585
 
 
586
    EVP_DigestInit_ex(m, EVP_md4(), NULL);
 
587
 
 
588
    ret = wind_utf8ucs2_length(password.data, &len);
 
589
    if (ret) {
 
590
        krb5_set_error_message (context, ret,
 
591
                                N_("Password not an UCS2 string", ""));
 
592
        goto out;
 
593
    }
 
594
        
 
595
    s = malloc (len * sizeof(s[0]));
 
596
    if (len != 0 && s == NULL) {
 
597
        krb5_set_error_message (context, ENOMEM,
 
598
                                N_("malloc: out of memory", ""));
 
599
        ret = ENOMEM;
 
600
        goto out;
 
601
    }
 
602
 
 
603
    ret = wind_utf8ucs2(password.data, s, &len);
 
604
    if (ret) {
 
605
        krb5_set_error_message (context, ret,
 
606
                                N_("Password not an UCS2 string", ""));
 
607
        goto out;
 
608
    }
 
609
 
 
610
    /* LE encoding */
 
611
    for (i = 0; i < len; i++) {
 
612
        unsigned char p;
 
613
        p = (s[i] & 0xff);
 
614
        EVP_DigestUpdate (m, &p, 1);
 
615
        p = (s[i] >> 8) & 0xff;
 
616
        EVP_DigestUpdate (m, &p, 1);
 
617
    }
 
618
 
 
619
    key->keytype = enctype;
 
620
    ret = krb5_data_alloc (&key->keyvalue, 16);
 
621
    if (ret) {
 
622
        krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 
623
        goto out;
 
624
    }
 
625
    EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
 
626
 
 
627
 out:
 
628
    EVP_MD_CTX_destroy(m);
 
629
    if (s)
 
630
        memset (s, 0, len);
 
631
    free (s);
 
632
    return ret;
 
633
}
 
634
 
 
635
/*
 
636
 * AES
 
637
 */
 
638
 
 
639
int _krb5_AES_string_to_default_iterator = 4096;
 
640
 
 
641
static krb5_error_code
 
642
AES_string_to_key(krb5_context context,
 
643
                  krb5_enctype enctype,
 
644
                  krb5_data password,
 
645
                  krb5_salt salt,
 
646
                  krb5_data opaque,
 
647
                  krb5_keyblock *key)
 
648
{
 
649
    krb5_error_code ret;
 
650
    uint32_t iter;
 
651
    struct encryption_type *et;
 
652
    struct key_data kd;
 
653
 
 
654
    if (opaque.length == 0)
 
655
        iter = _krb5_AES_string_to_default_iterator;
 
656
    else if (opaque.length == 4) {
 
657
        unsigned long v;
 
658
        _krb5_get_int(opaque.data, &v, 4);
 
659
        iter = ((uint32_t)v);
 
660
    } else
 
661
        return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
 
662
        
 
663
    et = _find_enctype(enctype);
 
664
    if (et == NULL)
 
665
        return KRB5_PROG_KEYTYPE_NOSUPP;
 
666
 
 
667
    kd.schedule = NULL;
 
668
    ALLOC(kd.key, 1);
 
669
    if(kd.key == NULL) {
 
670
        krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 
671
        return ENOMEM;
 
672
    }
 
673
    kd.key->keytype = enctype;
 
674
    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
 
675
    if (ret) {
 
676
        krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
 
677
        return ret;
 
678
    }
 
679
 
 
680
    ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
 
681
                                 salt.saltvalue.data, salt.saltvalue.length,
 
682
                                 iter,
 
683
                                 et->keytype->size, kd.key->keyvalue.data);
 
684
    if (ret != 1) {
 
685
        free_key_data(context, &kd, et);
 
686
        krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
 
687
                               "Error calculating s2k");
 
688
        return KRB5_PROG_KEYTYPE_NOSUPP;
 
689
    }
 
690
 
 
691
    ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
 
692
    if (ret == 0)
 
693
        ret = krb5_copy_keyblock_contents(context, kd.key, key);
 
694
    free_key_data(context, &kd, et);
 
695
 
 
696
    return ret;
 
697
}
 
698
 
 
699
static void
 
700
evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
 
701
{
 
702
    struct evp_schedule *key = kd->schedule->data;
 
703
    const EVP_CIPHER *c = (*kt->evp)();
 
704
 
 
705
    EVP_CIPHER_CTX_init(&key->ectx);
 
706
    EVP_CIPHER_CTX_init(&key->dctx);
 
707
 
 
708
    EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
 
709
    EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
 
710
}
 
711
 
 
712
static void
 
713
evp_cleanup(krb5_context context, struct key_data *kd)
 
714
{
 
715
    struct evp_schedule *key = kd->schedule->data;
 
716
    EVP_CIPHER_CTX_cleanup(&key->ectx);
 
717
    EVP_CIPHER_CTX_cleanup(&key->dctx);
 
718
}
 
719
 
 
720
/*
 
721
 *
 
722
 */
 
723
 
 
724
#ifdef WEAK_ENCTYPES
 
725
static struct salt_type des_salt[] = {
 
726
    {
 
727
        KRB5_PW_SALT,
 
728
        "pw-salt",
 
729
        krb5_DES_string_to_key
 
730
    },
 
731
#ifdef ENABLE_AFS_STRING_TO_KEY
 
732
    {
 
733
        KRB5_AFS3_SALT,
 
734
        "afs3-salt",
 
735
        DES_AFS3_string_to_key
 
736
    },
 
737
#endif
 
738
    { 0 }
 
739
};
 
740
#endif
 
741
 
 
742
#ifdef DES3_OLD_ENCTYPE
 
743
static struct salt_type des3_salt[] = {
 
744
    {
 
745
        KRB5_PW_SALT,
 
746
        "pw-salt",
 
747
        DES3_string_to_key
 
748
    },
 
749
    { 0 }
 
750
};
 
751
#endif
 
752
 
 
753
static struct salt_type des3_salt_derived[] = {
 
754
    {
 
755
        KRB5_PW_SALT,
 
756
        "pw-salt",
 
757
        DES3_string_to_key_derived
 
758
    },
 
759
    { 0 }
 
760
};
 
761
 
 
762
static struct salt_type AES_salt[] = {
 
763
    {
 
764
        KRB5_PW_SALT,
 
765
        "pw-salt",
 
766
        AES_string_to_key
 
767
    },
 
768
    { 0 }
 
769
};
 
770
 
 
771
static struct salt_type arcfour_salt[] = {
 
772
    {
 
773
        KRB5_PW_SALT,
 
774
        "pw-salt",
 
775
        ARCFOUR_string_to_key
 
776
    },
 
777
    { 0 }
 
778
};
 
779
 
 
780
/*
 
781
 *
 
782
 */
 
783
 
 
784
static struct key_type keytype_null = {
 
785
    KEYTYPE_NULL,
 
786
    "null",
 
787
    0,
 
788
    0,
 
789
    0,
 
790
    NULL,
 
791
    NULL,
 
792
    NULL
 
793
};
 
794
 
 
795
#ifdef WEAK_ENCTYPES
 
796
static struct key_type keytype_des_old = {
 
797
    KEYTYPE_DES,
 
798
    "des-old",
 
799
    56,
 
800
    8,
 
801
    sizeof(DES_key_schedule),
 
802
    krb5_DES_random_key,
 
803
    krb5_DES_schedule_old,
 
804
    des_salt,
 
805
    krb5_DES_random_to_key
 
806
};
 
807
 
 
808
static struct key_type keytype_des = {
 
809
    KEYTYPE_DES,
 
810
    "des",
 
811
    56,
 
812
    8,
 
813
    sizeof(struct evp_schedule),
 
814
    krb5_DES_random_key,
 
815
    evp_schedule,
 
816
    des_salt,
 
817
    krb5_DES_random_to_key,
 
818
    evp_cleanup,
 
819
    EVP_des_cbc
 
820
};
 
821
#endif /* WEAK_ENCTYPES */
 
822
 
 
823
#ifdef DES3_OLD_ENCTYPE
 
824
static struct key_type keytype_des3 = {
 
825
    KEYTYPE_DES3,
 
826
    "des3",
 
827
    168,
 
828
    24,
 
829
    sizeof(struct evp_schedule),
 
830
    DES3_random_key,
 
831
    evp_schedule,
 
832
    des3_salt,
 
833
    DES3_random_to_key,
 
834
    evp_cleanup,
 
835
    EVP_des_ede3_cbc
 
836
};
 
837
#endif
 
838
 
 
839
static struct key_type keytype_des3_derived = {
 
840
    KEYTYPE_DES3,
 
841
    "des3",
 
842
    168,
 
843
    24,
 
844
    sizeof(struct evp_schedule),
 
845
    DES3_random_key,
 
846
    evp_schedule,
 
847
    des3_salt_derived,
 
848
    DES3_random_to_key,
 
849
    evp_cleanup,
 
850
    EVP_des_ede3_cbc
 
851
};
 
852
 
 
853
static struct key_type keytype_aes128 = {
 
854
    KEYTYPE_AES128,
 
855
    "aes-128",
 
856
    128,
 
857
    16,
 
858
    sizeof(struct evp_schedule),
 
859
    NULL,
 
860
    evp_schedule,
 
861
    AES_salt,
 
862
    NULL,
 
863
    evp_cleanup,
 
864
    EVP_hcrypto_aes_128_cts
 
865
};
 
866
 
 
867
static struct key_type keytype_aes256 = {
 
868
    KEYTYPE_AES256,
 
869
    "aes-256",
 
870
    256,
 
871
    32,
 
872
    sizeof(struct evp_schedule),
 
873
    NULL,
 
874
    evp_schedule,
 
875
    AES_salt,
 
876
    NULL,
 
877
    evp_cleanup,
 
878
    EVP_hcrypto_aes_256_cts
 
879
};
 
880
 
 
881
static struct key_type keytype_arcfour = {
 
882
    KEYTYPE_ARCFOUR,
 
883
    "arcfour",
 
884
    128,
 
885
    16,
 
886
    sizeof(RC4_KEY),
 
887
    NULL,
 
888
    ARCFOUR_schedule,
 
889
    arcfour_salt
 
890
};
 
891
 
 
892
krb5_error_code KRB5_LIB_FUNCTION
 
893
krb5_salttype_to_string (krb5_context context,
 
894
                         krb5_enctype etype,
 
895
                         krb5_salttype stype,
 
896
                         char **string)
 
897
{
 
898
    struct encryption_type *e;
 
899
    struct salt_type *st;
 
900
 
 
901
    e = _find_enctype (etype);
 
902
    if (e == NULL) {
 
903
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
904
                               "encryption type %d not supported",
 
905
                               etype);
 
906
        return KRB5_PROG_ETYPE_NOSUPP;
 
907
    }
 
908
    for (st = e->keytype->string_to_key; st && st->type; st++) {
 
909
        if (st->type == stype) {
 
910
            *string = strdup (st->name);
 
911
            if (*string == NULL) {
 
912
                krb5_set_error_message (context, ENOMEM,
 
913
                                        N_("malloc: out of memory", ""));
 
914
                return ENOMEM;
 
915
            }
 
916
            return 0;
 
917
        }
 
918
    }
 
919
    krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
 
920
                            "salttype %d not supported", stype);
 
921
    return HEIM_ERR_SALTTYPE_NOSUPP;
 
922
}
 
923
 
 
924
krb5_error_code KRB5_LIB_FUNCTION
 
925
krb5_string_to_salttype (krb5_context context,
 
926
                         krb5_enctype etype,
 
927
                         const char *string,
 
928
                         krb5_salttype *salttype)
 
929
{
 
930
    struct encryption_type *e;
 
931
    struct salt_type *st;
 
932
 
 
933
    e = _find_enctype (etype);
 
934
    if (e == NULL) {
 
935
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
936
                               N_("encryption type %d not supported", ""),
 
937
                               etype);
 
938
        return KRB5_PROG_ETYPE_NOSUPP;
 
939
    }
 
940
    for (st = e->keytype->string_to_key; st && st->type; st++) {
 
941
        if (strcasecmp (st->name, string) == 0) {
 
942
            *salttype = st->type;
 
943
            return 0;
 
944
        }
 
945
    }
 
946
    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
 
947
                           N_("salttype %s not supported", ""), string);
 
948
    return HEIM_ERR_SALTTYPE_NOSUPP;
 
949
}
 
950
 
 
951
krb5_error_code KRB5_LIB_FUNCTION
 
952
krb5_get_pw_salt(krb5_context context,
 
953
                 krb5_const_principal principal,
 
954
                 krb5_salt *salt)
 
955
{
 
956
    size_t len;
 
957
    int i;
 
958
    krb5_error_code ret;
 
959
    char *p;
 
960
 
 
961
    salt->salttype = KRB5_PW_SALT;
 
962
    len = strlen(principal->realm);
 
963
    for (i = 0; i < principal->name.name_string.len; ++i)
 
964
        len += strlen(principal->name.name_string.val[i]);
 
965
    ret = krb5_data_alloc (&salt->saltvalue, len);
 
966
    if (ret)
 
967
        return ret;
 
968
    p = salt->saltvalue.data;
 
969
    memcpy (p, principal->realm, strlen(principal->realm));
 
970
    p += strlen(principal->realm);
 
971
    for (i = 0; i < principal->name.name_string.len; ++i) {
 
972
        memcpy (p,
 
973
                principal->name.name_string.val[i],
 
974
                strlen(principal->name.name_string.val[i]));
 
975
        p += strlen(principal->name.name_string.val[i]);
 
976
    }
 
977
    return 0;
 
978
}
 
979
 
 
980
krb5_error_code KRB5_LIB_FUNCTION
 
981
krb5_free_salt(krb5_context context,
 
982
               krb5_salt salt)
 
983
{
 
984
    krb5_data_free(&salt.saltvalue);
 
985
    return 0;
 
986
}
 
987
 
 
988
krb5_error_code KRB5_LIB_FUNCTION
 
989
krb5_string_to_key_data (krb5_context context,
 
990
                         krb5_enctype enctype,
 
991
                         krb5_data password,
 
992
                         krb5_principal principal,
 
993
                         krb5_keyblock *key)
 
994
{
 
995
    krb5_error_code ret;
 
996
    krb5_salt salt;
 
997
 
 
998
    ret = krb5_get_pw_salt(context, principal, &salt);
 
999
    if(ret)
 
1000
        return ret;
 
1001
    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
 
1002
    krb5_free_salt(context, salt);
 
1003
    return ret;
 
1004
}
 
1005
 
 
1006
krb5_error_code KRB5_LIB_FUNCTION
 
1007
krb5_string_to_key (krb5_context context,
 
1008
                    krb5_enctype enctype,
 
1009
                    const char *password,
 
1010
                    krb5_principal principal,
 
1011
                    krb5_keyblock *key)
 
1012
{
 
1013
    krb5_data pw;
 
1014
    pw.data = rk_UNCONST(password);
 
1015
    pw.length = strlen(password);
 
1016
    return krb5_string_to_key_data(context, enctype, pw, principal, key);
 
1017
}
 
1018
 
 
1019
krb5_error_code KRB5_LIB_FUNCTION
 
1020
krb5_string_to_key_data_salt (krb5_context context,
 
1021
                              krb5_enctype enctype,
 
1022
                              krb5_data password,
 
1023
                              krb5_salt salt,
 
1024
                              krb5_keyblock *key)
 
1025
{
 
1026
    krb5_data opaque;
 
1027
    krb5_data_zero(&opaque);
 
1028
    return krb5_string_to_key_data_salt_opaque(context, enctype, password,
 
1029
                                               salt, opaque, key);
 
1030
}
 
1031
 
 
1032
/*
 
1033
 * Do a string -> key for encryption type `enctype' operation on
 
1034
 * `password' (with salt `salt' and the enctype specific data string
 
1035
 * `opaque'), returning the resulting key in `key'
 
1036
 */
 
1037
 
 
1038
krb5_error_code KRB5_LIB_FUNCTION
 
1039
krb5_string_to_key_data_salt_opaque (krb5_context context,
 
1040
                                     krb5_enctype enctype,
 
1041
                                     krb5_data password,
 
1042
                                     krb5_salt salt,
 
1043
                                     krb5_data opaque,
 
1044
                                     krb5_keyblock *key)
 
1045
{
 
1046
    struct encryption_type *et =_find_enctype(enctype);
 
1047
    struct salt_type *st;
 
1048
    if(et == NULL) {
 
1049
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
1050
                               N_("encryption type %d not supported", ""),
 
1051
                               enctype);
 
1052
        return KRB5_PROG_ETYPE_NOSUPP;
 
1053
    }
 
1054
    for(st = et->keytype->string_to_key; st && st->type; st++)
 
1055
        if(st->type == salt.salttype)
 
1056
            return (*st->string_to_key)(context, enctype, password,
 
1057
                                        salt, opaque, key);
 
1058
    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
 
1059
                           N_("salt type %d not supported", ""),
 
1060
                           salt.salttype);
 
1061
    return HEIM_ERR_SALTTYPE_NOSUPP;
 
1062
}
 
1063
 
 
1064
/*
 
1065
 * Do a string -> key for encryption type `enctype' operation on the
 
1066
 * string `password' (with salt `salt'), returning the resulting key
 
1067
 * in `key'
 
1068
 */
 
1069
 
 
1070
krb5_error_code KRB5_LIB_FUNCTION
 
1071
krb5_string_to_key_salt (krb5_context context,
 
1072
                         krb5_enctype enctype,
 
1073
                         const char *password,
 
1074
                         krb5_salt salt,
 
1075
                         krb5_keyblock *key)
 
1076
{
 
1077
    krb5_data pw;
 
1078
    pw.data = rk_UNCONST(password);
 
1079
    pw.length = strlen(password);
 
1080
    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
 
1081
}
 
1082
 
 
1083
krb5_error_code KRB5_LIB_FUNCTION
 
1084
krb5_string_to_key_salt_opaque (krb5_context context,
 
1085
                                krb5_enctype enctype,
 
1086
                                const char *password,
 
1087
                                krb5_salt salt,
 
1088
                                krb5_data opaque,
 
1089
                                krb5_keyblock *key)
 
1090
{
 
1091
    krb5_data pw;
 
1092
    pw.data = rk_UNCONST(password);
 
1093
    pw.length = strlen(password);
 
1094
    return krb5_string_to_key_data_salt_opaque(context, enctype,
 
1095
                                               pw, salt, opaque, key);
 
1096
}
 
1097
 
 
1098
krb5_error_code KRB5_LIB_FUNCTION
 
1099
krb5_enctype_keysize(krb5_context context,
 
1100
                     krb5_enctype type,
 
1101
                     size_t *keysize)
 
1102
{
 
1103
    struct encryption_type *et = _find_enctype(type);
 
1104
    if(et == NULL) {
 
1105
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
1106
                               N_("encryption type %d not supported", ""),
 
1107
                               type);
 
1108
        return KRB5_PROG_ETYPE_NOSUPP;
 
1109
    }
 
1110
    *keysize = et->keytype->size;
 
1111
    return 0;
 
1112
}
 
1113
 
 
1114
krb5_error_code KRB5_LIB_FUNCTION
 
1115
krb5_enctype_keybits(krb5_context context,
 
1116
                     krb5_enctype type,
 
1117
                     size_t *keybits)
 
1118
{
 
1119
    struct encryption_type *et = _find_enctype(type);
 
1120
    if(et == NULL) {
 
1121
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
1122
                               "encryption type %d not supported",
 
1123
                               type);
 
1124
        return KRB5_PROG_ETYPE_NOSUPP;
 
1125
    }
 
1126
    *keybits = et->keytype->bits;
 
1127
    return 0;
 
1128
}
 
1129
 
 
1130
krb5_error_code KRB5_LIB_FUNCTION
 
1131
krb5_generate_random_keyblock(krb5_context context,
 
1132
                              krb5_enctype type,
 
1133
                              krb5_keyblock *key)
 
1134
{
 
1135
    krb5_error_code ret;
 
1136
    struct encryption_type *et = _find_enctype(type);
 
1137
    if(et == NULL) {
 
1138
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
1139
                               N_("encryption type %d not supported", ""),
 
1140
                               type);
 
1141
        return KRB5_PROG_ETYPE_NOSUPP;
 
1142
    }
 
1143
    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
 
1144
    if(ret)
 
1145
        return ret;
 
1146
    key->keytype = type;
 
1147
    if(et->keytype->random_key)
 
1148
        (*et->keytype->random_key)(context, key);
 
1149
    else
 
1150
        krb5_generate_random_block(key->keyvalue.data,
 
1151
                                   key->keyvalue.length);
 
1152
    return 0;
 
1153
}
 
1154
 
 
1155
static krb5_error_code
 
1156
_key_schedule(krb5_context context,
 
1157
              struct key_data *key)
 
1158
{
 
1159
    krb5_error_code ret;
 
1160
    struct encryption_type *et = _find_enctype(key->key->keytype);
 
1161
    struct key_type *kt = et->keytype;
 
1162
 
 
1163
    if(kt->schedule == NULL)
 
1164
        return 0;
 
1165
    if (key->schedule != NULL)
 
1166
        return 0;
 
1167
    ALLOC(key->schedule, 1);
 
1168
    if(key->schedule == NULL) {
 
1169
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
1170
        return ENOMEM;
 
1171
    }
 
1172
    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
 
1173
    if(ret) {
 
1174
        free(key->schedule);
 
1175
        key->schedule = NULL;
 
1176
        return ret;
 
1177
    }
 
1178
    (*kt->schedule)(context, kt, key);
 
1179
    return 0;
 
1180
}
 
1181
 
 
1182
/************************************************************
 
1183
 *                                                          *
 
1184
 ************************************************************/
 
1185
 
 
1186
static krb5_error_code
 
1187
NONE_checksum(krb5_context context,
 
1188
              struct key_data *key,
 
1189
              const void *data,
 
1190
              size_t len,
 
1191
              unsigned usage,
 
1192
              Checksum *C)
 
1193
{
 
1194
    return 0;
 
1195
}
 
1196
 
 
1197
static krb5_error_code
 
1198
CRC32_checksum(krb5_context context,
 
1199
               struct key_data *key,
 
1200
               const void *data,
 
1201
               size_t len,
 
1202
               unsigned usage,
 
1203
               Checksum *C)
 
1204
{
 
1205
    uint32_t crc;
 
1206
    unsigned char *r = C->checksum.data;
 
1207
    _krb5_crc_init_table ();
 
1208
    crc = _krb5_crc_update (data, len, 0);
 
1209
    r[0] = crc & 0xff;
 
1210
    r[1] = (crc >> 8)  & 0xff;
 
1211
    r[2] = (crc >> 16) & 0xff;
 
1212
    r[3] = (crc >> 24) & 0xff;
 
1213
    return 0;
 
1214
}
 
1215
 
 
1216
static krb5_error_code
 
1217
RSA_MD4_checksum(krb5_context context,
 
1218
                 struct key_data *key,
 
1219
                 const void *data,
 
1220
                 size_t len,
 
1221
                 unsigned usage,
 
1222
                 Checksum *C)
 
1223
{
 
1224
    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
 
1225
        krb5_abortx(context, "md4 checksum failed");
 
1226
    return 0;
 
1227
}
 
1228
 
 
1229
static krb5_error_code
 
1230
des_checksum(krb5_context context,
 
1231
             const EVP_MD *evp_md,
 
1232
             struct key_data *key,
 
1233
             const void *data,
 
1234
             size_t len,
 
1235
             Checksum *cksum)
 
1236
{
 
1237
    struct evp_schedule *ctx = key->schedule->data;
 
1238
    EVP_MD_CTX *m;
 
1239
    DES_cblock ivec;
 
1240
    unsigned char *p = cksum->checksum.data;
 
1241
 
 
1242
    krb5_generate_random_block(p, 8);
 
1243
 
 
1244
    m = EVP_MD_CTX_create();
 
1245
    if (m == NULL) {
 
1246
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
1247
        return ENOMEM;
 
1248
    }
 
1249
 
 
1250
    EVP_DigestInit_ex(m, evp_md, NULL);
 
1251
    EVP_DigestUpdate(m, p, 8);
 
1252
    EVP_DigestUpdate(m, data, len);
 
1253
    EVP_DigestFinal_ex (m, p + 8, NULL);
 
1254
    EVP_MD_CTX_destroy(m);
 
1255
    memset (&ivec, 0, sizeof(ivec));
 
1256
    EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
 
1257
    EVP_Cipher(&ctx->ectx, p, p, 24);
 
1258
 
 
1259
    return 0;
 
1260
}
 
1261
 
 
1262
static krb5_error_code
 
1263
des_verify(krb5_context context,
 
1264
           const EVP_MD *evp_md,
 
1265
           struct key_data *key,
 
1266
           const void *data,
 
1267
           size_t len,
 
1268
           Checksum *C)
 
1269
{
 
1270
    struct evp_schedule *ctx = key->schedule->data;
 
1271
    EVP_MD_CTX *m;
 
1272
    unsigned char tmp[24];
 
1273
    unsigned char res[16];
 
1274
    DES_cblock ivec;
 
1275
    krb5_error_code ret = 0;
 
1276
 
 
1277
    m = EVP_MD_CTX_create();
 
1278
    if (m == NULL) {
 
1279
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
1280
        return ENOMEM;
 
1281
    }
 
1282
 
 
1283
    memset(&ivec, 0, sizeof(ivec));
 
1284
    EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
 
1285
    EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
 
1286
 
 
1287
    EVP_DigestInit_ex(m, evp_md, NULL);
 
1288
    EVP_DigestUpdate(m, tmp, 8); /* confounder */
 
1289
    EVP_DigestUpdate(m, data, len);
 
1290
    EVP_DigestFinal_ex (m, res, NULL);
 
1291
    EVP_MD_CTX_destroy(m);
 
1292
    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
 
1293
        krb5_clear_error_message (context);
 
1294
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
 
1295
    }
 
1296
    memset(tmp, 0, sizeof(tmp));
 
1297
    memset(res, 0, sizeof(res));
 
1298
    return ret;
 
1299
}
 
1300
 
 
1301
static krb5_error_code
 
1302
RSA_MD4_DES_checksum(krb5_context context,
 
1303
                     struct key_data *key,
 
1304
                     const void *data,
 
1305
                     size_t len,
 
1306
                     unsigned usage,
 
1307
                     Checksum *cksum)
 
1308
{
 
1309
    return des_checksum(context, EVP_md4(), key, data, len, cksum);
 
1310
}
 
1311
 
 
1312
static krb5_error_code
 
1313
RSA_MD4_DES_verify(krb5_context context,
 
1314
                   struct key_data *key,
 
1315
                   const void *data,
 
1316
                   size_t len,
 
1317
                   unsigned usage,
 
1318
                   Checksum *C)
 
1319
{
 
1320
    return des_verify(context, EVP_md5(), key, data, len, C);
 
1321
}
 
1322
 
 
1323
static krb5_error_code
 
1324
RSA_MD5_checksum(krb5_context context,
 
1325
                 struct key_data *key,
 
1326
                 const void *data,
 
1327
                 size_t len,
 
1328
                 unsigned usage,
 
1329
                 Checksum *C)
 
1330
{
 
1331
    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
 
1332
        krb5_abortx(context, "md5 checksum failed");
 
1333
    return 0;
 
1334
}
 
1335
 
 
1336
static krb5_error_code
 
1337
RSA_MD5_DES_checksum(krb5_context context,
 
1338
                     struct key_data *key,
 
1339
                     const void *data,
 
1340
                     size_t len,
 
1341
                     unsigned usage,
 
1342
                     Checksum *C)
 
1343
{
 
1344
    return des_checksum(context, EVP_md5(), key, data, len, C);
 
1345
}
 
1346
 
 
1347
static krb5_error_code
 
1348
RSA_MD5_DES_verify(krb5_context context,
 
1349
                   struct key_data *key,
 
1350
                   const void *data,
 
1351
                   size_t len,
 
1352
                   unsigned usage,
 
1353
                   Checksum *C)
 
1354
{
 
1355
    return des_verify(context, EVP_md5(), key, data, len, C);
 
1356
}
 
1357
 
 
1358
#ifdef DES3_OLD_ENCTYPE
 
1359
static krb5_error_code
 
1360
RSA_MD5_DES3_checksum(krb5_context context,
 
1361
                      struct key_data *key,
 
1362
                      const void *data,
 
1363
                      size_t len,
 
1364
                      unsigned usage,
 
1365
                      Checksum *C)
 
1366
{
 
1367
    return des_checksum(context, EVP_md5(), key, data, len, C);
 
1368
}
 
1369
 
 
1370
static krb5_error_code
 
1371
RSA_MD5_DES3_verify(krb5_context context,
 
1372
                    struct key_data *key,
 
1373
                    const void *data,
 
1374
                    size_t len,
 
1375
                    unsigned usage,
 
1376
                    Checksum *C)
 
1377
{
 
1378
    return des_verify(context, EVP_md5(), key, data, len, C);
 
1379
}
 
1380
#endif
 
1381
 
 
1382
static krb5_error_code
 
1383
SHA1_checksum(krb5_context context,
 
1384
              struct key_data *key,
 
1385
              const void *data,
 
1386
              size_t len,
 
1387
              unsigned usage,
 
1388
              Checksum *C)
 
1389
{
 
1390
    if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
 
1391
        krb5_abortx(context, "sha1 checksum failed");
 
1392
    return 0;
 
1393
}
 
1394
 
 
1395
/* HMAC according to RFC2104 */
 
1396
static krb5_error_code
 
1397
hmac(krb5_context context,
 
1398
     struct checksum_type *cm,
 
1399
     const void *data,
 
1400
     size_t len,
 
1401
     unsigned usage,
 
1402
     struct key_data *keyblock,
 
1403
     Checksum *result)
 
1404
{
 
1405
    unsigned char *ipad, *opad;
 
1406
    unsigned char *key;
 
1407
    size_t key_len;
 
1408
    int i;
 
1409
 
 
1410
    ipad = malloc(cm->blocksize + len);
 
1411
    if (ipad == NULL)
 
1412
        return ENOMEM;
 
1413
    opad = malloc(cm->blocksize + cm->checksumsize);
 
1414
    if (opad == NULL) {
 
1415
        free(ipad);
 
1416
        return ENOMEM;
 
1417
    }
 
1418
    memset(ipad, 0x36, cm->blocksize);
 
1419
    memset(opad, 0x5c, cm->blocksize);
 
1420
 
 
1421
    if(keyblock->key->keyvalue.length > cm->blocksize){
 
1422
        (*cm->checksum)(context,
 
1423
                        keyblock,
 
1424
                        keyblock->key->keyvalue.data,
 
1425
                        keyblock->key->keyvalue.length,
 
1426
                        usage,
 
1427
                        result);
 
1428
        key = result->checksum.data;
 
1429
        key_len = result->checksum.length;
 
1430
    } else {
 
1431
        key = keyblock->key->keyvalue.data;
 
1432
        key_len = keyblock->key->keyvalue.length;
 
1433
    }
 
1434
    for(i = 0; i < key_len; i++){
 
1435
        ipad[i] ^= key[i];
 
1436
        opad[i] ^= key[i];
 
1437
    }
 
1438
    memcpy(ipad + cm->blocksize, data, len);
 
1439
    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
 
1440
                    usage, result);
 
1441
    memcpy(opad + cm->blocksize, result->checksum.data,
 
1442
           result->checksum.length);
 
1443
    (*cm->checksum)(context, keyblock, opad,
 
1444
                    cm->blocksize + cm->checksumsize, usage, result);
 
1445
    memset(ipad, 0, cm->blocksize + len);
 
1446
    free(ipad);
 
1447
    memset(opad, 0, cm->blocksize + cm->checksumsize);
 
1448
    free(opad);
 
1449
 
 
1450
    return 0;
 
1451
}
 
1452
 
 
1453
krb5_error_code KRB5_LIB_FUNCTION
 
1454
krb5_hmac(krb5_context context,
 
1455
          krb5_cksumtype cktype,
 
1456
          const void *data,
 
1457
          size_t len,
 
1458
          unsigned usage,
 
1459
          krb5_keyblock *key,
 
1460
          Checksum *result)
 
1461
{
 
1462
    struct checksum_type *c = _find_checksum(cktype);
 
1463
    struct key_data kd;
 
1464
    krb5_error_code ret;
 
1465
 
 
1466
    if (c == NULL) {
 
1467
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1468
                                N_("checksum type %d not supported", ""),
 
1469
                                cktype);
 
1470
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1471
    }
 
1472
 
 
1473
    kd.key = key;
 
1474
    kd.schedule = NULL;
 
1475
 
 
1476
    ret = hmac(context, c, data, len, usage, &kd, result);
 
1477
 
 
1478
    if (kd.schedule)
 
1479
        krb5_free_data(context, kd.schedule);
 
1480
 
 
1481
    return ret;
 
1482
}
 
1483
 
 
1484
static krb5_error_code
 
1485
SP_HMAC_SHA1_checksum(krb5_context context,
 
1486
                      struct key_data *key,
 
1487
                      const void *data,
 
1488
                      size_t len,
 
1489
                      unsigned usage,
 
1490
                      Checksum *result)
 
1491
{
 
1492
    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
 
1493
    Checksum res;
 
1494
    char sha1_data[20];
 
1495
    krb5_error_code ret;
 
1496
 
 
1497
    res.checksum.data = sha1_data;
 
1498
    res.checksum.length = sizeof(sha1_data);
 
1499
 
 
1500
    ret = hmac(context, c, data, len, usage, key, &res);
 
1501
    if (ret)
 
1502
        krb5_abortx(context, "hmac failed");
 
1503
    memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
 
1504
    return 0;
 
1505
}
 
1506
 
 
1507
/*
 
1508
 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
 
1509
 */
 
1510
 
 
1511
static krb5_error_code
 
1512
HMAC_MD5_checksum(krb5_context context,
 
1513
                  struct key_data *key,
 
1514
                  const void *data,
 
1515
                  size_t len,
 
1516
                  unsigned usage,
 
1517
                  Checksum *result)
 
1518
{
 
1519
    EVP_MD_CTX *m;
 
1520
    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
 
1521
    const char signature[] = "signaturekey";
 
1522
    Checksum ksign_c;
 
1523
    struct key_data ksign;
 
1524
    krb5_keyblock kb;
 
1525
    unsigned char t[4];
 
1526
    unsigned char tmp[16];
 
1527
    unsigned char ksign_c_data[16];
 
1528
    krb5_error_code ret;
 
1529
 
 
1530
    m = EVP_MD_CTX_create();
 
1531
    if (m == NULL) {
 
1532
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
1533
        return ENOMEM;
 
1534
    }
 
1535
    ksign_c.checksum.length = sizeof(ksign_c_data);
 
1536
    ksign_c.checksum.data   = ksign_c_data;
 
1537
    ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
 
1538
    if (ret) {
 
1539
        EVP_MD_CTX_destroy(m);
 
1540
        return ret;
 
1541
    }
 
1542
    ksign.key = &kb;
 
1543
    kb.keyvalue = ksign_c.checksum;
 
1544
    EVP_DigestInit_ex(m, EVP_md5(), NULL);
 
1545
    t[0] = (usage >>  0) & 0xFF;
 
1546
    t[1] = (usage >>  8) & 0xFF;
 
1547
    t[2] = (usage >> 16) & 0xFF;
 
1548
    t[3] = (usage >> 24) & 0xFF;
 
1549
    EVP_DigestUpdate(m, t, 4);
 
1550
    EVP_DigestUpdate(m, data, len);
 
1551
    EVP_DigestFinal_ex (m, tmp, NULL);
 
1552
    EVP_MD_CTX_destroy(m);
 
1553
 
 
1554
    ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
 
1555
    if (ret)
 
1556
        return ret;
 
1557
    return 0;
 
1558
}
 
1559
 
 
1560
static struct checksum_type checksum_none = {
 
1561
    CKSUMTYPE_NONE,
 
1562
    "none",
 
1563
    1,
 
1564
    0,
 
1565
    0,
 
1566
    NONE_checksum,
 
1567
    NULL
 
1568
};
 
1569
static struct checksum_type checksum_crc32 = {
 
1570
    CKSUMTYPE_CRC32,
 
1571
    "crc32",
 
1572
    1,
 
1573
    4,
 
1574
    0,
 
1575
    CRC32_checksum,
 
1576
    NULL
 
1577
};
 
1578
static struct checksum_type checksum_rsa_md4 = {
 
1579
    CKSUMTYPE_RSA_MD4,
 
1580
    "rsa-md4",
 
1581
    64,
 
1582
    16,
 
1583
    F_CPROOF,
 
1584
    RSA_MD4_checksum,
 
1585
    NULL
 
1586
};
 
1587
static struct checksum_type checksum_rsa_md4_des = {
 
1588
    CKSUMTYPE_RSA_MD4_DES,
 
1589
    "rsa-md4-des",
 
1590
    64,
 
1591
    24,
 
1592
    F_KEYED | F_CPROOF | F_VARIANT,
 
1593
    RSA_MD4_DES_checksum,
 
1594
    RSA_MD4_DES_verify
 
1595
};
 
1596
static struct checksum_type checksum_rsa_md5 = {
 
1597
    CKSUMTYPE_RSA_MD5,
 
1598
    "rsa-md5",
 
1599
    64,
 
1600
    16,
 
1601
    F_CPROOF,
 
1602
    RSA_MD5_checksum,
 
1603
    NULL
 
1604
};
 
1605
static struct checksum_type checksum_rsa_md5_des = {
 
1606
    CKSUMTYPE_RSA_MD5_DES,
 
1607
    "rsa-md5-des",
 
1608
    64,
 
1609
    24,
 
1610
    F_KEYED | F_CPROOF | F_VARIANT,
 
1611
    RSA_MD5_DES_checksum,
 
1612
    RSA_MD5_DES_verify
 
1613
};
 
1614
#ifdef DES3_OLD_ENCTYPE
 
1615
static struct checksum_type checksum_rsa_md5_des3 = {
 
1616
    CKSUMTYPE_RSA_MD5_DES3,
 
1617
    "rsa-md5-des3",
 
1618
    64,
 
1619
    24,
 
1620
    F_KEYED | F_CPROOF | F_VARIANT,
 
1621
    RSA_MD5_DES3_checksum,
 
1622
    RSA_MD5_DES3_verify
 
1623
};
 
1624
#endif
 
1625
static struct checksum_type checksum_sha1 = {
 
1626
    CKSUMTYPE_SHA1,
 
1627
    "sha1",
 
1628
    64,
 
1629
    20,
 
1630
    F_CPROOF,
 
1631
    SHA1_checksum,
 
1632
    NULL
 
1633
};
 
1634
static struct checksum_type checksum_hmac_sha1_des3 = {
 
1635
    CKSUMTYPE_HMAC_SHA1_DES3,
 
1636
    "hmac-sha1-des3",
 
1637
    64,
 
1638
    20,
 
1639
    F_KEYED | F_CPROOF | F_DERIVED,
 
1640
    SP_HMAC_SHA1_checksum,
 
1641
    NULL
 
1642
};
 
1643
 
 
1644
static struct checksum_type checksum_hmac_sha1_aes128 = {
 
1645
    CKSUMTYPE_HMAC_SHA1_96_AES_128,
 
1646
    "hmac-sha1-96-aes128",
 
1647
    64,
 
1648
    12,
 
1649
    F_KEYED | F_CPROOF | F_DERIVED,
 
1650
    SP_HMAC_SHA1_checksum,
 
1651
    NULL
 
1652
};
 
1653
 
 
1654
static struct checksum_type checksum_hmac_sha1_aes256 = {
 
1655
    CKSUMTYPE_HMAC_SHA1_96_AES_256,
 
1656
    "hmac-sha1-96-aes256",
 
1657
    64,
 
1658
    12,
 
1659
    F_KEYED | F_CPROOF | F_DERIVED,
 
1660
    SP_HMAC_SHA1_checksum,
 
1661
    NULL
 
1662
};
 
1663
 
 
1664
static struct checksum_type checksum_hmac_md5 = {
 
1665
    CKSUMTYPE_HMAC_MD5,
 
1666
    "hmac-md5",
 
1667
    64,
 
1668
    16,
 
1669
    F_KEYED | F_CPROOF,
 
1670
    HMAC_MD5_checksum,
 
1671
    NULL
 
1672
};
 
1673
 
 
1674
static struct checksum_type *checksum_types[] = {
 
1675
    &checksum_none,
 
1676
    &checksum_crc32,
 
1677
    &checksum_rsa_md4,
 
1678
    &checksum_rsa_md4_des,
 
1679
    &checksum_rsa_md5,
 
1680
    &checksum_rsa_md5_des,
 
1681
#ifdef DES3_OLD_ENCTYPE
 
1682
    &checksum_rsa_md5_des3,
 
1683
#endif
 
1684
    &checksum_sha1,
 
1685
    &checksum_hmac_sha1_des3,
 
1686
    &checksum_hmac_sha1_aes128,
 
1687
    &checksum_hmac_sha1_aes256,
 
1688
    &checksum_hmac_md5
 
1689
};
 
1690
 
 
1691
static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
 
1692
 
 
1693
static struct checksum_type *
 
1694
_find_checksum(krb5_cksumtype type)
 
1695
{
 
1696
    int i;
 
1697
    for(i = 0; i < num_checksums; i++)
 
1698
        if(checksum_types[i]->type == type)
 
1699
            return checksum_types[i];
 
1700
    return NULL;
 
1701
}
 
1702
 
 
1703
static krb5_error_code
 
1704
get_checksum_key(krb5_context context,
 
1705
                 krb5_crypto crypto,
 
1706
                 unsigned usage,  /* not krb5_key_usage */
 
1707
                 struct checksum_type *ct,
 
1708
                 struct key_data **key)
 
1709
{
 
1710
    krb5_error_code ret = 0;
 
1711
 
 
1712
    if(ct->flags & F_DERIVED)
 
1713
        ret = _get_derived_key(context, crypto, usage, key);
 
1714
    else if(ct->flags & F_VARIANT) {
 
1715
        int i;
 
1716
 
 
1717
        *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
 
1718
        if(*key == NULL) {
 
1719
            krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
1720
            return ENOMEM;
 
1721
        }
 
1722
        ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
 
1723
        if(ret)
 
1724
            return ret;
 
1725
        for(i = 0; i < (*key)->key->keyvalue.length; i++)
 
1726
            ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
 
1727
    } else {
 
1728
        *key = &crypto->key;
 
1729
    }
 
1730
    if(ret == 0)
 
1731
        ret = _key_schedule(context, *key);
 
1732
    return ret;
 
1733
}
 
1734
 
 
1735
static krb5_error_code
 
1736
create_checksum (krb5_context context,
 
1737
                 struct checksum_type *ct,
 
1738
                 krb5_crypto crypto,
 
1739
                 unsigned usage,
 
1740
                 void *data,
 
1741
                 size_t len,
 
1742
                 Checksum *result)
 
1743
{
 
1744
    krb5_error_code ret;
 
1745
    struct key_data *dkey;
 
1746
    int keyed_checksum;
 
1747
 
 
1748
    if (ct->flags & F_DISABLED) {
 
1749
        krb5_clear_error_message (context);
 
1750
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1751
    }
 
1752
    keyed_checksum = (ct->flags & F_KEYED) != 0;
 
1753
    if(keyed_checksum && crypto == NULL) {
 
1754
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1755
                                N_("Checksum type %s is keyed but no "
 
1756
                                   "crypto context (key) was passed in", ""),
 
1757
                                ct->name);
 
1758
        return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
 
1759
    }
 
1760
    if(keyed_checksum) {
 
1761
        ret = get_checksum_key(context, crypto, usage, ct, &dkey);
 
1762
        if (ret)
 
1763
            return ret;
 
1764
    } else
 
1765
        dkey = NULL;
 
1766
    result->cksumtype = ct->type;
 
1767
    ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
 
1768
    if (ret)
 
1769
        return (ret);
 
1770
    return (*ct->checksum)(context, dkey, data, len, usage, result);
 
1771
}
 
1772
 
 
1773
static int
 
1774
arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
 
1775
{
 
1776
    return (ct->type == CKSUMTYPE_HMAC_MD5) &&
 
1777
        (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
 
1778
}
 
1779
 
 
1780
krb5_error_code KRB5_LIB_FUNCTION
 
1781
krb5_create_checksum(krb5_context context,
 
1782
                     krb5_crypto crypto,
 
1783
                     krb5_key_usage usage,
 
1784
                     int type,
 
1785
                     void *data,
 
1786
                     size_t len,
 
1787
                     Checksum *result)
 
1788
{
 
1789
    struct checksum_type *ct = NULL;
 
1790
    unsigned keyusage;
 
1791
 
 
1792
    /* type 0 -> pick from crypto */
 
1793
    if (type) {
 
1794
        ct = _find_checksum(type);
 
1795
    } else if (crypto) {
 
1796
        ct = crypto->et->keyed_checksum;
 
1797
        if (ct == NULL)
 
1798
            ct = crypto->et->checksum;
 
1799
    }
 
1800
 
 
1801
    if(ct == NULL) {
 
1802
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1803
                                N_("checksum type %d not supported", ""),
 
1804
                                type);
 
1805
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1806
    }
 
1807
 
 
1808
    if (arcfour_checksum_p(ct, crypto)) {
 
1809
        keyusage = usage;
 
1810
        usage2arcfour(context, &keyusage);
 
1811
    } else
 
1812
        keyusage = CHECKSUM_USAGE(usage);
 
1813
 
 
1814
    return create_checksum(context, ct, crypto, keyusage,
 
1815
                           data, len, result);
 
1816
}
 
1817
 
 
1818
static krb5_error_code
 
1819
verify_checksum(krb5_context context,
 
1820
                krb5_crypto crypto,
 
1821
                unsigned usage, /* not krb5_key_usage */
 
1822
                void *data,
 
1823
                size_t len,
 
1824
                Checksum *cksum)
 
1825
{
 
1826
    krb5_error_code ret;
 
1827
    struct key_data *dkey;
 
1828
    int keyed_checksum;
 
1829
    Checksum c;
 
1830
    struct checksum_type *ct;
 
1831
 
 
1832
    ct = _find_checksum(cksum->cksumtype);
 
1833
    if (ct == NULL || (ct->flags & F_DISABLED)) {
 
1834
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1835
                                N_("checksum type %d not supported", ""),
 
1836
                                cksum->cksumtype);
 
1837
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1838
    }
 
1839
    if(ct->checksumsize != cksum->checksum.length) {
 
1840
        krb5_clear_error_message (context);
 
1841
        return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
 
1842
    }
 
1843
    keyed_checksum = (ct->flags & F_KEYED) != 0;
 
1844
    if(keyed_checksum && crypto == NULL) {
 
1845
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1846
                                N_("Checksum type %s is keyed but no "
 
1847
                                   "crypto context (key) was passed in", ""),
 
1848
                                ct->name);
 
1849
        return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
 
1850
    }
 
1851
    if(keyed_checksum) {
 
1852
        ret = get_checksum_key(context, crypto, usage, ct, &dkey);
 
1853
        if (ret)
 
1854
            return ret;
 
1855
    } else
 
1856
        dkey = NULL;
 
1857
    if(ct->verify)
 
1858
        return (*ct->verify)(context, dkey, data, len, usage, cksum);
 
1859
 
 
1860
    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
 
1861
    if (ret)
 
1862
        return ret;
 
1863
 
 
1864
    ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
 
1865
    if (ret) {
 
1866
        krb5_data_free(&c.checksum);
 
1867
        return ret;
 
1868
    }
 
1869
 
 
1870
    if(c.checksum.length != cksum->checksum.length ||
 
1871
       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
 
1872
        krb5_clear_error_message (context);
 
1873
        ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
 
1874
    } else {
 
1875
        ret = 0;
 
1876
    }
 
1877
    krb5_data_free (&c.checksum);
 
1878
    return ret;
 
1879
}
 
1880
 
 
1881
krb5_error_code KRB5_LIB_FUNCTION
 
1882
krb5_verify_checksum(krb5_context context,
 
1883
                     krb5_crypto crypto,
 
1884
                     krb5_key_usage usage,
 
1885
                     void *data,
 
1886
                     size_t len,
 
1887
                     Checksum *cksum)
 
1888
{
 
1889
    struct checksum_type *ct;
 
1890
    unsigned keyusage;
 
1891
 
 
1892
    ct = _find_checksum(cksum->cksumtype);
 
1893
    if(ct == NULL) {
 
1894
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1895
                                N_("checksum type %d not supported", ""),
 
1896
                                cksum->cksumtype);
 
1897
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1898
    }
 
1899
 
 
1900
    if (arcfour_checksum_p(ct, crypto)) {
 
1901
        keyusage = usage;
 
1902
        usage2arcfour(context, &keyusage);
 
1903
    } else
 
1904
        keyusage = CHECKSUM_USAGE(usage);
 
1905
 
 
1906
    return verify_checksum(context, crypto, keyusage,
 
1907
                           data, len, cksum);
 
1908
}
 
1909
 
 
1910
krb5_error_code KRB5_LIB_FUNCTION
 
1911
krb5_crypto_get_checksum_type(krb5_context context,
 
1912
                              krb5_crypto crypto,
 
1913
                              krb5_cksumtype *type)
 
1914
{
 
1915
    struct checksum_type *ct = NULL;
 
1916
 
 
1917
    if (crypto != NULL) {
 
1918
        ct = crypto->et->keyed_checksum;
 
1919
        if (ct == NULL)
 
1920
            ct = crypto->et->checksum;
 
1921
    }
 
1922
 
 
1923
    if (ct == NULL) {
 
1924
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1925
                                N_("checksum type not found", ""));
 
1926
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1927
    }
 
1928
 
 
1929
    *type = ct->type;
 
1930
 
 
1931
    return 0;
 
1932
}
 
1933
 
 
1934
 
 
1935
krb5_error_code KRB5_LIB_FUNCTION
 
1936
krb5_checksumsize(krb5_context context,
 
1937
                  krb5_cksumtype type,
 
1938
                  size_t *size)
 
1939
{
 
1940
    struct checksum_type *ct = _find_checksum(type);
 
1941
    if(ct == NULL) {
 
1942
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1943
                                N_("checksum type %d not supported", ""),
 
1944
                                type);
 
1945
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1946
    }
 
1947
    *size = ct->checksumsize;
 
1948
    return 0;
 
1949
}
 
1950
 
 
1951
krb5_boolean KRB5_LIB_FUNCTION
 
1952
krb5_checksum_is_keyed(krb5_context context,
 
1953
                       krb5_cksumtype type)
 
1954
{
 
1955
    struct checksum_type *ct = _find_checksum(type);
 
1956
    if(ct == NULL) {
 
1957
        if (context)
 
1958
            krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1959
                                    N_("checksum type %d not supported", ""),
 
1960
                                    type);
 
1961
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1962
    }
 
1963
    return ct->flags & F_KEYED;
 
1964
}
 
1965
 
 
1966
krb5_boolean KRB5_LIB_FUNCTION
 
1967
krb5_checksum_is_collision_proof(krb5_context context,
 
1968
                                 krb5_cksumtype type)
 
1969
{
 
1970
    struct checksum_type *ct = _find_checksum(type);
 
1971
    if(ct == NULL) {
 
1972
        if (context)
 
1973
            krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1974
                                    N_("checksum type %d not supported", ""),
 
1975
                                    type);
 
1976
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1977
    }
 
1978
    return ct->flags & F_CPROOF;
 
1979
}
 
1980
 
 
1981
krb5_error_code KRB5_LIB_FUNCTION
 
1982
krb5_checksum_disable(krb5_context context,
 
1983
                      krb5_cksumtype type)
 
1984
{
 
1985
    struct checksum_type *ct = _find_checksum(type);
 
1986
    if(ct == NULL) {
 
1987
        if (context)
 
1988
            krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
1989
                                    N_("checksum type %d not supported", ""),
 
1990
                                    type);
 
1991
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
1992
    }
 
1993
    ct->flags |= F_DISABLED;
 
1994
    return 0;
 
1995
}
 
1996
 
 
1997
/************************************************************
 
1998
 *                                                          *
 
1999
 ************************************************************/
 
2000
 
 
2001
static krb5_error_code
 
2002
NULL_encrypt(krb5_context context,
 
2003
             struct key_data *key,
 
2004
             void *data,
 
2005
             size_t len,
 
2006
             krb5_boolean encryptp,
 
2007
             int usage,
 
2008
             void *ivec)
 
2009
{
 
2010
    return 0;
 
2011
}
 
2012
 
 
2013
static krb5_error_code
 
2014
evp_encrypt(krb5_context context,
 
2015
            struct key_data *key,
 
2016
            void *data,
 
2017
            size_t len,
 
2018
            krb5_boolean encryptp,
 
2019
            int usage,
 
2020
            void *ivec)
 
2021
{
 
2022
    struct evp_schedule *ctx = key->schedule->data;
 
2023
    EVP_CIPHER_CTX *c;
 
2024
    c = encryptp ? &ctx->ectx : &ctx->dctx;
 
2025
    if (ivec == NULL) {
 
2026
        /* alloca ? */
 
2027
        size_t len = EVP_CIPHER_CTX_iv_length(c);
 
2028
        void *loiv = malloc(len);
 
2029
        if (loiv == NULL) {
 
2030
            krb5_clear_error_message(context);
 
2031
            return ENOMEM;
 
2032
        }
 
2033
        memset(loiv, 0, len);
 
2034
        EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
 
2035
        free(loiv);
 
2036
    } else
 
2037
        EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
 
2038
    EVP_Cipher(c, data, data, len);
 
2039
    return 0;
 
2040
}
 
2041
 
 
2042
#ifdef WEAK_ENCTYPES
 
2043
static krb5_error_code
 
2044
evp_des_encrypt_null_ivec(krb5_context context,
 
2045
                          struct key_data *key,
 
2046
                          void *data,
 
2047
                          size_t len,
 
2048
                          krb5_boolean encryptp,
 
2049
                          int usage,
 
2050
                          void *ignore_ivec)
 
2051
{
 
2052
    struct evp_schedule *ctx = key->schedule->data;
 
2053
    EVP_CIPHER_CTX *c;
 
2054
    DES_cblock ivec;
 
2055
    memset(&ivec, 0, sizeof(ivec));
 
2056
    c = encryptp ? &ctx->ectx : &ctx->dctx;
 
2057
    EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
 
2058
    EVP_Cipher(c, data, data, len);
 
2059
    return 0;
 
2060
}
 
2061
 
 
2062
static krb5_error_code
 
2063
evp_des_encrypt_key_ivec(krb5_context context,
 
2064
                         struct key_data *key,
 
2065
                         void *data,
 
2066
                         size_t len,
 
2067
                         krb5_boolean encryptp,
 
2068
                         int usage,
 
2069
                         void *ignore_ivec)
 
2070
{
 
2071
    struct evp_schedule *ctx = key->schedule->data;
 
2072
    EVP_CIPHER_CTX *c;
 
2073
    DES_cblock ivec;
 
2074
    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
 
2075
    c = encryptp ? &ctx->ectx : &ctx->dctx;
 
2076
    EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
 
2077
    EVP_Cipher(c, data, data, len);
 
2078
    return 0;
 
2079
}
 
2080
 
 
2081
static krb5_error_code
 
2082
DES_CFB64_encrypt_null_ivec(krb5_context context,
 
2083
                            struct key_data *key,
 
2084
                            void *data,
 
2085
                            size_t len,
 
2086
                            krb5_boolean encryptp,
 
2087
                            int usage,
 
2088
                            void *ignore_ivec)
 
2089
{
 
2090
    DES_cblock ivec;
 
2091
    int num = 0;
 
2092
    DES_key_schedule *s = key->schedule->data;
 
2093
    memset(&ivec, 0, sizeof(ivec));
 
2094
 
 
2095
    DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
 
2096
    return 0;
 
2097
}
 
2098
 
 
2099
static krb5_error_code
 
2100
DES_PCBC_encrypt_key_ivec(krb5_context context,
 
2101
                          struct key_data *key,
 
2102
                          void *data,
 
2103
                          size_t len,
 
2104
                          krb5_boolean encryptp,
 
2105
                          int usage,
 
2106
                          void *ignore_ivec)
 
2107
{
 
2108
    DES_cblock ivec;
 
2109
    DES_key_schedule *s = key->schedule->data;
 
2110
    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
 
2111
 
 
2112
    DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
 
2113
    return 0;
 
2114
}
 
2115
#endif
 
2116
 
 
2117
/*
 
2118
 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
 
2119
 *
 
2120
 * warning: not for small children
 
2121
 */
 
2122
 
 
2123
static krb5_error_code
 
2124
ARCFOUR_subencrypt(krb5_context context,
 
2125
                   struct key_data *key,
 
2126
                   void *data,
 
2127
                   size_t len,
 
2128
                   unsigned usage,
 
2129
                   void *ivec)
 
2130
{
 
2131
    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
 
2132
    Checksum k1_c, k2_c, k3_c, cksum;
 
2133
    struct key_data ke;
 
2134
    krb5_keyblock kb;
 
2135
    unsigned char t[4];
 
2136
    RC4_KEY rc4_key;
 
2137
    unsigned char *cdata = data;
 
2138
    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
 
2139
    krb5_error_code ret;
 
2140
 
 
2141
    t[0] = (usage >>  0) & 0xFF;
 
2142
    t[1] = (usage >>  8) & 0xFF;
 
2143
    t[2] = (usage >> 16) & 0xFF;
 
2144
    t[3] = (usage >> 24) & 0xFF;
 
2145
 
 
2146
    k1_c.checksum.length = sizeof(k1_c_data);
 
2147
    k1_c.checksum.data   = k1_c_data;
 
2148
 
 
2149
    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
 
2150
    if (ret)
 
2151
        krb5_abortx(context, "hmac failed");
 
2152
 
 
2153
    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
 
2154
 
 
2155
    k2_c.checksum.length = sizeof(k2_c_data);
 
2156
    k2_c.checksum.data   = k2_c_data;
 
2157
 
 
2158
    ke.key = &kb;
 
2159
    kb.keyvalue = k2_c.checksum;
 
2160
 
 
2161
    cksum.checksum.length = 16;
 
2162
    cksum.checksum.data   = data;
 
2163
 
 
2164
    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
 
2165
    if (ret)
 
2166
        krb5_abortx(context, "hmac failed");
 
2167
 
 
2168
    ke.key = &kb;
 
2169
    kb.keyvalue = k1_c.checksum;
 
2170
 
 
2171
    k3_c.checksum.length = sizeof(k3_c_data);
 
2172
    k3_c.checksum.data   = k3_c_data;
 
2173
 
 
2174
    ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
 
2175
    if (ret)
 
2176
        krb5_abortx(context, "hmac failed");
 
2177
 
 
2178
    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
 
2179
    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
 
2180
    memset (k1_c_data, 0, sizeof(k1_c_data));
 
2181
    memset (k2_c_data, 0, sizeof(k2_c_data));
 
2182
    memset (k3_c_data, 0, sizeof(k3_c_data));
 
2183
    return 0;
 
2184
}
 
2185
 
 
2186
static krb5_error_code
 
2187
ARCFOUR_subdecrypt(krb5_context context,
 
2188
                   struct key_data *key,
 
2189
                   void *data,
 
2190
                   size_t len,
 
2191
                   unsigned usage,
 
2192
                   void *ivec)
 
2193
{
 
2194
    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
 
2195
    Checksum k1_c, k2_c, k3_c, cksum;
 
2196
    struct key_data ke;
 
2197
    krb5_keyblock kb;
 
2198
    unsigned char t[4];
 
2199
    RC4_KEY rc4_key;
 
2200
    unsigned char *cdata = data;
 
2201
    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
 
2202
    unsigned char cksum_data[16];
 
2203
    krb5_error_code ret;
 
2204
 
 
2205
    t[0] = (usage >>  0) & 0xFF;
 
2206
    t[1] = (usage >>  8) & 0xFF;
 
2207
    t[2] = (usage >> 16) & 0xFF;
 
2208
    t[3] = (usage >> 24) & 0xFF;
 
2209
 
 
2210
    k1_c.checksum.length = sizeof(k1_c_data);
 
2211
    k1_c.checksum.data   = k1_c_data;
 
2212
 
 
2213
    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
 
2214
    if (ret)
 
2215
        krb5_abortx(context, "hmac failed");
 
2216
 
 
2217
    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
 
2218
 
 
2219
    k2_c.checksum.length = sizeof(k2_c_data);
 
2220
    k2_c.checksum.data   = k2_c_data;
 
2221
 
 
2222
    ke.key = &kb;
 
2223
    kb.keyvalue = k1_c.checksum;
 
2224
 
 
2225
    k3_c.checksum.length = sizeof(k3_c_data);
 
2226
    k3_c.checksum.data   = k3_c_data;
 
2227
 
 
2228
    ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
 
2229
    if (ret)
 
2230
        krb5_abortx(context, "hmac failed");
 
2231
 
 
2232
    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
 
2233
    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
 
2234
 
 
2235
    ke.key = &kb;
 
2236
    kb.keyvalue = k2_c.checksum;
 
2237
 
 
2238
    cksum.checksum.length = 16;
 
2239
    cksum.checksum.data   = cksum_data;
 
2240
 
 
2241
    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
 
2242
    if (ret)
 
2243
        krb5_abortx(context, "hmac failed");
 
2244
 
 
2245
    memset (k1_c_data, 0, sizeof(k1_c_data));
 
2246
    memset (k2_c_data, 0, sizeof(k2_c_data));
 
2247
    memset (k3_c_data, 0, sizeof(k3_c_data));
 
2248
 
 
2249
    if (memcmp (cksum.checksum.data, data, 16) != 0) {
 
2250
        krb5_clear_error_message (context);
 
2251
        return KRB5KRB_AP_ERR_BAD_INTEGRITY;
 
2252
    } else {
 
2253
        return 0;
 
2254
    }
 
2255
}
 
2256
 
 
2257
/*
 
2258
 * convert the usage numbers used in
 
2259
 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
 
2260
 * draft-brezak-win2k-krb-rc4-hmac-04.txt
 
2261
 */
 
2262
 
 
2263
static krb5_error_code
 
2264
usage2arcfour (krb5_context context, unsigned *usage)
 
2265
{
 
2266
    switch (*usage) {
 
2267
    case KRB5_KU_AS_REP_ENC_PART : /* 3 */
 
2268
    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
 
2269
        *usage = 8;
 
2270
        return 0;
 
2271
    case KRB5_KU_USAGE_SEAL :  /* 22 */
 
2272
        *usage = 13;
 
2273
        return 0;
 
2274
    case KRB5_KU_USAGE_SIGN : /* 23 */
 
2275
        *usage = 15;
 
2276
        return 0;
 
2277
    case KRB5_KU_USAGE_SEQ: /* 24 */
 
2278
        *usage = 0;
 
2279
        return 0;
 
2280
    default :
 
2281
        return 0;
 
2282
    }
 
2283
}
 
2284
 
 
2285
static krb5_error_code
 
2286
ARCFOUR_encrypt(krb5_context context,
 
2287
                struct key_data *key,
 
2288
                void *data,
 
2289
                size_t len,
 
2290
                krb5_boolean encryptp,
 
2291
                int usage,
 
2292
                void *ivec)
 
2293
{
 
2294
    krb5_error_code ret;
 
2295
    unsigned keyusage = usage;
 
2296
 
 
2297
    if((ret = usage2arcfour (context, &keyusage)) != 0)
 
2298
        return ret;
 
2299
 
 
2300
    if (encryptp)
 
2301
        return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
 
2302
    else
 
2303
        return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
 
2304
}
 
2305
 
 
2306
 
 
2307
/*
 
2308
 *
 
2309
 */
 
2310
 
 
2311
static krb5_error_code
 
2312
AES_PRF(krb5_context context,
 
2313
        krb5_crypto crypto,
 
2314
        const krb5_data *in,
 
2315
        krb5_data *out)
 
2316
{
 
2317
    struct checksum_type *ct = crypto->et->checksum;
 
2318
    krb5_error_code ret;
 
2319
    Checksum result;
 
2320
    krb5_keyblock *derived;
 
2321
 
 
2322
    result.cksumtype = ct->type;
 
2323
    ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
 
2324
    if (ret) {
 
2325
        krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
 
2326
        return ret;
 
2327
    }
 
2328
 
 
2329
    ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
 
2330
    if (ret) {
 
2331
        krb5_data_free(&result.checksum);
 
2332
        return ret;
 
2333
    }
 
2334
 
 
2335
    if (result.checksum.length < crypto->et->blocksize)
 
2336
        krb5_abortx(context, "internal prf error");
 
2337
 
 
2338
    derived = NULL;
 
2339
    ret = krb5_derive_key(context, crypto->key.key,
 
2340
                          crypto->et->type, "prf", 3, &derived);
 
2341
    if (ret)
 
2342
        krb5_abortx(context, "krb5_derive_key");
 
2343
 
 
2344
    ret = krb5_data_alloc(out, crypto->et->blocksize);
 
2345
    if (ret)
 
2346
        krb5_abortx(context, "malloc failed");
 
2347
 
 
2348
    {
 
2349
        const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
 
2350
        EVP_CIPHER_CTX ctx;
 
2351
        /* XXX blksz 1 for cts, so we can't use that */
 
2352
        EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
 
2353
        EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
 
2354
        EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
 
2355
        EVP_CIPHER_CTX_cleanup(&ctx);
 
2356
    }
 
2357
 
 
2358
    krb5_data_free(&result.checksum);
 
2359
    krb5_free_keyblock(context, derived);
 
2360
 
 
2361
    return ret;
 
2362
}
 
2363
 
 
2364
/*
 
2365
 * these should currently be in reverse preference order.
 
2366
 * (only relevant for !F_PSEUDO) */
 
2367
 
 
2368
static struct encryption_type enctype_null = {
 
2369
    ETYPE_NULL,
 
2370
    "null",
 
2371
    1,
 
2372
    1,
 
2373
    0,
 
2374
    &keytype_null,
 
2375
    &checksum_none,
 
2376
    NULL,
 
2377
    F_DISABLED,
 
2378
    NULL_encrypt,
 
2379
    0,
 
2380
    NULL
 
2381
};
 
2382
static struct encryption_type enctype_arcfour_hmac_md5 = {
 
2383
    ETYPE_ARCFOUR_HMAC_MD5,
 
2384
    "arcfour-hmac-md5",
 
2385
    1,
 
2386
    1,
 
2387
    8,
 
2388
    &keytype_arcfour,
 
2389
    &checksum_hmac_md5,
 
2390
    NULL,
 
2391
    F_SPECIAL,
 
2392
    ARCFOUR_encrypt,
 
2393
    0,
 
2394
    NULL
 
2395
};
 
2396
#ifdef DES3_OLD_ENCTYPE
 
2397
static struct encryption_type enctype_des3_cbc_md5 = {
 
2398
    ETYPE_DES3_CBC_MD5,
 
2399
    "des3-cbc-md5",
 
2400
    8,
 
2401
    8,
 
2402
    8,
 
2403
    &keytype_des3,
 
2404
    &checksum_rsa_md5,
 
2405
    &checksum_rsa_md5_des3,
 
2406
    0,
 
2407
    evp_encrypt,
 
2408
    0,
 
2409
    NULL
 
2410
};
 
2411
#endif
 
2412
static struct encryption_type enctype_des3_cbc_sha1 = {
 
2413
    ETYPE_DES3_CBC_SHA1,
 
2414
    "des3-cbc-sha1",
 
2415
    8,
 
2416
    8,
 
2417
    8,
 
2418
    &keytype_des3_derived,
 
2419
    &checksum_sha1,
 
2420
    &checksum_hmac_sha1_des3,
 
2421
    F_DERIVED,
 
2422
    evp_encrypt,
 
2423
    0,
 
2424
    NULL
 
2425
};
 
2426
#ifdef DES3_OLD_ENCTYPE
 
2427
static struct encryption_type enctype_old_des3_cbc_sha1 = {
 
2428
    ETYPE_OLD_DES3_CBC_SHA1,
 
2429
    "old-des3-cbc-sha1",
 
2430
    8,
 
2431
    8,
 
2432
    8,
 
2433
    &keytype_des3,
 
2434
    &checksum_sha1,
 
2435
    &checksum_hmac_sha1_des3,
 
2436
    0,
 
2437
    evp_encrypt,
 
2438
    0,
 
2439
    NULL
 
2440
};
 
2441
#endif
 
2442
static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
 
2443
    ETYPE_AES128_CTS_HMAC_SHA1_96,
 
2444
    "aes128-cts-hmac-sha1-96",
 
2445
    16,
 
2446
    1,
 
2447
    16,
 
2448
    &keytype_aes128,
 
2449
    &checksum_sha1,
 
2450
    &checksum_hmac_sha1_aes128,
 
2451
    F_DERIVED,
 
2452
    evp_encrypt,
 
2453
    16,
 
2454
    AES_PRF
 
2455
};
 
2456
static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
 
2457
    ETYPE_AES256_CTS_HMAC_SHA1_96,
 
2458
    "aes256-cts-hmac-sha1-96",
 
2459
    16,
 
2460
    1,
 
2461
    16,
 
2462
    &keytype_aes256,
 
2463
    &checksum_sha1,
 
2464
    &checksum_hmac_sha1_aes256,
 
2465
    F_DERIVED,
 
2466
    evp_encrypt,
 
2467
    16,
 
2468
    AES_PRF
 
2469
};
 
2470
static struct encryption_type enctype_des3_cbc_none = {
 
2471
    ETYPE_DES3_CBC_NONE,
 
2472
    "des3-cbc-none",
 
2473
    8,
 
2474
    8,
 
2475
    0,
 
2476
    &keytype_des3_derived,
 
2477
    &checksum_none,
 
2478
    NULL,
 
2479
    F_PSEUDO,
 
2480
    evp_encrypt,
 
2481
    0,
 
2482
    NULL
 
2483
};
 
2484
#ifdef WEAK_ENCTYPES
 
2485
static struct encryption_type enctype_des_cbc_crc = {
 
2486
    ETYPE_DES_CBC_CRC,
 
2487
    "des-cbc-crc",
 
2488
    8,
 
2489
    8,
 
2490
    8,
 
2491
    &keytype_des,
 
2492
    &checksum_crc32,
 
2493
    NULL,
 
2494
    F_DISABLED,
 
2495
    evp_des_encrypt_key_ivec,
 
2496
    0,
 
2497
    NULL
 
2498
};
 
2499
static struct encryption_type enctype_des_cbc_md4 = {
 
2500
    ETYPE_DES_CBC_MD4,
 
2501
    "des-cbc-md4",
 
2502
    8,
 
2503
    8,
 
2504
    8,
 
2505
    &keytype_des,
 
2506
    &checksum_rsa_md4,
 
2507
    &checksum_rsa_md4_des,
 
2508
    F_DISABLED,
 
2509
    evp_des_encrypt_null_ivec,
 
2510
    0,
 
2511
    NULL
 
2512
};
 
2513
static struct encryption_type enctype_des_cbc_md5 = {
 
2514
    ETYPE_DES_CBC_MD5,
 
2515
    "des-cbc-md5",
 
2516
    8,
 
2517
    8,
 
2518
    8,
 
2519
    &keytype_des,
 
2520
    &checksum_rsa_md5,
 
2521
    &checksum_rsa_md5_des,
 
2522
    F_DISABLED,
 
2523
    evp_des_encrypt_null_ivec,
 
2524
    0,
 
2525
    NULL
 
2526
};
 
2527
static struct encryption_type enctype_des_cbc_none = {
 
2528
    ETYPE_DES_CBC_NONE,
 
2529
    "des-cbc-none",
 
2530
    8,
 
2531
    8,
 
2532
    0,
 
2533
    &keytype_des,
 
2534
    &checksum_none,
 
2535
    NULL,
 
2536
    F_PSEUDO|F_DISABLED,
 
2537
    evp_des_encrypt_null_ivec,
 
2538
    0,
 
2539
    NULL
 
2540
};
 
2541
static struct encryption_type enctype_des_cfb64_none = {
 
2542
    ETYPE_DES_CFB64_NONE,
 
2543
    "des-cfb64-none",
 
2544
    1,
 
2545
    1,
 
2546
    0,
 
2547
    &keytype_des_old,
 
2548
    &checksum_none,
 
2549
    NULL,
 
2550
    F_PSEUDO|F_DISABLED,
 
2551
    DES_CFB64_encrypt_null_ivec,
 
2552
    0,
 
2553
    NULL
 
2554
};
 
2555
static struct encryption_type enctype_des_pcbc_none = {
 
2556
    ETYPE_DES_PCBC_NONE,
 
2557
    "des-pcbc-none",
 
2558
    8,
 
2559
    8,
 
2560
    0,
 
2561
    &keytype_des_old,
 
2562
    &checksum_none,
 
2563
    NULL,
 
2564
    F_PSEUDO|F_DISABLED,
 
2565
    DES_PCBC_encrypt_key_ivec,
 
2566
    0,
 
2567
    NULL
 
2568
};
 
2569
#endif /* WEAK_ENCTYPES */
 
2570
 
 
2571
static struct encryption_type *etypes[] = {
 
2572
    &enctype_aes256_cts_hmac_sha1,
 
2573
    &enctype_aes128_cts_hmac_sha1,
 
2574
    &enctype_des3_cbc_sha1,
 
2575
    &enctype_des3_cbc_none, /* used by the gss-api mech */
 
2576
    &enctype_arcfour_hmac_md5,
 
2577
#ifdef DES3_OLD_ENCTYPE
 
2578
    &enctype_des3_cbc_md5,
 
2579
    &enctype_old_des3_cbc_sha1,
 
2580
#endif
 
2581
#ifdef WEAK_ENCTYPES
 
2582
    &enctype_des_cbc_crc,
 
2583
    &enctype_des_cbc_md4,
 
2584
    &enctype_des_cbc_md5,
 
2585
    &enctype_des_cbc_none,
 
2586
    &enctype_des_cfb64_none,
 
2587
    &enctype_des_pcbc_none,
 
2588
#endif
 
2589
    &enctype_null
 
2590
};
 
2591
 
 
2592
static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
 
2593
 
 
2594
 
 
2595
static struct encryption_type *
 
2596
_find_enctype(krb5_enctype type)
 
2597
{
 
2598
    int i;
 
2599
    for(i = 0; i < num_etypes; i++)
 
2600
        if(etypes[i]->type == type)
 
2601
            return etypes[i];
 
2602
    return NULL;
 
2603
}
 
2604
 
 
2605
 
 
2606
krb5_error_code KRB5_LIB_FUNCTION
 
2607
krb5_enctype_to_string(krb5_context context,
 
2608
                       krb5_enctype etype,
 
2609
                       char **string)
 
2610
{
 
2611
    struct encryption_type *e;
 
2612
    e = _find_enctype(etype);
 
2613
    if(e == NULL) {
 
2614
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
2615
                                N_("encryption type %d not supported", ""),
 
2616
                                etype);
 
2617
        *string = NULL;
 
2618
        return KRB5_PROG_ETYPE_NOSUPP;
 
2619
    }
 
2620
    *string = strdup(e->name);
 
2621
    if(*string == NULL) {
 
2622
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
2623
        return ENOMEM;
 
2624
    }
 
2625
    return 0;
 
2626
}
 
2627
 
 
2628
krb5_error_code KRB5_LIB_FUNCTION
 
2629
krb5_string_to_enctype(krb5_context context,
 
2630
                       const char *string,
 
2631
                       krb5_enctype *etype)
 
2632
{
 
2633
    int i;
 
2634
    for(i = 0; i < num_etypes; i++)
 
2635
        if(strcasecmp(etypes[i]->name, string) == 0){
 
2636
            *etype = etypes[i]->type;
 
2637
            return 0;
 
2638
        }
 
2639
    krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
2640
                            N_("encryption type %s not supported", ""),
 
2641
                            string);
 
2642
    return KRB5_PROG_ETYPE_NOSUPP;
 
2643
}
 
2644
 
 
2645
krb5_error_code KRB5_LIB_FUNCTION
 
2646
krb5_enctype_to_keytype(krb5_context context,
 
2647
                        krb5_enctype etype,
 
2648
                        krb5_keytype *keytype)
 
2649
{
 
2650
    struct encryption_type *e = _find_enctype(etype);
 
2651
    if(e == NULL) {
 
2652
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
2653
                                N_("encryption type %d not supported", ""),
 
2654
                                etype);
 
2655
        return KRB5_PROG_ETYPE_NOSUPP;
 
2656
    }
 
2657
    *keytype = e->keytype->type; /* XXX */
 
2658
    return 0;
 
2659
}
 
2660
 
 
2661
krb5_error_code KRB5_LIB_FUNCTION
 
2662
krb5_enctype_valid(krb5_context context,
 
2663
                   krb5_enctype etype)
 
2664
{
 
2665
    struct encryption_type *e = _find_enctype(etype);
 
2666
    if(e == NULL) {
 
2667
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
2668
                                N_("encryption type %d not supported", ""),
 
2669
                                etype);
 
2670
        return KRB5_PROG_ETYPE_NOSUPP;
 
2671
    }
 
2672
    if (e->flags & F_DISABLED) {
 
2673
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
2674
                                N_("encryption type %s is disabled", ""),
 
2675
                                e->name);
 
2676
        return KRB5_PROG_ETYPE_NOSUPP;
 
2677
    }
 
2678
    return 0;
 
2679
}
 
2680
 
 
2681
/**
 
2682
 * Return the coresponding encryption type for a checksum type.
 
2683
 *
 
2684
 * @param context Kerberos context
 
2685
 * @param ctype The checksum type to get the result enctype for
 
2686
 * @param etype The returned encryption, when the matching etype is
 
2687
 * not found, etype is set to ETYPE_NULL.
 
2688
 *
 
2689
 * @return Return an error code for an failure or 0 on success.
 
2690
 * @ingroup krb5_crypto
 
2691
 */
 
2692
 
 
2693
 
 
2694
krb5_error_code KRB5_LIB_FUNCTION
 
2695
krb5_cksumtype_to_enctype(krb5_context context,
 
2696
                          krb5_cksumtype ctype,
 
2697
                          krb5_enctype *etype)
 
2698
{
 
2699
    int i;
 
2700
 
 
2701
    *etype = ETYPE_NULL;
 
2702
 
 
2703
    for(i = 0; i < num_etypes; i++) {
 
2704
        if(etypes[i]->keyed_checksum &&
 
2705
           etypes[i]->keyed_checksum->type == ctype)
 
2706
            {
 
2707
                *etype = etypes[i]->type;
 
2708
                return 0;
 
2709
            }
 
2710
    }
 
2711
 
 
2712
    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
2713
                            N_("checksum type %d not supported", ""),
 
2714
                            (int)ctype);
 
2715
    return KRB5_PROG_SUMTYPE_NOSUPP;
 
2716
}
 
2717
 
 
2718
 
 
2719
krb5_error_code KRB5_LIB_FUNCTION
 
2720
krb5_cksumtype_valid(krb5_context context,
 
2721
                     krb5_cksumtype ctype)
 
2722
{
 
2723
    struct checksum_type *c = _find_checksum(ctype);
 
2724
    if (c == NULL) {
 
2725
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
2726
                                N_("checksum type %d not supported", ""),
 
2727
                                ctype);
 
2728
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
2729
    }
 
2730
    if (c->flags & F_DISABLED) {
 
2731
        krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
 
2732
                                N_("checksum type %s is disabled", ""),
 
2733
                                c->name);
 
2734
        return KRB5_PROG_SUMTYPE_NOSUPP;
 
2735
    }
 
2736
    return 0;
 
2737
}
 
2738
 
 
2739
 
 
2740
/* if two enctypes have compatible keys */
 
2741
krb5_boolean KRB5_LIB_FUNCTION
 
2742
krb5_enctypes_compatible_keys(krb5_context context,
 
2743
                              krb5_enctype etype1,
 
2744
                              krb5_enctype etype2)
 
2745
{
 
2746
    struct encryption_type *e1 = _find_enctype(etype1);
 
2747
    struct encryption_type *e2 = _find_enctype(etype2);
 
2748
    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
 
2749
}
 
2750
 
 
2751
static krb5_boolean
 
2752
derived_crypto(krb5_context context,
 
2753
               krb5_crypto crypto)
 
2754
{
 
2755
    return (crypto->et->flags & F_DERIVED) != 0;
 
2756
}
 
2757
 
 
2758
static krb5_boolean
 
2759
special_crypto(krb5_context context,
 
2760
               krb5_crypto crypto)
 
2761
{
 
2762
    return (crypto->et->flags & F_SPECIAL) != 0;
 
2763
}
 
2764
 
 
2765
#define CHECKSUMSIZE(C) ((C)->checksumsize)
 
2766
#define CHECKSUMTYPE(C) ((C)->type)
 
2767
 
 
2768
static krb5_error_code
 
2769
encrypt_internal_derived(krb5_context context,
 
2770
                         krb5_crypto crypto,
 
2771
                         unsigned usage,
 
2772
                         const void *data,
 
2773
                         size_t len,
 
2774
                         krb5_data *result,
 
2775
                         void *ivec)
 
2776
{
 
2777
    size_t sz, block_sz, checksum_sz, total_sz;
 
2778
    Checksum cksum;
 
2779
    unsigned char *p, *q;
 
2780
    krb5_error_code ret;
 
2781
    struct key_data *dkey;
 
2782
    const struct encryption_type *et = crypto->et;
 
2783
 
 
2784
    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
 
2785
 
 
2786
    sz = et->confoundersize + len;
 
2787
    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
 
2788
    total_sz = block_sz + checksum_sz;
 
2789
    p = calloc(1, total_sz);
 
2790
    if(p == NULL) {
 
2791
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
2792
        return ENOMEM;
 
2793
    }
 
2794
 
 
2795
    q = p;
 
2796
    krb5_generate_random_block(q, et->confoundersize); /* XXX */
 
2797
    q += et->confoundersize;
 
2798
    memcpy(q, data, len);
 
2799
 
 
2800
    ret = create_checksum(context,
 
2801
                          et->keyed_checksum,
 
2802
                          crypto,
 
2803
                          INTEGRITY_USAGE(usage),
 
2804
                          p,
 
2805
                          block_sz,
 
2806
                          &cksum);
 
2807
    if(ret == 0 && cksum.checksum.length != checksum_sz) {
 
2808
        free_Checksum (&cksum);
 
2809
        krb5_clear_error_message (context);
 
2810
        ret = KRB5_CRYPTO_INTERNAL;
 
2811
    }
 
2812
    if(ret)
 
2813
        goto fail;
 
2814
    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
 
2815
    free_Checksum (&cksum);
 
2816
    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
 
2817
    if(ret)
 
2818
        goto fail;
 
2819
    ret = _key_schedule(context, dkey);
 
2820
    if(ret)
 
2821
        goto fail;
 
2822
    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
 
2823
    if (ret)
 
2824
        goto fail;
 
2825
    result->data = p;
 
2826
    result->length = total_sz;
 
2827
    return 0;
 
2828
 fail:
 
2829
    memset(p, 0, total_sz);
 
2830
    free(p);
 
2831
    return ret;
 
2832
}
 
2833
 
 
2834
 
 
2835
static krb5_error_code
 
2836
encrypt_internal(krb5_context context,
 
2837
                 krb5_crypto crypto,
 
2838
                 const void *data,
 
2839
                 size_t len,
 
2840
                 krb5_data *result,
 
2841
                 void *ivec)
 
2842
{
 
2843
    size_t sz, block_sz, checksum_sz;
 
2844
    Checksum cksum;
 
2845
    unsigned char *p, *q;
 
2846
    krb5_error_code ret;
 
2847
    const struct encryption_type *et = crypto->et;
 
2848
 
 
2849
    checksum_sz = CHECKSUMSIZE(et->checksum);
 
2850
 
 
2851
    sz = et->confoundersize + checksum_sz + len;
 
2852
    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
 
2853
    p = calloc(1, block_sz);
 
2854
    if(p == NULL) {
 
2855
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
2856
        return ENOMEM;
 
2857
    }
 
2858
 
 
2859
    q = p;
 
2860
    krb5_generate_random_block(q, et->confoundersize); /* XXX */
 
2861
    q += et->confoundersize;
 
2862
    memset(q, 0, checksum_sz);
 
2863
    q += checksum_sz;
 
2864
    memcpy(q, data, len);
 
2865
 
 
2866
    ret = create_checksum(context,
 
2867
                          et->checksum,
 
2868
                          crypto,
 
2869
                          0,
 
2870
                          p,
 
2871
                          block_sz,
 
2872
                          &cksum);
 
2873
    if(ret == 0 && cksum.checksum.length != checksum_sz) {
 
2874
        krb5_clear_error_message (context);
 
2875
        free_Checksum(&cksum);
 
2876
        ret = KRB5_CRYPTO_INTERNAL;
 
2877
    }
 
2878
    if(ret)
 
2879
        goto fail;
 
2880
    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
 
2881
    free_Checksum(&cksum);
 
2882
    ret = _key_schedule(context, &crypto->key);
 
2883
    if(ret)
 
2884
        goto fail;
 
2885
    ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
 
2886
    if (ret) {
 
2887
        memset(p, 0, block_sz);
 
2888
        free(p);
 
2889
        return ret;
 
2890
    }
 
2891
    result->data = p;
 
2892
    result->length = block_sz;
 
2893
    return 0;
 
2894
 fail:
 
2895
    memset(p, 0, block_sz);
 
2896
    free(p);
 
2897
    return ret;
 
2898
}
 
2899
 
 
2900
static krb5_error_code
 
2901
encrypt_internal_special(krb5_context context,
 
2902
                         krb5_crypto crypto,
 
2903
                         int usage,
 
2904
                         const void *data,
 
2905
                         size_t len,
 
2906
                         krb5_data *result,
 
2907
                         void *ivec)
 
2908
{
 
2909
    struct encryption_type *et = crypto->et;
 
2910
    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
 
2911
    size_t sz = len + cksum_sz + et->confoundersize;
 
2912
    char *tmp, *p;
 
2913
    krb5_error_code ret;
 
2914
 
 
2915
    tmp = malloc (sz);
 
2916
    if (tmp == NULL) {
 
2917
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
2918
        return ENOMEM;
 
2919
    }
 
2920
    p = tmp;
 
2921
    memset (p, 0, cksum_sz);
 
2922
    p += cksum_sz;
 
2923
    krb5_generate_random_block(p, et->confoundersize);
 
2924
    p += et->confoundersize;
 
2925
    memcpy (p, data, len);
 
2926
    ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
 
2927
    if (ret) {
 
2928
        memset(tmp, 0, sz);
 
2929
        free(tmp);
 
2930
        return ret;
 
2931
    }
 
2932
    result->data   = tmp;
 
2933
    result->length = sz;
 
2934
    return 0;
 
2935
}
 
2936
 
 
2937
static krb5_error_code
 
2938
decrypt_internal_derived(krb5_context context,
 
2939
                         krb5_crypto crypto,
 
2940
                         unsigned usage,
 
2941
                         void *data,
 
2942
                         size_t len,
 
2943
                         krb5_data *result,
 
2944
                         void *ivec)
 
2945
{
 
2946
    size_t checksum_sz;
 
2947
    Checksum cksum;
 
2948
    unsigned char *p;
 
2949
    krb5_error_code ret;
 
2950
    struct key_data *dkey;
 
2951
    struct encryption_type *et = crypto->et;
 
2952
    unsigned long l;
 
2953
 
 
2954
    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
 
2955
    if (len < checksum_sz + et->confoundersize) {
 
2956
        krb5_set_error_message(context, KRB5_BAD_MSIZE,
 
2957
                               N_("Encrypted data shorter then "
 
2958
                                  "checksum + confunder", ""));
 
2959
        return KRB5_BAD_MSIZE;
 
2960
    }
 
2961
 
 
2962
    if (((len - checksum_sz) % et->padsize) != 0) {
 
2963
        krb5_clear_error_message(context);
 
2964
        return KRB5_BAD_MSIZE;
 
2965
    }
 
2966
 
 
2967
    p = malloc(len);
 
2968
    if(len != 0 && p == NULL) {
 
2969
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
2970
        return ENOMEM;
 
2971
    }
 
2972
    memcpy(p, data, len);
 
2973
 
 
2974
    len -= checksum_sz;
 
2975
 
 
2976
    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
 
2977
    if(ret) {
 
2978
        free(p);
 
2979
        return ret;
 
2980
    }
 
2981
    ret = _key_schedule(context, dkey);
 
2982
    if(ret) {
 
2983
        free(p);
 
2984
        return ret;
 
2985
    }
 
2986
    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
 
2987
    if (ret) {
 
2988
        free(p);
 
2989
        return ret;
 
2990
    }
 
2991
 
 
2992
    cksum.checksum.data   = p + len;
 
2993
    cksum.checksum.length = checksum_sz;
 
2994
    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
 
2995
 
 
2996
    ret = verify_checksum(context,
 
2997
                          crypto,
 
2998
                          INTEGRITY_USAGE(usage),
 
2999
                          p,
 
3000
                          len,
 
3001
                          &cksum);
 
3002
    if(ret) {
 
3003
        free(p);
 
3004
        return ret;
 
3005
    }
 
3006
    l = len - et->confoundersize;
 
3007
    memmove(p, p + et->confoundersize, l);
 
3008
    result->data = realloc(p, l);
 
3009
    if(result->data == NULL && l != 0) {
 
3010
        free(p);
 
3011
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3012
        return ENOMEM;
 
3013
    }
 
3014
    result->length = l;
 
3015
    return 0;
 
3016
}
 
3017
 
 
3018
static krb5_error_code
 
3019
decrypt_internal(krb5_context context,
 
3020
                 krb5_crypto crypto,
 
3021
                 void *data,
 
3022
                 size_t len,
 
3023
                 krb5_data *result,
 
3024
                 void *ivec)
 
3025
{
 
3026
    krb5_error_code ret;
 
3027
    unsigned char *p;
 
3028
    Checksum cksum;
 
3029
    size_t checksum_sz, l;
 
3030
    struct encryption_type *et = crypto->et;
 
3031
 
 
3032
    if ((len % et->padsize) != 0) {
 
3033
        krb5_clear_error_message(context);
 
3034
        return KRB5_BAD_MSIZE;
 
3035
    }
 
3036
 
 
3037
    checksum_sz = CHECKSUMSIZE(et->checksum);
 
3038
    p = malloc(len);
 
3039
    if(len != 0 && p == NULL) {
 
3040
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3041
        return ENOMEM;
 
3042
    }
 
3043
    memcpy(p, data, len);
 
3044
 
 
3045
    ret = _key_schedule(context, &crypto->key);
 
3046
    if(ret) {
 
3047
        free(p);
 
3048
        return ret;
 
3049
    }
 
3050
    ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
 
3051
    if (ret) {
 
3052
        free(p);
 
3053
        return ret;
 
3054
    }
 
3055
    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
 
3056
    if(ret) {
 
3057
        free(p);
 
3058
        return ret;
 
3059
    }
 
3060
    memset(p + et->confoundersize, 0, checksum_sz);
 
3061
    cksum.cksumtype = CHECKSUMTYPE(et->checksum);
 
3062
    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
 
3063
    free_Checksum(&cksum);
 
3064
    if(ret) {
 
3065
        free(p);
 
3066
        return ret;
 
3067
    }
 
3068
    l = len - et->confoundersize - checksum_sz;
 
3069
    memmove(p, p + et->confoundersize + checksum_sz, l);
 
3070
    result->data = realloc(p, l);
 
3071
    if(result->data == NULL && l != 0) {
 
3072
        free(p);
 
3073
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3074
        return ENOMEM;
 
3075
    }
 
3076
    result->length = l;
 
3077
    return 0;
 
3078
}
 
3079
 
 
3080
static krb5_error_code
 
3081
decrypt_internal_special(krb5_context context,
 
3082
                         krb5_crypto crypto,
 
3083
                         int usage,
 
3084
                         void *data,
 
3085
                         size_t len,
 
3086
                         krb5_data *result,
 
3087
                         void *ivec)
 
3088
{
 
3089
    struct encryption_type *et = crypto->et;
 
3090
    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
 
3091
    size_t sz = len - cksum_sz - et->confoundersize;
 
3092
    unsigned char *p;
 
3093
    krb5_error_code ret;
 
3094
 
 
3095
    if ((len % et->padsize) != 0) {
 
3096
        krb5_clear_error_message(context);
 
3097
        return KRB5_BAD_MSIZE;
 
3098
    }
 
3099
 
 
3100
    p = malloc (len);
 
3101
    if (p == NULL) {
 
3102
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3103
        return ENOMEM;
 
3104
    }
 
3105
    memcpy(p, data, len);
 
3106
 
 
3107
    ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
 
3108
    if (ret) {
 
3109
        free(p);
 
3110
        return ret;
 
3111
    }
 
3112
 
 
3113
    memmove (p, p + cksum_sz + et->confoundersize, sz);
 
3114
    result->data = realloc(p, sz);
 
3115
    if(result->data == NULL && sz != 0) {
 
3116
        free(p);
 
3117
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3118
        return ENOMEM;
 
3119
    }
 
3120
    result->length = sz;
 
3121
    return 0;
 
3122
}
 
3123
 
 
3124
static krb5_crypto_iov *
 
3125
find_iv(krb5_crypto_iov *data, int num_data, int type)
 
3126
{
 
3127
    int i;
 
3128
    for (i = 0; i < num_data; i++)
 
3129
        if (data[i].flags == type)
 
3130
            return &data[i];
 
3131
    return NULL;
 
3132
}
 
3133
 
 
3134
/**
 
3135
 * Inline encrypt a kerberos message
 
3136
 *
 
3137
 * @param context Kerberos context
 
3138
 * @param crypto Kerberos crypto context
 
3139
 * @param usage Key usage for this buffer
 
3140
 * @param data array of buffers to process
 
3141
 * @param num_data length of array
 
3142
 * @param ivec initial cbc/cts vector
 
3143
 *
 
3144
 * @return Return an error code or 0.
 
3145
 * @ingroup krb5_crypto
 
3146
 *
 
3147
 * Kerberos encrypted data look like this:
 
3148
 *
 
3149
 * 1. KRB5_CRYPTO_TYPE_HEADER
 
3150
 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
 
3151
 *  any order, however the receiver have to aware of the
 
3152
 *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
 
3153
 *  trailers.
 
3154
 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
 
3155
 * 4. KRB5_CRYPTO_TYPE_TRAILER
 
3156
 */
 
3157
 
 
3158
krb5_error_code KRB5_LIB_FUNCTION
 
3159
krb5_encrypt_iov_ivec(krb5_context context,
 
3160
                      krb5_crypto crypto,
 
3161
                      unsigned usage,
 
3162
                      krb5_crypto_iov *data,
 
3163
                      size_t num_data,
 
3164
                      void *ivec)
 
3165
{
 
3166
    size_t headersz, trailersz, len;
 
3167
    size_t i, sz, block_sz, pad_sz;
 
3168
    Checksum cksum;
 
3169
    unsigned char *p, *q;
 
3170
    krb5_error_code ret;
 
3171
    struct key_data *dkey;
 
3172
    const struct encryption_type *et = crypto->et;
 
3173
    krb5_crypto_iov *tiv, *piv, *hiv;
 
3174
 
 
3175
    if(!derived_crypto(context, crypto)) {
 
3176
        krb5_clear_error_message(context);
 
3177
        return KRB5_CRYPTO_INTERNAL;
 
3178
    }
 
3179
 
 
3180
    headersz = et->confoundersize;
 
3181
    trailersz = CHECKSUMSIZE(et->keyed_checksum);
 
3182
 
 
3183
    for (len = 0, i = 0; i < num_data; i++) {
 
3184
        if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
 
3185
            data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
 
3186
            len += data[i].data.length;
 
3187
        }
 
3188
    }
 
3189
 
 
3190
    sz = headersz + len;
 
3191
    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
 
3192
 
 
3193
    pad_sz = block_sz - sz;
 
3194
    trailersz += pad_sz;
 
3195
 
 
3196
    /* header */
 
3197
 
 
3198
    hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
 
3199
    if (hiv == NULL || hiv->data.length != headersz)
 
3200
        return KRB5_BAD_MSIZE;
 
3201
 
 
3202
    krb5_generate_random_block(hiv->data.data, hiv->data.length);
 
3203
 
 
3204
    /* padding */
 
3205
 
 
3206
    piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
 
3207
    /* its ok to have no TYPE_PADDING if there is no padding */
 
3208
    if (piv == NULL && pad_sz != 0)
 
3209
        return KRB5_BAD_MSIZE;
 
3210
    if (piv) {
 
3211
        if (piv->data.length < pad_sz)
 
3212
            return KRB5_BAD_MSIZE;
 
3213
        piv->data.length = pad_sz;
 
3214
    }
 
3215
 
 
3216
 
 
3217
    /* trailer */
 
3218
 
 
3219
    tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
 
3220
    if (tiv == NULL || tiv->data.length != trailersz)
 
3221
        return KRB5_BAD_MSIZE;
 
3222
 
 
3223
 
 
3224
    /*
 
3225
     * XXX replace with EVP_Sign? at least make create_checksum an iov
 
3226
     * function.
 
3227
     * XXX CTS EVP is broken, can't handle multi buffers :(
 
3228
     */
 
3229
 
 
3230
    len = hiv->data.length;
 
3231
    for (i = 0; i < num_data; i++) {
 
3232
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3233
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3234
            continue;
 
3235
        len += data[i].data.length;
 
3236
    }
 
3237
 
 
3238
    p = q = malloc(len);
 
3239
 
 
3240
    memcpy(q, hiv->data.data, hiv->data.length);
 
3241
    q += hiv->data.length;
 
3242
    for (i = 0; i < num_data; i++) {
 
3243
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3244
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3245
            continue;
 
3246
        memcpy(q, data[i].data.data, data[i].data.length);
 
3247
        q += data[i].data.length;
 
3248
    }
 
3249
 
 
3250
    ret = create_checksum(context,
 
3251
                          et->keyed_checksum,
 
3252
                          crypto,
 
3253
                          INTEGRITY_USAGE(usage),
 
3254
                          p,
 
3255
                          len,
 
3256
                          &cksum);
 
3257
    free(p);
 
3258
    if(ret == 0 && cksum.checksum.length != trailersz) {
 
3259
        free_Checksum (&cksum);
 
3260
        krb5_clear_error_message (context);
 
3261
        ret = KRB5_CRYPTO_INTERNAL;
 
3262
    }
 
3263
    if(ret)
 
3264
        return ret;
 
3265
 
 
3266
    /* save cksum at end */
 
3267
    memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
 
3268
    free_Checksum (&cksum);
 
3269
 
 
3270
    /* now encrypt data */
 
3271
 
 
3272
    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
 
3273
    if(ret)
 
3274
        return ret;
 
3275
    ret = _key_schedule(context, dkey);
 
3276
    if(ret)
 
3277
        return ret;
 
3278
 
 
3279
    /* XXX replace with EVP_Cipher */
 
3280
 
 
3281
    len = hiv->data.length;
 
3282
    for (i = 0; i < num_data; i++) {
 
3283
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3284
            data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
 
3285
            continue;
 
3286
        len += data[i].data.length;
 
3287
    }
 
3288
 
 
3289
    p = q = malloc(len);
 
3290
    if(p == NULL)
 
3291
        return ENOMEM;
 
3292
 
 
3293
    memcpy(q, hiv->data.data, hiv->data.length);
 
3294
    q += hiv->data.length;
 
3295
    for (i = 0; i < num_data; i++) {
 
3296
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3297
            data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
 
3298
            continue;
 
3299
        memcpy(q, data[i].data.data, data[i].data.length);
 
3300
        q += data[i].data.length;
 
3301
    }
 
3302
 
 
3303
    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
 
3304
    if(ret) {
 
3305
        free(p);
 
3306
        return ret;
 
3307
    }
 
3308
    ret = _key_schedule(context, dkey);
 
3309
    if(ret) {
 
3310
        free(p);
 
3311
        return ret;
 
3312
    }
 
3313
 
 
3314
    ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
 
3315
    if (ret) {
 
3316
        free(p);
 
3317
        return ret;
 
3318
    }
 
3319
 
 
3320
    /* now copy data back to buffers */
 
3321
    q = p;
 
3322
    memcpy(hiv->data.data, q, hiv->data.length);
 
3323
    q += hiv->data.length;
 
3324
 
 
3325
    for (i = 0; i < num_data; i++) {
 
3326
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3327
            data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
 
3328
            continue;
 
3329
        memcpy(data[i].data.data, q, data[i].data.length);
 
3330
        q += data[i].data.length;
 
3331
    }
 
3332
    free(p);
 
3333
 
 
3334
    return ret;
 
3335
}
 
3336
 
 
3337
/**
 
3338
 * Inline decrypt a Kerberos message.
 
3339
 *
 
3340
 * @param context Kerberos context
 
3341
 * @param crypto Kerberos crypto context
 
3342
 * @param usage Key usage for this buffer
 
3343
 * @param data array of buffers to process
 
3344
 * @param num_data length of array
 
3345
 * @param ivec initial cbc/cts vector
 
3346
 *
 
3347
 * @return Return an error code or 0.
 
3348
 * @ingroup krb5_crypto
 
3349
 *
 
3350
 * 1. KRB5_CRYPTO_TYPE_HEADER
 
3351
 * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
 
3352
 *  any order, however the receiver have to aware of the
 
3353
 *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
 
3354
 *  protocol headers and trailers. The output data will be of same
 
3355
 *  size as the input data or shorter.
 
3356
 */
 
3357
 
 
3358
krb5_error_code KRB5_LIB_FUNCTION
 
3359
krb5_decrypt_iov_ivec(krb5_context context,
 
3360
                      krb5_crypto crypto,
 
3361
                      unsigned usage,
 
3362
                      krb5_crypto_iov *data,
 
3363
                      size_t num_data,
 
3364
                      void *ivec)
 
3365
{
 
3366
    size_t headersz, trailersz, len;
 
3367
    size_t i, sz, block_sz, pad_sz;
 
3368
    Checksum cksum;
 
3369
    unsigned char *p, *q;
 
3370
    krb5_error_code ret;
 
3371
    struct key_data *dkey;
 
3372
    struct encryption_type *et = crypto->et;
 
3373
    krb5_crypto_iov *tiv, *hiv;
 
3374
 
 
3375
    if(!derived_crypto(context, crypto)) {
 
3376
        krb5_clear_error_message(context);
 
3377
        return KRB5_CRYPTO_INTERNAL;
 
3378
    }
 
3379
 
 
3380
    headersz = et->confoundersize;
 
3381
    trailersz = CHECKSUMSIZE(et->keyed_checksum);
 
3382
 
 
3383
    for (len = 0, i = 0; i < num_data; i++)
 
3384
        if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
 
3385
            len += data[i].data.length;
 
3386
 
 
3387
    sz = headersz + len;
 
3388
    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
 
3389
 
 
3390
    pad_sz = block_sz - sz;
 
3391
    trailersz += pad_sz;
 
3392
 
 
3393
    /* header */
 
3394
 
 
3395
    hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
 
3396
    if (hiv == NULL || hiv->data.length < headersz)
 
3397
        return KRB5_BAD_MSIZE;
 
3398
    hiv->data.length = headersz;
 
3399
 
 
3400
    /* trailer */
 
3401
 
 
3402
    tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
 
3403
    if (tiv == NULL || tiv->data.length < trailersz)
 
3404
        return KRB5_BAD_MSIZE;
 
3405
    tiv->data.length = trailersz;
 
3406
 
 
3407
    /* body */
 
3408
 
 
3409
    /* XXX replace with EVP_Cipher */
 
3410
 
 
3411
    for (len = 0, i = 0; i < num_data; i++) {
 
3412
        if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
 
3413
            data[i].flags != KRB5_CRYPTO_TYPE_DATA)
 
3414
            continue;
 
3415
        len += data[i].data.length;
 
3416
    }
 
3417
 
 
3418
    p = q = malloc(len);
 
3419
    if (p == NULL)
 
3420
        return ENOMEM;
 
3421
 
 
3422
    memcpy(q, hiv->data.data, hiv->data.length);
 
3423
    q += hiv->data.length;
 
3424
    for (i = 0; i < num_data; i++) {
 
3425
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
 
3426
            continue;
 
3427
        memcpy(q, data[i].data.data, data[i].data.length);
 
3428
        q += data[i].data.length;
 
3429
    }
 
3430
 
 
3431
    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
 
3432
    if(ret) {
 
3433
        free(p);
 
3434
        return ret;
 
3435
    }
 
3436
    ret = _key_schedule(context, dkey);
 
3437
    if(ret) {
 
3438
        free(p);
 
3439
        return ret;
 
3440
    }
 
3441
 
 
3442
    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
 
3443
    if (ret) {
 
3444
        free(p);
 
3445
        return ret;
 
3446
    }
 
3447
 
 
3448
    /* XXX now copy data back to buffers */
 
3449
    q = p;
 
3450
    memcpy(hiv->data.data, q, hiv->data.length);
 
3451
    q += hiv->data.length;
 
3452
    len -= hiv->data.length;
 
3453
 
 
3454
    for (i = 0; i < num_data; i++) {
 
3455
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
 
3456
            continue;
 
3457
        if (len < data[i].data.length)
 
3458
            data[i].data.length = len;
 
3459
        memcpy(data[i].data.data, q, data[i].data.length);
 
3460
        q += data[i].data.length;
 
3461
        len -= data[i].data.length;
 
3462
    }
 
3463
    free(p);
 
3464
    if (len)
 
3465
        krb5_abortx(context, "data still in the buffer");
 
3466
 
 
3467
    len = hiv->data.length;
 
3468
    for (i = 0; i < num_data; i++) {
 
3469
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3470
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3471
            continue;
 
3472
        len += data[i].data.length;
 
3473
    }
 
3474
 
 
3475
    p = q = malloc(len);
 
3476
 
 
3477
    memcpy(q, hiv->data.data, hiv->data.length);
 
3478
    q += hiv->data.length;
 
3479
    for (i = 0; i < num_data; i++) {
 
3480
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3481
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3482
            continue;
 
3483
        memcpy(q, data[i].data.data, data[i].data.length);
 
3484
        q += data[i].data.length;
 
3485
    }
 
3486
 
 
3487
    cksum.checksum.data   = tiv->data.data;
 
3488
    cksum.checksum.length = tiv->data.length;
 
3489
    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
 
3490
 
 
3491
    ret = verify_checksum(context,
 
3492
                          crypto,
 
3493
                          INTEGRITY_USAGE(usage),
 
3494
                          p,
 
3495
                          len,
 
3496
                          &cksum);
 
3497
    free(p);
 
3498
    return ret;
 
3499
}
 
3500
 
 
3501
/**
 
3502
 * Create a Kerberos message checksum.
 
3503
 *
 
3504
 * @param context Kerberos context
 
3505
 * @param crypto Kerberos crypto context
 
3506
 * @param usage Key usage for this buffer
 
3507
 * @param data array of buffers to process
 
3508
 * @param num_data length of array
 
3509
 * @param result output data
 
3510
 *
 
3511
 * @return Return an error code or 0.
 
3512
 * @ingroup krb5_crypto
 
3513
 */
 
3514
 
 
3515
krb5_error_code KRB5_LIB_FUNCTION
 
3516
krb5_create_checksum_iov(krb5_context context,
 
3517
                         krb5_crypto crypto,
 
3518
                         unsigned usage,
 
3519
                         krb5_crypto_iov *data,
 
3520
                         size_t num_data,
 
3521
                         krb5_cksumtype *type)
 
3522
{
 
3523
    Checksum cksum;
 
3524
    krb5_crypto_iov *civ;
 
3525
    krb5_error_code ret;
 
3526
    unsigned int i;
 
3527
    size_t len;
 
3528
    char *p, *q;
 
3529
 
 
3530
    if(!derived_crypto(context, crypto)) {
 
3531
        krb5_clear_error_message(context);
 
3532
        return KRB5_CRYPTO_INTERNAL;
 
3533
    }
 
3534
 
 
3535
    civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
 
3536
    if (civ == NULL)
 
3537
        return KRB5_BAD_MSIZE;
 
3538
 
 
3539
    len = 0;
 
3540
    for (i = 0; i < num_data; i++) {
 
3541
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3542
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3543
            continue;
 
3544
        len += data[i].data.length;
 
3545
    }
 
3546
 
 
3547
    p = q = malloc(len);
 
3548
 
 
3549
    for (i = 0; i < num_data; i++) {
 
3550
        if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
 
3551
            data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
 
3552
            continue;
 
3553
        memcpy(q, data[i].data.data, data[i].data.length);
 
3554
        q += data[i].data.length;
 
3555
    }
 
3556
 
 
3557
    ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
 
3558
    free(p);
 
3559
    if (ret)
 
3560
        return ret;
 
3561
 
 
3562
    if (type)
 
3563
        *type = cksum.cksumtype;
 
3564
 
 
3565
    if (cksum.checksum.length > civ->data.length) {
 
3566
        krb5_set_error_message(context, KRB5_BAD_MSIZE,
 
3567
                               N_("Checksum larger then input buffer", ""));
 
3568
        free_Checksum(&cksum);
 
3569
        return KRB5_BAD_MSIZE;
 
3570
    }
 
3571
 
 
3572
    civ->data.length = cksum.checksum.length;
 
3573
    memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
 
3574
    free_Checksum(&cksum);
 
3575
 
 
3576
    return 0;
 
3577
}
 
3578
 
 
3579
 
 
3580
size_t KRB5_LIB_FUNCTION
 
3581
krb5_crypto_length(krb5_context context,
 
3582
                   krb5_crypto crypto,
 
3583
                   int type)
 
3584
{
 
3585
    if (!derived_crypto(context, crypto))
 
3586
        return (size_t)-1;
 
3587
    switch(type) {
 
3588
    case KRB5_CRYPTO_TYPE_EMPTY:
 
3589
        return 0;
 
3590
    case KRB5_CRYPTO_TYPE_HEADER:
 
3591
        return crypto->et->blocksize;
 
3592
    case KRB5_CRYPTO_TYPE_PADDING:
 
3593
        if (crypto->et->padsize > 1)
 
3594
            return crypto->et->padsize;
 
3595
        return 0;
 
3596
    case KRB5_CRYPTO_TYPE_TRAILER:
 
3597
        return CHECKSUMSIZE(crypto->et->keyed_checksum);
 
3598
    case KRB5_CRYPTO_TYPE_CHECKSUM:
 
3599
        if (crypto->et->keyed_checksum)
 
3600
            return CHECKSUMSIZE(crypto->et->keyed_checksum);
 
3601
        return CHECKSUMSIZE(crypto->et->checksum);
 
3602
    }
 
3603
    return (size_t)-1;
 
3604
}
 
3605
 
 
3606
krb5_error_code KRB5_LIB_FUNCTION
 
3607
krb5_encrypt_ivec(krb5_context context,
 
3608
                  krb5_crypto crypto,
 
3609
                  unsigned usage,
 
3610
                  const void *data,
 
3611
                  size_t len,
 
3612
                  krb5_data *result,
 
3613
                  void *ivec)
 
3614
{
 
3615
    if(derived_crypto(context, crypto))
 
3616
        return encrypt_internal_derived(context, crypto, usage,
 
3617
                                        data, len, result, ivec);
 
3618
    else if (special_crypto(context, crypto))
 
3619
        return encrypt_internal_special (context, crypto, usage,
 
3620
                                         data, len, result, ivec);
 
3621
    else
 
3622
        return encrypt_internal(context, crypto, data, len, result, ivec);
 
3623
}
 
3624
 
 
3625
krb5_error_code KRB5_LIB_FUNCTION
 
3626
krb5_encrypt(krb5_context context,
 
3627
             krb5_crypto crypto,
 
3628
             unsigned usage,
 
3629
             const void *data,
 
3630
             size_t len,
 
3631
             krb5_data *result)
 
3632
{
 
3633
    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
 
3634
}
 
3635
 
 
3636
krb5_error_code KRB5_LIB_FUNCTION
 
3637
krb5_encrypt_EncryptedData(krb5_context context,
 
3638
                           krb5_crypto crypto,
 
3639
                           unsigned usage,
 
3640
                           void *data,
 
3641
                           size_t len,
 
3642
                           int kvno,
 
3643
                           EncryptedData *result)
 
3644
{
 
3645
    result->etype = CRYPTO_ETYPE(crypto);
 
3646
    if(kvno){
 
3647
        ALLOC(result->kvno, 1);
 
3648
        *result->kvno = kvno;
 
3649
    }else
 
3650
        result->kvno = NULL;
 
3651
    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
 
3652
}
 
3653
 
 
3654
krb5_error_code KRB5_LIB_FUNCTION
 
3655
krb5_decrypt_ivec(krb5_context context,
 
3656
                  krb5_crypto crypto,
 
3657
                  unsigned usage,
 
3658
                  void *data,
 
3659
                  size_t len,
 
3660
                  krb5_data *result,
 
3661
                  void *ivec)
 
3662
{
 
3663
    if(derived_crypto(context, crypto))
 
3664
        return decrypt_internal_derived(context, crypto, usage,
 
3665
                                        data, len, result, ivec);
 
3666
    else if (special_crypto (context, crypto))
 
3667
        return decrypt_internal_special(context, crypto, usage,
 
3668
                                        data, len, result, ivec);
 
3669
    else
 
3670
        return decrypt_internal(context, crypto, data, len, result, ivec);
 
3671
}
 
3672
 
 
3673
krb5_error_code KRB5_LIB_FUNCTION
 
3674
krb5_decrypt(krb5_context context,
 
3675
             krb5_crypto crypto,
 
3676
             unsigned usage,
 
3677
             void *data,
 
3678
             size_t len,
 
3679
             krb5_data *result)
 
3680
{
 
3681
    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
 
3682
                              NULL);
 
3683
}
 
3684
 
 
3685
krb5_error_code KRB5_LIB_FUNCTION
 
3686
krb5_decrypt_EncryptedData(krb5_context context,
 
3687
                           krb5_crypto crypto,
 
3688
                           unsigned usage,
 
3689
                           const EncryptedData *e,
 
3690
                           krb5_data *result)
 
3691
{
 
3692
    return krb5_decrypt(context, crypto, usage,
 
3693
                        e->cipher.data, e->cipher.length, result);
 
3694
}
 
3695
 
 
3696
/************************************************************
 
3697
 *                                                          *
 
3698
 ************************************************************/
 
3699
 
 
3700
#define ENTROPY_NEEDED 128
 
3701
 
 
3702
static int
 
3703
seed_something(void)
 
3704
{
 
3705
    char buf[1024], seedfile[256];
 
3706
 
 
3707
    /* If there is a seed file, load it. But such a file cannot be trusted,
 
3708
       so use 0 for the entropy estimate */
 
3709
    if (RAND_file_name(seedfile, sizeof(seedfile))) {
 
3710
        int fd;
 
3711
        fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC);
 
3712
        if (fd >= 0) {
 
3713
            ssize_t ret;
 
3714
            rk_cloexec(fd);
 
3715
            ret = read(fd, buf, sizeof(buf));
 
3716
            if (ret > 0)
 
3717
                RAND_add(buf, ret, 0.0);
 
3718
            close(fd);
 
3719
        } else
 
3720
            seedfile[0] = '\0';
 
3721
    } else
 
3722
        seedfile[0] = '\0';
 
3723
 
 
3724
    /* Calling RAND_status() will try to use /dev/urandom if it exists so
 
3725
       we do not have to deal with it. */
 
3726
    if (RAND_status() != 1) {
 
3727
        krb5_context context;
 
3728
        const char *p;
 
3729
 
 
3730
        /* Try using egd */
 
3731
        if (!krb5_init_context(&context)) {
 
3732
            p = krb5_config_get_string(context, NULL, "libdefaults",
 
3733
                                       "egd_socket", NULL);
 
3734
            if (p != NULL)
 
3735
                RAND_egd_bytes(p, ENTROPY_NEEDED);
 
3736
            krb5_free_context(context);
 
3737
        }
 
3738
    }
 
3739
 
 
3740
    if (RAND_status() == 1)     {
 
3741
        /* Update the seed file */
 
3742
        if (seedfile[0])
 
3743
            RAND_write_file(seedfile);
 
3744
 
 
3745
        return 0;
 
3746
    } else
 
3747
        return -1;
 
3748
}
 
3749
 
 
3750
void KRB5_LIB_FUNCTION
 
3751
krb5_generate_random_block(void *buf, size_t len)
 
3752
{
 
3753
    static int rng_initialized = 0;
 
3754
 
 
3755
    HEIMDAL_MUTEX_lock(&crypto_mutex);
 
3756
    if (!rng_initialized) {
 
3757
        if (seed_something())
 
3758
            krb5_abortx(NULL, "Fatal: could not seed the "
 
3759
                        "random number generator");
 
3760
        
 
3761
        rng_initialized = 1;
 
3762
    }
 
3763
    HEIMDAL_MUTEX_unlock(&crypto_mutex);
 
3764
    if (RAND_bytes(buf, len) != 1)
 
3765
        krb5_abortx(NULL, "Failed to generate random block");
 
3766
}
 
3767
 
 
3768
static void
 
3769
DES3_postproc(krb5_context context,
 
3770
              unsigned char *k, size_t len, struct key_data *key)
 
3771
{
 
3772
    DES3_random_to_key(context, key->key, k, len);
 
3773
 
 
3774
    if (key->schedule) {
 
3775
        krb5_free_data(context, key->schedule);
 
3776
        key->schedule = NULL;
 
3777
    }
 
3778
}
 
3779
 
 
3780
static krb5_error_code
 
3781
derive_key(krb5_context context,
 
3782
           struct encryption_type *et,
 
3783
           struct key_data *key,
 
3784
           const void *constant,
 
3785
           size_t len)
 
3786
{
 
3787
    unsigned char *k;
 
3788
    unsigned int nblocks = 0, i;
 
3789
    krb5_error_code ret = 0;
 
3790
    struct key_type *kt = et->keytype;
 
3791
 
 
3792
    ret = _key_schedule(context, key);
 
3793
    if(ret)
 
3794
        return ret;
 
3795
    if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
 
3796
        nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
 
3797
        k = malloc(nblocks * et->blocksize);
 
3798
        if(k == NULL) {
 
3799
            krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3800
            return ENOMEM;
 
3801
        }
 
3802
        ret = _krb5_n_fold(constant, len, k, et->blocksize);
 
3803
        if (ret) {
 
3804
            free(k);
 
3805
            krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
3806
            return ret;
 
3807
        }
 
3808
        for(i = 0; i < nblocks; i++) {
 
3809
            if(i > 0)
 
3810
                memcpy(k + i * et->blocksize,
 
3811
                       k + (i - 1) * et->blocksize,
 
3812
                       et->blocksize);
 
3813
            (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
 
3814
                           1, 0, NULL);
 
3815
        }
 
3816
    } else {
 
3817
        /* this case is probably broken, but won't be run anyway */
 
3818
        void *c = malloc(len);
 
3819
        size_t res_len = (kt->bits + 7) / 8;
 
3820
 
 
3821
        if(len != 0 && c == NULL) {
 
3822
            krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3823
            return ENOMEM;
 
3824
        }
 
3825
        memcpy(c, constant, len);
 
3826
        (*et->encrypt)(context, key, c, len, 1, 0, NULL);
 
3827
        k = malloc(res_len);
 
3828
        if(res_len != 0 && k == NULL) {
 
3829
            free(c);
 
3830
            krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3831
            return ENOMEM;
 
3832
        }
 
3833
        ret = _krb5_n_fold(c, len, k, res_len);
 
3834
        if (ret) {
 
3835
            free(k);
 
3836
            krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
3837
            return ret;
 
3838
        }
 
3839
        free(c);
 
3840
    }
 
3841
 
 
3842
    /* XXX keytype dependent post-processing */
 
3843
    switch(kt->type) {
 
3844
    case KEYTYPE_DES3:
 
3845
        DES3_postproc(context, k, nblocks * et->blocksize, key);
 
3846
        break;
 
3847
    case KEYTYPE_AES128:
 
3848
    case KEYTYPE_AES256:
 
3849
        memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
 
3850
        break;
 
3851
    default:
 
3852
        ret = KRB5_CRYPTO_INTERNAL;
 
3853
        krb5_set_error_message(context, ret,
 
3854
                               N_("derive_key() called with unknown keytype (%u)", ""),
 
3855
                               kt->type);
 
3856
        break;
 
3857
    }
 
3858
    if (key->schedule) {
 
3859
        krb5_free_data(context, key->schedule);
 
3860
        key->schedule = NULL;
 
3861
    }
 
3862
    memset(k, 0, nblocks * et->blocksize);
 
3863
    free(k);
 
3864
    return ret;
 
3865
}
 
3866
 
 
3867
static struct key_data *
 
3868
_new_derived_key(krb5_crypto crypto, unsigned usage)
 
3869
{
 
3870
    struct key_usage *d = crypto->key_usage;
 
3871
    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
 
3872
    if(d == NULL)
 
3873
        return NULL;
 
3874
    crypto->key_usage = d;
 
3875
    d += crypto->num_key_usage++;
 
3876
    memset(d, 0, sizeof(*d));
 
3877
    d->usage = usage;
 
3878
    return &d->key;
 
3879
}
 
3880
 
 
3881
krb5_error_code KRB5_LIB_FUNCTION
 
3882
krb5_derive_key(krb5_context context,
 
3883
                const krb5_keyblock *key,
 
3884
                krb5_enctype etype,
 
3885
                const void *constant,
 
3886
                size_t constant_len,
 
3887
                krb5_keyblock **derived_key)
 
3888
{
 
3889
    krb5_error_code ret;
 
3890
    struct encryption_type *et;
 
3891
    struct key_data d;
 
3892
 
 
3893
    *derived_key = NULL;
 
3894
 
 
3895
    et = _find_enctype (etype);
 
3896
    if (et == NULL) {
 
3897
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
3898
                               N_("encryption type %d not supported", ""),
 
3899
                               etype);
 
3900
        return KRB5_PROG_ETYPE_NOSUPP;
 
3901
    }
 
3902
 
 
3903
    ret = krb5_copy_keyblock(context, key, &d.key);
 
3904
    if (ret)
 
3905
        return ret;
 
3906
 
 
3907
    d.schedule = NULL;
 
3908
    ret = derive_key(context, et, &d, constant, constant_len);
 
3909
    if (ret == 0)
 
3910
        ret = krb5_copy_keyblock(context, d.key, derived_key);
 
3911
    free_key_data(context, &d, et);
 
3912
    return ret;
 
3913
}
 
3914
 
 
3915
static krb5_error_code
 
3916
_get_derived_key(krb5_context context,
 
3917
                 krb5_crypto crypto,
 
3918
                 unsigned usage,
 
3919
                 struct key_data **key)
 
3920
{
 
3921
    int i;
 
3922
    struct key_data *d;
 
3923
    unsigned char constant[5];
 
3924
 
 
3925
    for(i = 0; i < crypto->num_key_usage; i++)
 
3926
        if(crypto->key_usage[i].usage == usage) {
 
3927
            *key = &crypto->key_usage[i].key;
 
3928
            return 0;
 
3929
        }
 
3930
    d = _new_derived_key(crypto, usage);
 
3931
    if(d == NULL) {
 
3932
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3933
        return ENOMEM;
 
3934
    }
 
3935
    krb5_copy_keyblock(context, crypto->key.key, &d->key);
 
3936
    _krb5_put_int(constant, usage, 5);
 
3937
    derive_key(context, crypto->et, d, constant, sizeof(constant));
 
3938
    *key = d;
 
3939
    return 0;
 
3940
}
 
3941
 
 
3942
 
 
3943
krb5_error_code KRB5_LIB_FUNCTION
 
3944
krb5_crypto_init(krb5_context context,
 
3945
                 const krb5_keyblock *key,
 
3946
                 krb5_enctype etype,
 
3947
                 krb5_crypto *crypto)
 
3948
{
 
3949
    krb5_error_code ret;
 
3950
    ALLOC(*crypto, 1);
 
3951
    if(*crypto == NULL) {
 
3952
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
3953
        return ENOMEM;
 
3954
    }
 
3955
    if(etype == ETYPE_NULL)
 
3956
        etype = key->keytype;
 
3957
    (*crypto)->et = _find_enctype(etype);
 
3958
    if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
 
3959
        free(*crypto);
 
3960
        *crypto = NULL;
 
3961
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
3962
                                N_("encryption type %d not supported", ""),
 
3963
                                etype);
 
3964
        return KRB5_PROG_ETYPE_NOSUPP;
 
3965
    }
 
3966
    if((*crypto)->et->keytype->size != key->keyvalue.length) {
 
3967
        free(*crypto);
 
3968
        *crypto = NULL;
 
3969
        krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
 
3970
                                "encryption key has bad length");
 
3971
        return KRB5_BAD_KEYSIZE;
 
3972
    }
 
3973
    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
 
3974
    if(ret) {
 
3975
        free(*crypto);
 
3976
        *crypto = NULL;
 
3977
        return ret;
 
3978
    }
 
3979
    (*crypto)->key.schedule = NULL;
 
3980
    (*crypto)->num_key_usage = 0;
 
3981
    (*crypto)->key_usage = NULL;
 
3982
    return 0;
 
3983
}
 
3984
 
 
3985
static void
 
3986
free_key_data(krb5_context context, struct key_data *key,
 
3987
              struct encryption_type *et)
 
3988
{
 
3989
    krb5_free_keyblock(context, key->key);
 
3990
    if(key->schedule) {
 
3991
        if (et->keytype->cleanup)
 
3992
            (*et->keytype->cleanup)(context, key);
 
3993
        memset(key->schedule->data, 0, key->schedule->length);
 
3994
        krb5_free_data(context, key->schedule);
 
3995
    }
 
3996
}
 
3997
 
 
3998
static void
 
3999
free_key_usage(krb5_context context, struct key_usage *ku,
 
4000
               struct encryption_type *et)
 
4001
{
 
4002
    free_key_data(context, &ku->key, et);
 
4003
}
 
4004
 
 
4005
krb5_error_code KRB5_LIB_FUNCTION
 
4006
krb5_crypto_destroy(krb5_context context,
 
4007
                    krb5_crypto crypto)
 
4008
{
 
4009
    int i;
 
4010
 
 
4011
    for(i = 0; i < crypto->num_key_usage; i++)
 
4012
        free_key_usage(context, &crypto->key_usage[i], crypto->et);
 
4013
    free(crypto->key_usage);
 
4014
    free_key_data(context, &crypto->key, crypto->et);
 
4015
    free (crypto);
 
4016
    return 0;
 
4017
}
 
4018
 
 
4019
krb5_error_code KRB5_LIB_FUNCTION
 
4020
krb5_crypto_getblocksize(krb5_context context,
 
4021
                         krb5_crypto crypto,
 
4022
                         size_t *blocksize)
 
4023
{
 
4024
    *blocksize = crypto->et->blocksize;
 
4025
    return 0;
 
4026
}
 
4027
 
 
4028
krb5_error_code KRB5_LIB_FUNCTION
 
4029
krb5_crypto_getenctype(krb5_context context,
 
4030
                       krb5_crypto crypto,
 
4031
                       krb5_enctype *enctype)
 
4032
{
 
4033
    *enctype = crypto->et->type;
 
4034
    return 0;
 
4035
}
 
4036
 
 
4037
krb5_error_code KRB5_LIB_FUNCTION
 
4038
krb5_crypto_getpadsize(krb5_context context,
 
4039
                       krb5_crypto crypto,
 
4040
                       size_t *padsize)
 
4041
{
 
4042
    *padsize = crypto->et->padsize;
 
4043
    return 0;
 
4044
}
 
4045
 
 
4046
krb5_error_code KRB5_LIB_FUNCTION
 
4047
krb5_crypto_getconfoundersize(krb5_context context,
 
4048
                              krb5_crypto crypto,
 
4049
                              size_t *confoundersize)
 
4050
{
 
4051
    *confoundersize = crypto->et->confoundersize;
 
4052
    return 0;
 
4053
}
 
4054
 
 
4055
 
 
4056
/**
 
4057
 * Disable encryption type
 
4058
 *
 
4059
 * @param context Kerberos 5 context
 
4060
 * @param enctype encryption type to disable
 
4061
 *
 
4062
 * @return Return an error code or 0.
 
4063
 *
 
4064
 * @ingroup krb5_crypto
 
4065
 */
 
4066
 
 
4067
krb5_error_code KRB5_LIB_FUNCTION
 
4068
krb5_enctype_disable(krb5_context context,
 
4069
                     krb5_enctype enctype)
 
4070
{
 
4071
    struct encryption_type *et = _find_enctype(enctype);
 
4072
    if(et == NULL) {
 
4073
        if (context)
 
4074
            krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
4075
                                    N_("encryption type %d not supported", ""),
 
4076
                                    enctype);
 
4077
        return KRB5_PROG_ETYPE_NOSUPP;
 
4078
    }
 
4079
    et->flags |= F_DISABLED;
 
4080
    return 0;
 
4081
}
 
4082
 
 
4083
/**
 
4084
 * Enable encryption type
 
4085
 *
 
4086
 * @param context Kerberos 5 context
 
4087
 * @param enctype encryption type to enable
 
4088
 *
 
4089
 * @return Return an error code or 0.
 
4090
 *
 
4091
 * @ingroup krb5_crypto
 
4092
 */
 
4093
 
 
4094
krb5_error_code KRB5_LIB_FUNCTION
 
4095
krb5_enctype_enable(krb5_context context,
 
4096
                    krb5_enctype enctype)
 
4097
{
 
4098
    struct encryption_type *et = _find_enctype(enctype);
 
4099
    if(et == NULL) {
 
4100
        if (context)
 
4101
            krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
4102
                                    N_("encryption type %d not supported", ""),
 
4103
                                    enctype);
 
4104
        return KRB5_PROG_ETYPE_NOSUPP;
 
4105
    }
 
4106
    et->flags &= ~F_DISABLED;
 
4107
    return 0;
 
4108
}
 
4109
 
 
4110
 
 
4111
krb5_error_code KRB5_LIB_FUNCTION
 
4112
krb5_string_to_key_derived(krb5_context context,
 
4113
                           const void *str,
 
4114
                           size_t len,
 
4115
                           krb5_enctype etype,
 
4116
                           krb5_keyblock *key)
 
4117
{
 
4118
    struct encryption_type *et = _find_enctype(etype);
 
4119
    krb5_error_code ret;
 
4120
    struct key_data kd;
 
4121
    size_t keylen;
 
4122
    u_char *tmp;
 
4123
 
 
4124
    if(et == NULL) {
 
4125
        krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
 
4126
                                N_("encryption type %d not supported", ""),
 
4127
                                etype);
 
4128
        return KRB5_PROG_ETYPE_NOSUPP;
 
4129
    }
 
4130
    keylen = et->keytype->bits / 8;
 
4131
 
 
4132
    ALLOC(kd.key, 1);
 
4133
    if(kd.key == NULL) {
 
4134
        krb5_set_error_message (context, ENOMEM,
 
4135
                                N_("malloc: out of memory", ""));
 
4136
        return ENOMEM;
 
4137
    }
 
4138
    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
 
4139
    if(ret) {
 
4140
        free(kd.key);
 
4141
        return ret;
 
4142
    }
 
4143
    kd.key->keytype = etype;
 
4144
    tmp = malloc (keylen);
 
4145
    if(tmp == NULL) {
 
4146
        krb5_free_keyblock(context, kd.key);
 
4147
        krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 
4148
        return ENOMEM;
 
4149
    }
 
4150
    ret = _krb5_n_fold(str, len, tmp, keylen);
 
4151
    if (ret) {
 
4152
        free(tmp);
 
4153
        krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
 
4154
        return ret;
 
4155
    }
 
4156
    kd.schedule = NULL;
 
4157
    DES3_postproc (context, tmp, keylen, &kd); /* XXX */
 
4158
    memset(tmp, 0, keylen);
 
4159
    free(tmp);
 
4160
    ret = derive_key(context,
 
4161
                     et,
 
4162
                     &kd,
 
4163
                     "kerberos", /* XXX well known constant */
 
4164
                     strlen("kerberos"));
 
4165
    if (ret) {
 
4166
        free_key_data(context, &kd, et);
 
4167
        return ret;
 
4168
    }
 
4169
    ret = krb5_copy_keyblock_contents(context, kd.key, key);
 
4170
    free_key_data(context, &kd, et);
 
4171
    return ret;
 
4172
}
 
4173
 
 
4174
static size_t
 
4175
wrapped_length (krb5_context context,
 
4176
                krb5_crypto  crypto,
 
4177
                size_t       data_len)
 
4178
{
 
4179
    struct encryption_type *et = crypto->et;
 
4180
    size_t padsize = et->padsize;
 
4181
    size_t checksumsize = CHECKSUMSIZE(et->checksum);
 
4182
    size_t res;
 
4183
 
 
4184
    res =  et->confoundersize + checksumsize + data_len;
 
4185
    res =  (res + padsize - 1) / padsize * padsize;
 
4186
    return res;
 
4187
}
 
4188
 
 
4189
static size_t
 
4190
wrapped_length_dervied (krb5_context context,
 
4191
                        krb5_crypto  crypto,
 
4192
                        size_t       data_len)
 
4193
{
 
4194
    struct encryption_type *et = crypto->et;
 
4195
    size_t padsize = et->padsize;
 
4196
    size_t res;
 
4197
 
 
4198
    res =  et->confoundersize + data_len;
 
4199
    res =  (res + padsize - 1) / padsize * padsize;
 
4200
    if (et->keyed_checksum)
 
4201
        res += et->keyed_checksum->checksumsize;
 
4202
    else
 
4203
        res += et->checksum->checksumsize;
 
4204
    return res;
 
4205
}
 
4206
 
 
4207
/*
 
4208
 * Return the size of an encrypted packet of length `data_len'
 
4209
 */
 
4210
 
 
4211
size_t
 
4212
krb5_get_wrapped_length (krb5_context context,
 
4213
                         krb5_crypto  crypto,
 
4214
                         size_t       data_len)
 
4215
{
 
4216
    if (derived_crypto (context, crypto))
 
4217
        return wrapped_length_dervied (context, crypto, data_len);
 
4218
    else
 
4219
        return wrapped_length (context, crypto, data_len);
 
4220
}
 
4221
 
 
4222
/*
 
4223
 * Return the size of an encrypted packet of length `data_len'
 
4224
 */
 
4225
 
 
4226
static size_t
 
4227
crypto_overhead (krb5_context context,
 
4228
                 krb5_crypto  crypto)
 
4229
{
 
4230
    struct encryption_type *et = crypto->et;
 
4231
    size_t res;
 
4232
 
 
4233
    res = CHECKSUMSIZE(et->checksum);
 
4234
    res += et->confoundersize;
 
4235
    if (et->padsize > 1)
 
4236
        res += et->padsize;
 
4237
    return res;
 
4238
}
 
4239
 
 
4240
static size_t
 
4241
crypto_overhead_dervied (krb5_context context,
 
4242
                         krb5_crypto  crypto)
 
4243
{
 
4244
    struct encryption_type *et = crypto->et;
 
4245
    size_t res;
 
4246
 
 
4247
    if (et->keyed_checksum)
 
4248
        res = CHECKSUMSIZE(et->keyed_checksum);
 
4249
    else
 
4250
        res = CHECKSUMSIZE(et->checksum);
 
4251
    res += et->confoundersize;
 
4252
    if (et->padsize > 1)
 
4253
        res += et->padsize;
 
4254
    return res;
 
4255
}
 
4256
 
 
4257
size_t
 
4258
krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
 
4259
{
 
4260
    if (derived_crypto (context, crypto))
 
4261
        return crypto_overhead_dervied (context, crypto);
 
4262
    else
 
4263
        return crypto_overhead (context, crypto);
 
4264
}
 
4265
 
 
4266
krb5_error_code KRB5_LIB_FUNCTION
 
4267
krb5_random_to_key(krb5_context context,
 
4268
                   krb5_enctype type,
 
4269
                   const void *data,
 
4270
                   size_t size,
 
4271
                   krb5_keyblock *key)
 
4272
{
 
4273
    krb5_error_code ret;
 
4274
    struct encryption_type *et = _find_enctype(type);
 
4275
    if(et == NULL) {
 
4276
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4277
                               N_("encryption type %d not supported", ""),
 
4278
                               type);
 
4279
        return KRB5_PROG_ETYPE_NOSUPP;
 
4280
    }
 
4281
    if ((et->keytype->bits + 7) / 8 > size) {
 
4282
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4283
                               N_("encryption key %s needs %d bytes "
 
4284
                                  "of random to make an encryption key "
 
4285
                                  "out of it", ""),
 
4286
                               et->name, (int)et->keytype->size);
 
4287
        return KRB5_PROG_ETYPE_NOSUPP;
 
4288
    }
 
4289
    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
 
4290
    if(ret)
 
4291
        return ret;
 
4292
    key->keytype = type;
 
4293
    if (et->keytype->random_to_key)
 
4294
        (*et->keytype->random_to_key)(context, key, data, size);
 
4295
    else
 
4296
        memcpy(key->keyvalue.data, data, et->keytype->size);
 
4297
 
 
4298
    return 0;
 
4299
}
 
4300
 
 
4301
krb5_error_code
 
4302
_krb5_pk_octetstring2key(krb5_context context,
 
4303
                         krb5_enctype type,
 
4304
                         const void *dhdata,
 
4305
                         size_t dhsize,
 
4306
                         const heim_octet_string *c_n,
 
4307
                         const heim_octet_string *k_n,
 
4308
                         krb5_keyblock *key)
 
4309
{
 
4310
    struct encryption_type *et = _find_enctype(type);
 
4311
    krb5_error_code ret;
 
4312
    size_t keylen, offset;
 
4313
    void *keydata;
 
4314
    unsigned char counter;
 
4315
    unsigned char shaoutput[20];
 
4316
 
 
4317
    if(et == NULL) {
 
4318
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4319
                               N_("encryption type %d not supported", ""),
 
4320
                               type);
 
4321
        return KRB5_PROG_ETYPE_NOSUPP;
 
4322
    }
 
4323
    keylen = (et->keytype->bits + 7) / 8;
 
4324
 
 
4325
    keydata = malloc(keylen);
 
4326
    if (keydata == NULL) {
 
4327
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
4328
        return ENOMEM;
 
4329
    }
 
4330
 
 
4331
    counter = 0;
 
4332
    offset = 0;
 
4333
    do {
 
4334
        SHA_CTX m;
 
4335
        
 
4336
        SHA1_Init(&m);
 
4337
        SHA1_Update(&m, &counter, 1);
 
4338
        SHA1_Update(&m, dhdata, dhsize);
 
4339
        if (c_n)
 
4340
            SHA1_Update(&m, c_n->data, c_n->length);
 
4341
        if (k_n)
 
4342
            SHA1_Update(&m, k_n->data, k_n->length);
 
4343
        SHA1_Final(shaoutput, &m);
 
4344
 
 
4345
        memcpy((unsigned char *)keydata + offset,
 
4346
               shaoutput,
 
4347
               min(keylen - offset, sizeof(shaoutput)));
 
4348
 
 
4349
        offset += sizeof(shaoutput);
 
4350
        counter++;
 
4351
    } while(offset < keylen);
 
4352
    memset(shaoutput, 0, sizeof(shaoutput));
 
4353
 
 
4354
    ret = krb5_random_to_key(context, type, keydata, keylen, key);
 
4355
    memset(keydata, 0, sizeof(keylen));
 
4356
    free(keydata);
 
4357
    return ret;
 
4358
}
 
4359
 
 
4360
static krb5_error_code
 
4361
encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)
 
4362
{
 
4363
    KRB5PrincipalName pn;
 
4364
    krb5_error_code ret;
 
4365
    size_t size;
 
4366
 
 
4367
    pn.principalName = p->name;
 
4368
    pn.realm = p->realm;
 
4369
 
 
4370
    ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,
 
4371
                       &pn, &size, ret);
 
4372
    if (ret) {
 
4373
        krb5_data_zero(data);
 
4374
        krb5_set_error_message(context, ret,
 
4375
                               N_("Failed to encode KRB5PrincipalName", ""));
 
4376
        return ret;
 
4377
    }
 
4378
    if (data->length != size)
 
4379
        krb5_abortx(context, "asn1 compiler internal error");
 
4380
    return 0;
 
4381
}
 
4382
 
 
4383
static krb5_error_code
 
4384
encode_otherinfo(krb5_context context,
 
4385
                 const AlgorithmIdentifier *ai,
 
4386
                 krb5_const_principal client,
 
4387
                 krb5_const_principal server,
 
4388
                 krb5_enctype enctype,
 
4389
                 const krb5_data *as_req,
 
4390
                 const krb5_data *pk_as_rep,
 
4391
                 const Ticket *ticket,
 
4392
                 krb5_data *other)
 
4393
{
 
4394
    PkinitSP80056AOtherInfo otherinfo;
 
4395
    PkinitSuppPubInfo pubinfo;
 
4396
    krb5_error_code ret;
 
4397
    krb5_data pub;
 
4398
    size_t size;
 
4399
 
 
4400
    krb5_data_zero(other);
 
4401
    memset(&otherinfo, 0, sizeof(otherinfo));
 
4402
    memset(&pubinfo, 0, sizeof(pubinfo));
 
4403
 
 
4404
    pubinfo.enctype = enctype;
 
4405
    pubinfo.as_REQ = *as_req;
 
4406
    pubinfo.pk_as_rep = *pk_as_rep;
 
4407
    pubinfo.ticket = *ticket;
 
4408
    ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,
 
4409
                       &pubinfo, &size, ret);
 
4410
    if (ret) {
 
4411
        krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
4412
        return ret;
 
4413
    }
 
4414
    if (pub.length != size)
 
4415
        krb5_abortx(context, "asn1 compiler internal error");
 
4416
 
 
4417
    ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);
 
4418
    if (ret) {
 
4419
        free(pub.data);
 
4420
        return ret;
 
4421
    }
 
4422
    ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);
 
4423
    if (ret) {
 
4424
        free(otherinfo.partyUInfo.data);
 
4425
        free(pub.data);
 
4426
        return ret;
 
4427
    }
 
4428
 
 
4429
    otherinfo.algorithmID = *ai;
 
4430
    otherinfo.suppPubInfo = &pub;
 
4431
 
 
4432
    ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,
 
4433
                       &otherinfo, &size, ret);
 
4434
    free(otherinfo.partyUInfo.data);
 
4435
    free(otherinfo.partyVInfo.data);
 
4436
    free(pub.data);
 
4437
    if (ret) {
 
4438
        krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
 
4439
        return ret;
 
4440
    }
 
4441
    if (other->length != size)
 
4442
        krb5_abortx(context, "asn1 compiler internal error");
 
4443
 
 
4444
    return 0;
 
4445
}
 
4446
 
 
4447
krb5_error_code
 
4448
_krb5_pk_kdf(krb5_context context,
 
4449
             const struct AlgorithmIdentifier *ai,
 
4450
             const void *dhdata,
 
4451
             size_t dhsize,
 
4452
             krb5_const_principal client,
 
4453
             krb5_const_principal server,
 
4454
             krb5_enctype enctype,
 
4455
             const krb5_data *as_req,
 
4456
             const krb5_data *pk_as_rep,
 
4457
             const Ticket *ticket,
 
4458
             krb5_keyblock *key)
 
4459
{
 
4460
    struct encryption_type *et;
 
4461
    krb5_error_code ret;
 
4462
    krb5_data other;
 
4463
    size_t keylen, offset;
 
4464
    uint32_t counter;
 
4465
    unsigned char *keydata;
 
4466
    unsigned char shaoutput[20];
 
4467
 
 
4468
    if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
 
4469
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4470
                               N_("KDF not supported", ""));
 
4471
        return KRB5_PROG_ETYPE_NOSUPP;
 
4472
    }
 
4473
    if (ai->parameters != NULL &&
 
4474
        (ai->parameters->length != 2 ||
 
4475
         memcmp(ai->parameters->data, "\x05\x00", 2) != 0))
 
4476
        {
 
4477
            krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4478
                                   N_("kdf params not NULL or the NULL-type",
 
4479
                                      ""));
 
4480
            return KRB5_PROG_ETYPE_NOSUPP;
 
4481
        }
 
4482
 
 
4483
    et = _find_enctype(enctype);
 
4484
    if(et == NULL) {
 
4485
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4486
                               N_("encryption type %d not supported", ""),
 
4487
                               enctype);
 
4488
        return KRB5_PROG_ETYPE_NOSUPP;
 
4489
    }
 
4490
    keylen = (et->keytype->bits + 7) / 8;
 
4491
 
 
4492
    keydata = malloc(keylen);
 
4493
    if (keydata == NULL) {
 
4494
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
4495
        return ENOMEM;
 
4496
    }
 
4497
 
 
4498
    ret = encode_otherinfo(context, ai, client, server,
 
4499
                           enctype, as_req, pk_as_rep, ticket, &other);
 
4500
    if (ret) {
 
4501
        free(keydata);
 
4502
        return ret;
 
4503
    }
 
4504
 
 
4505
    offset = 0;
 
4506
    counter = 1;
 
4507
    do {
 
4508
        unsigned char cdata[4];
 
4509
        SHA_CTX m;
 
4510
        
 
4511
        SHA1_Init(&m);
 
4512
        _krb5_put_int(cdata, counter, 4);
 
4513
        SHA1_Update(&m, cdata, 4);
 
4514
        SHA1_Update(&m, dhdata, dhsize);
 
4515
        SHA1_Update(&m, other.data, other.length);
 
4516
        SHA1_Final(shaoutput, &m);
 
4517
 
 
4518
        memcpy((unsigned char *)keydata + offset,
 
4519
               shaoutput,
 
4520
               min(keylen - offset, sizeof(shaoutput)));
 
4521
 
 
4522
        offset += sizeof(shaoutput);
 
4523
        counter++;
 
4524
    } while(offset < keylen);
 
4525
    memset(shaoutput, 0, sizeof(shaoutput));
 
4526
 
 
4527
    free(other.data);
 
4528
 
 
4529
    ret = krb5_random_to_key(context, enctype, keydata, keylen, key);
 
4530
    memset(keydata, 0, sizeof(keylen));
 
4531
    free(keydata);
 
4532
 
 
4533
    return ret;
 
4534
}
 
4535
 
 
4536
 
 
4537
krb5_error_code KRB5_LIB_FUNCTION
 
4538
krb5_crypto_prf_length(krb5_context context,
 
4539
                       krb5_enctype type,
 
4540
                       size_t *length)
 
4541
{
 
4542
    struct encryption_type *et = _find_enctype(type);
 
4543
 
 
4544
    if(et == NULL || et->prf_length == 0) {
 
4545
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4546
                               N_("encryption type %d not supported", ""),
 
4547
                               type);
 
4548
        return KRB5_PROG_ETYPE_NOSUPP;
 
4549
    }
 
4550
 
 
4551
    *length = et->prf_length;
 
4552
    return 0;
 
4553
}
 
4554
 
 
4555
krb5_error_code KRB5_LIB_FUNCTION
 
4556
krb5_crypto_prf(krb5_context context,
 
4557
                const krb5_crypto crypto,
 
4558
                const krb5_data *input,
 
4559
                krb5_data *output)
 
4560
{
 
4561
    struct encryption_type *et = crypto->et;
 
4562
 
 
4563
    krb5_data_zero(output);
 
4564
 
 
4565
    if(et->prf == NULL) {
 
4566
        krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
 
4567
                               "kerberos prf for %s not supported",
 
4568
                               et->name);
 
4569
        return KRB5_PROG_ETYPE_NOSUPP;
 
4570
    }
 
4571
 
 
4572
    return (*et->prf)(context, crypto, input, output);
 
4573
}
 
4574
 
 
4575
#ifndef HEIMDAL_SMALLER
 
4576
 
 
4577
static struct key_type *keytypes[] = {
 
4578
    &keytype_null,
 
4579
    &keytype_des,
 
4580
    &keytype_des3_derived,
 
4581
#ifdef DES3_OLD_ENCTYPE
 
4582
    &keytype_des3,
 
4583
#endif
 
4584
    &keytype_aes128,
 
4585
    &keytype_aes256,
 
4586
    &keytype_arcfour
 
4587
};
 
4588
 
 
4589
static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
 
4590
 
 
4591
 
 
4592
static struct key_type *
 
4593
_find_keytype(krb5_keytype type)
 
4594
{
 
4595
    int i;
 
4596
    for(i = 0; i < num_keytypes; i++)
 
4597
        if(keytypes[i]->type == type)
 
4598
            return keytypes[i];
 
4599
    return NULL;
 
4600
}
 
4601
 
 
4602
/*
 
4603
 * First take the configured list of etypes for `keytype' if available,
 
4604
 * else, do `krb5_keytype_to_enctypes'.
 
4605
 */
 
4606
 
 
4607
krb5_error_code KRB5_LIB_FUNCTION
 
4608
krb5_keytype_to_enctypes_default (krb5_context context,
 
4609
                                  krb5_keytype keytype,
 
4610
                                  unsigned *len,
 
4611
                                  krb5_enctype **val)
 
4612
    __attribute__((deprecated))
 
4613
{
 
4614
    unsigned int i, n;
 
4615
    krb5_enctype *ret;
 
4616
 
 
4617
    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
 
4618
        return krb5_keytype_to_enctypes (context, keytype, len, val);
 
4619
 
 
4620
    for (n = 0; context->etypes_des[n]; ++n)
 
4621
        ;
 
4622
    ret = malloc (n * sizeof(*ret));
 
4623
    if (ret == NULL && n != 0) {
 
4624
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
4625
        return ENOMEM;
 
4626
    }
 
4627
    for (i = 0; i < n; ++i)
 
4628
        ret[i] = context->etypes_des[i];
 
4629
    *len = n;
 
4630
    *val = ret;
 
4631
    return 0;
 
4632
}
 
4633
 
 
4634
krb5_error_code KRB5_LIB_FUNCTION
 
4635
krb5_keytype_to_string(krb5_context context,
 
4636
                       krb5_keytype keytype,
 
4637
                       char **string)
 
4638
    __attribute__((deprecated))
 
4639
{
 
4640
    struct key_type *kt = _find_keytype(keytype);
 
4641
    if(kt == NULL) {
 
4642
        krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
 
4643
                               "key type %d not supported", keytype);
 
4644
        return KRB5_PROG_KEYTYPE_NOSUPP;
 
4645
    }
 
4646
    *string = strdup(kt->name);
 
4647
    if(*string == NULL) {
 
4648
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
4649
        return ENOMEM;
 
4650
    }
 
4651
    return 0;
 
4652
}
 
4653
 
 
4654
 
 
4655
krb5_error_code KRB5_LIB_FUNCTION
 
4656
krb5_string_to_keytype(krb5_context context,
 
4657
                       const char *string,
 
4658
                       krb5_keytype *keytype)
 
4659
    __attribute__((deprecated))
 
4660
{
 
4661
    char *end;
 
4662
    int i;
 
4663
 
 
4664
    for(i = 0; i < num_keytypes; i++)
 
4665
        if(strcasecmp(keytypes[i]->name, string) == 0){
 
4666
            *keytype = keytypes[i]->type;
 
4667
            return 0;
 
4668
        }
 
4669
 
 
4670
    /* check if the enctype is a number */
 
4671
    *keytype = strtol(string, &end, 0);
 
4672
    if(*end == '\0' && *keytype != 0) {
 
4673
        if (krb5_enctype_valid(context, *keytype) == 0)
 
4674
            return 0;
 
4675
    }
 
4676
 
 
4677
    krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
 
4678
                           "key type %s not supported", string);
 
4679
    return KRB5_PROG_KEYTYPE_NOSUPP;
 
4680
}
 
4681
 
 
4682
krb5_error_code KRB5_LIB_FUNCTION
 
4683
krb5_keytype_to_enctypes (krb5_context context,
 
4684
                          krb5_keytype keytype,
 
4685
                          unsigned *len,
 
4686
                          krb5_enctype **val)
 
4687
{
 
4688
    int i;
 
4689
    unsigned n = 0;
 
4690
    krb5_enctype *ret;
 
4691
 
 
4692
    for (i = num_etypes - 1; i >= 0; --i) {
 
4693
        if (etypes[i]->keytype->type == keytype
 
4694
            && !(etypes[i]->flags & F_PSEUDO))
 
4695
            ++n;
 
4696
    }
 
4697
    ret = malloc(n * sizeof(*ret));
 
4698
    if (ret == NULL && n != 0) {
 
4699
        krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
 
4700
        return ENOMEM;
 
4701
    }
 
4702
    n = 0;
 
4703
    for (i = num_etypes - 1; i >= 0; --i) {
 
4704
        if (etypes[i]->keytype->type == keytype
 
4705
            && !(etypes[i]->flags & F_PSEUDO))
 
4706
            ret[n++] = etypes[i]->type;
 
4707
    }
 
4708
    *len = n;
 
4709
    *val = ret;
 
4710
    return 0;
 
4711
}
 
4712
 
 
4713
#endif /* HEIMDAL_SMALLER */