heimdal Don't dereference NULL in error verify_checksum error path
[samba.git] / source4 / heimdal / lib / krb5 / crypto.c
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 #define KRB5_DEPRECATED
35
36 #include "krb5_locl.h"
37 #include <pkinit_asn1.h>
38
39 #ifndef HEIMDAL_SMALLER
40 #define DES3_OLD_ENCTYPE 1
41 #endif
42
43 struct key_data {
44     krb5_keyblock *key;
45     krb5_data *schedule;
46 };
47
48 struct key_usage {
49     unsigned usage;
50     struct key_data key;
51 };
52
53 struct krb5_crypto_data {
54     struct encryption_type *et;
55     struct key_data key;
56     int num_key_usage;
57     struct key_usage *key_usage;
58 };
59
60 #define CRYPTO_ETYPE(C) ((C)->et->type)
61
62 /* bits for `flags' below */
63 #define F_KEYED          1      /* checksum is keyed */
64 #define F_CPROOF         2      /* checksum is collision proof */
65 #define F_DERIVED        4      /* uses derived keys */
66 #define F_VARIANT        8      /* uses `variant' keys (6.4.3) */
67 #define F_PSEUDO        16      /* not a real protocol type */
68 #define F_SPECIAL       32      /* backwards */
69 #define F_DISABLED      64      /* enctype/checksum disabled */
70 #define F_WEAK         128      /* enctype is considered weak */
71
72 struct salt_type {
73     krb5_salttype type;
74     const char *name;
75     krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
76                                      krb5_salt, krb5_data, krb5_keyblock*);
77 };
78
79 struct key_type {
80     krb5_keytype type; /* XXX */
81     const char *name;
82     size_t bits;
83     size_t size;
84     size_t schedule_size;
85     void (*random_key)(krb5_context, krb5_keyblock*);
86     void (*schedule)(krb5_context, struct key_type *, struct key_data *);
87     struct salt_type *string_to_key;
88     void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
89     void (*cleanup)(krb5_context, struct key_data *);
90     const EVP_CIPHER *(*evp)(void);
91 };
92
93 struct checksum_type {
94     krb5_cksumtype type;
95     const char *name;
96     size_t blocksize;
97     size_t checksumsize;
98     unsigned flags;
99     krb5_error_code (*checksum)(krb5_context context,
100                                 struct key_data *key,
101                                 const void *buf, size_t len,
102                                 unsigned usage,
103                                 Checksum *csum);
104     krb5_error_code (*verify)(krb5_context context,
105                               struct key_data *key,
106                               const void *buf, size_t len,
107                               unsigned usage,
108                               Checksum *csum);
109 };
110
111 struct encryption_type {
112     krb5_enctype type;
113     const char *name;
114     size_t blocksize;
115     size_t padsize;
116     size_t confoundersize;
117     struct key_type *keytype;
118     struct checksum_type *checksum;
119     struct checksum_type *keyed_checksum;
120     unsigned flags;
121     krb5_error_code (*encrypt)(krb5_context context,
122                                struct key_data *key,
123                                void *data, size_t len,
124                                krb5_boolean encryptp,
125                                int usage,
126                                void *ivec);
127     size_t prf_length;
128     krb5_error_code (*prf)(krb5_context,
129                            krb5_crypto, const krb5_data *, krb5_data *);
130 };
131
132 #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
133 #define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
134 #define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
135
136 static struct checksum_type *_find_checksum(krb5_cksumtype type);
137 static struct encryption_type *_find_enctype(krb5_enctype type);
138 static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
139                                         unsigned, struct key_data**);
140 static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
141 static krb5_error_code derive_key(krb5_context context,
142                                   struct encryption_type *et,
143                                   struct key_data *key,
144                                   const void *constant,
145                                   size_t len);
146 static krb5_error_code hmac(krb5_context context,
147                             struct checksum_type *cm,
148                             const void *data,
149                             size_t len,
150                             unsigned usage,
151                             struct key_data *keyblock,
152                             Checksum *result);
153 static void free_key_data(krb5_context,
154                           struct key_data *,
155                           struct encryption_type *);
156 static void free_key_schedule(krb5_context,
157                               struct key_data *,
158                               struct encryption_type *);
159 static krb5_error_code usage2arcfour (krb5_context, unsigned *);
160 static void xor (DES_cblock *, const unsigned char *);
161
162 /************************************************************
163  *                                                          *
164  ************************************************************/
165
166 struct evp_schedule {
167     EVP_CIPHER_CTX ectx;
168     EVP_CIPHER_CTX dctx;
169 };
170
171
172 static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
173
174 #ifdef HEIM_WEAK_CRYPTO
175 static void
176 krb5_DES_random_key(krb5_context context,
177                     krb5_keyblock *key)
178 {
179     DES_cblock *k = key->keyvalue.data;
180     do {
181         krb5_generate_random_block(k, sizeof(DES_cblock));
182         DES_set_odd_parity(k);
183     } while(DES_is_weak_key(k));
184 }
185
186 static void
187 krb5_DES_schedule_old(krb5_context context,
188                       struct key_type *kt,
189                       struct key_data *key)
190 {
191     DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data);
192 }
193
194 #ifdef ENABLE_AFS_STRING_TO_KEY
195
196 /* This defines the Andrew string_to_key function.  It accepts a password
197  * string as input and converts it via a one-way encryption algorithm to a DES
198  * encryption key.  It is compatible with the original Andrew authentication
199  * service password database.
200  */
201
202 /*
203  * Short passwords, i.e 8 characters or less.
204  */
205 static void
206 krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
207                                  krb5_data cell,
208                                  DES_cblock *key)
209 {
210     char  password[8+1];        /* crypt is limited to 8 chars anyway */
211     int   i;
212
213     for(i = 0; i < 8; i++) {
214         char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
215             ((i < cell.length) ?
216              tolower(((unsigned char*)cell.data)[i]) : 0);
217         password[i] = c ? c : 'X';
218     }
219     password[8] = '\0';
220
221     memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
222
223     /* parity is inserted into the LSB so left shift each byte up one
224        bit. This allows ascii characters with a zero MSB to retain as
225        much significance as possible. */
226     for (i = 0; i < sizeof(DES_cblock); i++)
227         ((unsigned char*)key)[i] <<= 1;
228     DES_set_odd_parity (key);
229 }
230
231 /*
232  * Long passwords, i.e 9 characters or more.
233  */
234 static void
235 krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
236                                       krb5_data cell,
237                                       DES_cblock *key)
238 {
239     DES_key_schedule schedule;
240     DES_cblock temp_key;
241     DES_cblock ivec;
242     char password[512];
243     size_t passlen;
244
245     memcpy(password, pw.data, min(pw.length, sizeof(password)));
246     if(pw.length < sizeof(password)) {
247         int len = min(cell.length, sizeof(password) - pw.length);
248         int i;
249
250         memcpy(password + pw.length, cell.data, len);
251         for (i = pw.length; i < pw.length + len; ++i)
252             password[i] = tolower((unsigned char)password[i]);
253     }
254     passlen = min(sizeof(password), pw.length + cell.length);
255     memcpy(&ivec, "kerberos", 8);
256     memcpy(&temp_key, "kerberos", 8);
257     DES_set_odd_parity (&temp_key);
258     DES_set_key_unchecked (&temp_key, &schedule);
259     DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
260
261     memcpy(&temp_key, &ivec, 8);
262     DES_set_odd_parity (&temp_key);
263     DES_set_key_unchecked (&temp_key, &schedule);
264     DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
265     memset(&schedule, 0, sizeof(schedule));
266     memset(&temp_key, 0, sizeof(temp_key));
267     memset(&ivec, 0, sizeof(ivec));
268     memset(password, 0, sizeof(password));
269
270     DES_set_odd_parity (key);
271 }
272
273 static krb5_error_code
274 DES_AFS3_string_to_key(krb5_context context,
275                        krb5_enctype enctype,
276                        krb5_data password,
277                        krb5_salt salt,
278                        krb5_data opaque,
279                        krb5_keyblock *key)
280 {
281     DES_cblock tmp;
282     if(password.length > 8)
283         krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
284     else
285         krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
286     key->keytype = enctype;
287     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
288     memset(&key, 0, sizeof(key));
289     return 0;
290 }
291 #endif /* ENABLE_AFS_STRING_TO_KEY */
292
293 static void
294 DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
295 {
296     DES_key_schedule schedule;
297     int i;
298     int reverse = 0;
299     unsigned char *p;
300
301     unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
302                              0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
303     memset(key, 0, 8);
304
305     p = (unsigned char*)key;
306     for (i = 0; i < length; i++) {
307         unsigned char tmp = data[i];
308         if (!reverse)
309             *p++ ^= (tmp << 1);
310         else
311             *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
312         if((i % 8) == 7)
313             reverse = !reverse;
314     }
315     DES_set_odd_parity(key);
316     if(DES_is_weak_key(key))
317         (*key)[7] ^= 0xF0;
318     DES_set_key_unchecked(key, &schedule);
319     DES_cbc_cksum((void*)data, key, length, &schedule, key);
320     memset(&schedule, 0, sizeof(schedule));
321     DES_set_odd_parity(key);
322     if(DES_is_weak_key(key))
323         (*key)[7] ^= 0xF0;
324 }
325
326 static krb5_error_code
327 krb5_DES_string_to_key(krb5_context context,
328                        krb5_enctype enctype,
329                        krb5_data password,
330                        krb5_salt salt,
331                        krb5_data opaque,
332                        krb5_keyblock *key)
333 {
334     unsigned char *s;
335     size_t len;
336     DES_cblock tmp;
337
338 #ifdef ENABLE_AFS_STRING_TO_KEY
339     if (opaque.length == 1) {
340         unsigned long v;
341         _krb5_get_int(opaque.data, &v, 1);
342         if (v == 1)
343             return DES_AFS3_string_to_key(context, enctype, password,
344                                           salt, opaque, key);
345     }
346 #endif
347
348     len = password.length + salt.saltvalue.length;
349     s = malloc(len);
350     if(len > 0 && s == NULL) {
351         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
352         return ENOMEM;
353     }
354     memcpy(s, password.data, password.length);
355     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
356     DES_string_to_key_int(s, len, &tmp);
357     key->keytype = enctype;
358     krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
359     memset(&tmp, 0, sizeof(tmp));
360     memset(s, 0, len);
361     free(s);
362     return 0;
363 }
364
365 static void
366 krb5_DES_random_to_key(krb5_context context,
367                        krb5_keyblock *key,
368                        const void *data,
369                        size_t size)
370 {
371     DES_cblock *k = key->keyvalue.data;
372     memcpy(k, data, key->keyvalue.length);
373     DES_set_odd_parity(k);
374     if(DES_is_weak_key(k))
375         xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
376 }
377 #endif
378
379 /*
380  *
381  */
382
383 static void
384 DES3_random_key(krb5_context context,
385                 krb5_keyblock *key)
386 {
387     DES_cblock *k = key->keyvalue.data;
388     do {
389         krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
390         DES_set_odd_parity(&k[0]);
391         DES_set_odd_parity(&k[1]);
392         DES_set_odd_parity(&k[2]);
393     } while(DES_is_weak_key(&k[0]) ||
394             DES_is_weak_key(&k[1]) ||
395             DES_is_weak_key(&k[2]));
396 }
397
398 /*
399  * A = A xor B. A & B are 8 bytes.
400  */
401
402 static void
403 xor (DES_cblock *key, const unsigned char *b)
404 {
405     unsigned char *a = (unsigned char*)key;
406     a[0] ^= b[0];
407     a[1] ^= b[1];
408     a[2] ^= b[2];
409     a[3] ^= b[3];
410     a[4] ^= b[4];
411     a[5] ^= b[5];
412     a[6] ^= b[6];
413     a[7] ^= b[7];
414 }
415
416 #ifdef DES3_OLD_ENCTYPE
417 static krb5_error_code
418 DES3_string_to_key(krb5_context context,
419                    krb5_enctype enctype,
420                    krb5_data password,
421                    krb5_salt salt,
422                    krb5_data opaque,
423                    krb5_keyblock *key)
424 {
425     char *str;
426     size_t len;
427     unsigned char tmp[24];
428     DES_cblock keys[3];
429     krb5_error_code ret;
430
431     len = password.length + salt.saltvalue.length;
432     str = malloc(len);
433     if(len != 0 && str == NULL) {
434         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
435         return ENOMEM;
436     }
437     memcpy(str, password.data, password.length);
438     memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
439     {
440         DES_cblock ivec;
441         DES_key_schedule s[3];
442         int i;
443         
444         ret = _krb5_n_fold(str, len, tmp, 24);
445         if (ret) {
446             memset(str, 0, len);
447             free(str);
448             krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
449             return ret;
450         }
451         
452         for(i = 0; i < 3; i++){
453             memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
454             DES_set_odd_parity(keys + i);
455             if(DES_is_weak_key(keys + i))
456                 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
457             DES_set_key_unchecked(keys + i, &s[i]);
458         }
459         memset(&ivec, 0, sizeof(ivec));
460         DES_ede3_cbc_encrypt(tmp,
461                              tmp, sizeof(tmp),
462                              &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
463         memset(s, 0, sizeof(s));
464         memset(&ivec, 0, sizeof(ivec));
465         for(i = 0; i < 3; i++){
466             memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
467             DES_set_odd_parity(keys + i);
468             if(DES_is_weak_key(keys + i))
469                 xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
470         }
471         memset(tmp, 0, sizeof(tmp));
472     }
473     key->keytype = enctype;
474     krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
475     memset(keys, 0, sizeof(keys));
476     memset(str, 0, len);
477     free(str);
478     return 0;
479 }
480 #endif
481
482 static krb5_error_code
483 DES3_string_to_key_derived(krb5_context context,
484                            krb5_enctype enctype,
485                            krb5_data password,
486                            krb5_salt salt,
487                            krb5_data opaque,
488                            krb5_keyblock *key)
489 {
490     krb5_error_code ret;
491     size_t len = password.length + salt.saltvalue.length;
492     char *s;
493
494     s = malloc(len);
495     if(len != 0 && s == NULL) {
496         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
497         return ENOMEM;
498     }
499     memcpy(s, password.data, password.length);
500     memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
501     ret = krb5_string_to_key_derived(context,
502                                      s,
503                                      len,
504                                      enctype,
505                                      key);
506     memset(s, 0, len);
507     free(s);
508     return ret;
509 }
510
511 static void
512 DES3_random_to_key(krb5_context context,
513                    krb5_keyblock *key,
514                    const void *data,
515                    size_t size)
516 {
517     unsigned char *x = key->keyvalue.data;
518     const u_char *q = data;
519     DES_cblock *k;
520     int i, j;
521
522     memset(x, 0, sizeof(x));
523     for (i = 0; i < 3; ++i) {
524         unsigned char foo;
525         for (j = 0; j < 7; ++j) {
526             unsigned char b = q[7 * i + j];
527
528             x[8 * i + j] = b;
529         }
530         foo = 0;
531         for (j = 6; j >= 0; --j) {
532             foo |= q[7 * i + j] & 1;
533             foo <<= 1;
534         }
535         x[8 * i + 7] = foo;
536     }
537     k = key->keyvalue.data;
538     for (i = 0; i < 3; i++) {
539         DES_set_odd_parity(&k[i]);
540         if(DES_is_weak_key(&k[i]))
541             xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
542     }
543 }
544
545 /*
546  * ARCFOUR
547  */
548
549 static krb5_error_code
550 ARCFOUR_string_to_key(krb5_context context,
551                       krb5_enctype enctype,
552                       krb5_data password,
553                       krb5_salt salt,
554                       krb5_data opaque,
555                       krb5_keyblock *key)
556 {
557     krb5_error_code ret;
558     uint16_t *s = NULL;
559     size_t len, i;
560     EVP_MD_CTX *m;
561
562     m = EVP_MD_CTX_create();
563     if (m == NULL) {
564         ret = ENOMEM;
565         krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
566         goto out;
567     }
568
569     EVP_DigestInit_ex(m, EVP_md4(), NULL);
570
571     ret = wind_utf8ucs2_length(password.data, &len);
572     if (ret) {
573         krb5_set_error_message (context, ret,
574                                 N_("Password not an UCS2 string", ""));
575         goto out;
576     }
577         
578     s = malloc (len * sizeof(s[0]));
579     if (len != 0 && s == NULL) {
580         krb5_set_error_message (context, ENOMEM,
581                                 N_("malloc: out of memory", ""));
582         ret = ENOMEM;
583         goto out;
584     }
585
586     ret = wind_utf8ucs2(password.data, s, &len);
587     if (ret) {
588         krb5_set_error_message (context, ret,
589                                 N_("Password not an UCS2 string", ""));
590         goto out;
591     }
592
593     /* LE encoding */
594     for (i = 0; i < len; i++) {
595         unsigned char p;
596         p = (s[i] & 0xff);
597         EVP_DigestUpdate (m, &p, 1);
598         p = (s[i] >> 8) & 0xff;
599         EVP_DigestUpdate (m, &p, 1);
600     }
601
602     key->keytype = enctype;
603     ret = krb5_data_alloc (&key->keyvalue, 16);
604     if (ret) {
605         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
606         goto out;
607     }
608     EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
609
610  out:
611     EVP_MD_CTX_destroy(m);
612     if (s)
613         memset (s, 0, len);
614     free (s);
615     return ret;
616 }
617
618 /*
619  * AES
620  */
621
622 int _krb5_AES_string_to_default_iterator = 4096;
623
624 static krb5_error_code
625 AES_string_to_key(krb5_context context,
626                   krb5_enctype enctype,
627                   krb5_data password,
628                   krb5_salt salt,
629                   krb5_data opaque,
630                   krb5_keyblock *key)
631 {
632     krb5_error_code ret;
633     uint32_t iter;
634     struct encryption_type *et;
635     struct key_data kd;
636
637     if (opaque.length == 0)
638         iter = _krb5_AES_string_to_default_iterator;
639     else if (opaque.length == 4) {
640         unsigned long v;
641         _krb5_get_int(opaque.data, &v, 4);
642         iter = ((uint32_t)v);
643     } else
644         return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
645         
646     et = _find_enctype(enctype);
647     if (et == NULL)
648         return KRB5_PROG_KEYTYPE_NOSUPP;
649
650     kd.schedule = NULL;
651     ALLOC(kd.key, 1);
652     if(kd.key == NULL) {
653         krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
654         return ENOMEM;
655     }
656     kd.key->keytype = enctype;
657     ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
658     if (ret) {
659         krb5_set_error_message (context, ret, N_("malloc: out of memory", ""));
660         return ret;
661     }
662
663     ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
664                                  salt.saltvalue.data, salt.saltvalue.length,
665                                  iter,
666                                  et->keytype->size, kd.key->keyvalue.data);
667     if (ret != 1) {
668         free_key_data(context, &kd, et);
669         krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
670                                "Error calculating s2k");
671         return KRB5_PROG_KEYTYPE_NOSUPP;
672     }
673
674     ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
675     if (ret == 0)
676         ret = krb5_copy_keyblock_contents(context, kd.key, key);
677     free_key_data(context, &kd, et);
678
679     return ret;
680 }
681
682 static void
683 evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd)
684 {
685     struct evp_schedule *key = kd->schedule->data;
686     const EVP_CIPHER *c = (*kt->evp)();
687
688     EVP_CIPHER_CTX_init(&key->ectx);
689     EVP_CIPHER_CTX_init(&key->dctx);
690
691     EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1);
692     EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0);
693 }
694
695 static void
696 evp_cleanup(krb5_context context, struct key_data *kd)
697 {
698     struct evp_schedule *key = kd->schedule->data;
699     EVP_CIPHER_CTX_cleanup(&key->ectx);
700     EVP_CIPHER_CTX_cleanup(&key->dctx);
701 }
702
703 /*
704  *
705  */
706
707 #ifdef HEIM_WEAK_CRYPTO
708 static struct salt_type des_salt[] = {
709     {
710         KRB5_PW_SALT,
711         "pw-salt",
712         krb5_DES_string_to_key
713     },
714 #ifdef ENABLE_AFS_STRING_TO_KEY
715     {
716         KRB5_AFS3_SALT,
717         "afs3-salt",
718         DES_AFS3_string_to_key
719     },
720 #endif
721     { 0 }
722 };
723 #endif
724
725 #ifdef DES3_OLD_ENCTYPE
726 static struct salt_type des3_salt[] = {
727     {
728         KRB5_PW_SALT,
729         "pw-salt",
730         DES3_string_to_key
731     },
732     { 0 }
733 };
734 #endif
735
736 static struct salt_type des3_salt_derived[] = {
737     {
738         KRB5_PW_SALT,
739         "pw-salt",
740         DES3_string_to_key_derived
741     },
742     { 0 }
743 };
744
745 static struct salt_type AES_salt[] = {
746     {
747         KRB5_PW_SALT,
748         "pw-salt",
749         AES_string_to_key
750     },
751     { 0 }
752 };
753
754 static struct salt_type arcfour_salt[] = {
755     {
756         KRB5_PW_SALT,
757         "pw-salt",
758         ARCFOUR_string_to_key
759     },
760     { 0 }
761 };
762
763 /*
764  *
765  */
766
767 static struct key_type keytype_null = {
768     KEYTYPE_NULL,
769     "null",
770     0,
771     0,
772     0,
773     NULL,
774     NULL,
775     NULL
776 };
777
778 #ifdef HEIM_WEAK_CRYPTO
779 static struct key_type keytype_des_old = {
780     KEYTYPE_DES,
781     "des-old",
782     56,
783     8,
784     sizeof(DES_key_schedule),
785     krb5_DES_random_key,
786     krb5_DES_schedule_old,
787     des_salt,
788     krb5_DES_random_to_key
789 };
790
791 static struct key_type keytype_des = {
792     KEYTYPE_DES,
793     "des",
794     56,
795     8,
796     sizeof(struct evp_schedule),
797     krb5_DES_random_key,
798     evp_schedule,
799     des_salt,
800     krb5_DES_random_to_key,
801     evp_cleanup,
802     EVP_des_cbc
803 };
804 #endif /* HEIM_WEAK_CRYPTO */
805
806 #ifdef DES3_OLD_ENCTYPE
807 static struct key_type keytype_des3 = {
808     KEYTYPE_DES3,
809     "des3",
810     168,
811     24,
812     sizeof(struct evp_schedule),
813     DES3_random_key,
814     evp_schedule,
815     des3_salt,
816     DES3_random_to_key,
817     evp_cleanup,
818     EVP_des_ede3_cbc
819 };
820 #endif
821
822 static struct key_type keytype_des3_derived = {
823     KEYTYPE_DES3,
824     "des3",
825     168,
826     24,
827     sizeof(struct evp_schedule),
828     DES3_random_key,
829     evp_schedule,
830     des3_salt_derived,
831     DES3_random_to_key,
832     evp_cleanup,
833     EVP_des_ede3_cbc
834 };
835
836 static struct key_type keytype_aes128 = {
837     KEYTYPE_AES128,
838     "aes-128",
839     128,
840     16,
841     sizeof(struct evp_schedule),
842     NULL,
843     evp_schedule,
844     AES_salt,
845     NULL,
846     evp_cleanup,
847     EVP_aes_128_cbc
848 };
849
850 static struct key_type keytype_aes256 = {
851     KEYTYPE_AES256,
852     "aes-256",
853     256,
854     32,
855     sizeof(struct evp_schedule),
856     NULL,
857     evp_schedule,
858     AES_salt,
859     NULL,
860     evp_cleanup,
861     EVP_aes_256_cbc
862 };
863
864 static struct key_type keytype_arcfour = {
865     KEYTYPE_ARCFOUR,
866     "arcfour",
867     128,
868     16,
869     sizeof(struct evp_schedule),
870     NULL,
871     evp_schedule,
872     arcfour_salt,
873     NULL,
874     evp_cleanup,
875     EVP_rc4
876 };
877
878 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
879 krb5_salttype_to_string (krb5_context context,
880                          krb5_enctype etype,
881                          krb5_salttype stype,
882                          char **string)
883 {
884     struct encryption_type *e;
885     struct salt_type *st;
886
887     e = _find_enctype (etype);
888     if (e == NULL) {
889         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
890                                "encryption type %d not supported",
891                                etype);
892         return KRB5_PROG_ETYPE_NOSUPP;
893     }
894     for (st = e->keytype->string_to_key; st && st->type; st++) {
895         if (st->type == stype) {
896             *string = strdup (st->name);
897             if (*string == NULL) {
898                 krb5_set_error_message (context, ENOMEM,
899                                         N_("malloc: out of memory", ""));
900                 return ENOMEM;
901             }
902             return 0;
903         }
904     }
905     krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
906                             "salttype %d not supported", stype);
907     return HEIM_ERR_SALTTYPE_NOSUPP;
908 }
909
910 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
911 krb5_string_to_salttype (krb5_context context,
912                          krb5_enctype etype,
913                          const char *string,
914                          krb5_salttype *salttype)
915 {
916     struct encryption_type *e;
917     struct salt_type *st;
918
919     e = _find_enctype (etype);
920     if (e == NULL) {
921         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
922                                N_("encryption type %d not supported", ""),
923                                etype);
924         return KRB5_PROG_ETYPE_NOSUPP;
925     }
926     for (st = e->keytype->string_to_key; st && st->type; st++) {
927         if (strcasecmp (st->name, string) == 0) {
928             *salttype = st->type;
929             return 0;
930         }
931     }
932     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
933                            N_("salttype %s not supported", ""), string);
934     return HEIM_ERR_SALTTYPE_NOSUPP;
935 }
936
937 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
938 krb5_get_pw_salt(krb5_context context,
939                  krb5_const_principal principal,
940                  krb5_salt *salt)
941 {
942     size_t len;
943     int i;
944     krb5_error_code ret;
945     char *p;
946
947     salt->salttype = KRB5_PW_SALT;
948     len = strlen(principal->realm);
949     for (i = 0; i < principal->name.name_string.len; ++i)
950         len += strlen(principal->name.name_string.val[i]);
951     ret = krb5_data_alloc (&salt->saltvalue, len);
952     if (ret)
953         return ret;
954     p = salt->saltvalue.data;
955     memcpy (p, principal->realm, strlen(principal->realm));
956     p += strlen(principal->realm);
957     for (i = 0; i < principal->name.name_string.len; ++i) {
958         memcpy (p,
959                 principal->name.name_string.val[i],
960                 strlen(principal->name.name_string.val[i]));
961         p += strlen(principal->name.name_string.val[i]);
962     }
963     return 0;
964 }
965
966 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
967 krb5_free_salt(krb5_context context,
968                krb5_salt salt)
969 {
970     krb5_data_free(&salt.saltvalue);
971     return 0;
972 }
973
974 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
975 krb5_string_to_key_data (krb5_context context,
976                          krb5_enctype enctype,
977                          krb5_data password,
978                          krb5_principal principal,
979                          krb5_keyblock *key)
980 {
981     krb5_error_code ret;
982     krb5_salt salt;
983
984     ret = krb5_get_pw_salt(context, principal, &salt);
985     if(ret)
986         return ret;
987     ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
988     krb5_free_salt(context, salt);
989     return ret;
990 }
991
992 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
993 krb5_string_to_key (krb5_context context,
994                     krb5_enctype enctype,
995                     const char *password,
996                     krb5_principal principal,
997                     krb5_keyblock *key)
998 {
999     krb5_data pw;
1000     pw.data = rk_UNCONST(password);
1001     pw.length = strlen(password);
1002     return krb5_string_to_key_data(context, enctype, pw, principal, key);
1003 }
1004
1005 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1006 krb5_string_to_key_data_salt (krb5_context context,
1007                               krb5_enctype enctype,
1008                               krb5_data password,
1009                               krb5_salt salt,
1010                               krb5_keyblock *key)
1011 {
1012     krb5_data opaque;
1013     krb5_data_zero(&opaque);
1014     return krb5_string_to_key_data_salt_opaque(context, enctype, password,
1015                                                salt, opaque, key);
1016 }
1017
1018 /*
1019  * Do a string -> key for encryption type `enctype' operation on
1020  * `password' (with salt `salt' and the enctype specific data string
1021  * `opaque'), returning the resulting key in `key'
1022  */
1023
1024 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1025 krb5_string_to_key_data_salt_opaque (krb5_context context,
1026                                      krb5_enctype enctype,
1027                                      krb5_data password,
1028                                      krb5_salt salt,
1029                                      krb5_data opaque,
1030                                      krb5_keyblock *key)
1031 {
1032     struct encryption_type *et =_find_enctype(enctype);
1033     struct salt_type *st;
1034     if(et == NULL) {
1035         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1036                                N_("encryption type %d not supported", ""),
1037                                enctype);
1038         return KRB5_PROG_ETYPE_NOSUPP;
1039     }
1040     for(st = et->keytype->string_to_key; st && st->type; st++)
1041         if(st->type == salt.salttype)
1042             return (*st->string_to_key)(context, enctype, password,
1043                                         salt, opaque, key);
1044     krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
1045                            N_("salt type %d not supported", ""),
1046                            salt.salttype);
1047     return HEIM_ERR_SALTTYPE_NOSUPP;
1048 }
1049
1050 /*
1051  * Do a string -> key for encryption type `enctype' operation on the
1052  * string `password' (with salt `salt'), returning the resulting key
1053  * in `key'
1054  */
1055
1056 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1057 krb5_string_to_key_salt (krb5_context context,
1058                          krb5_enctype enctype,
1059                          const char *password,
1060                          krb5_salt salt,
1061                          krb5_keyblock *key)
1062 {
1063     krb5_data pw;
1064     pw.data = rk_UNCONST(password);
1065     pw.length = strlen(password);
1066     return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
1067 }
1068
1069 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1070 krb5_string_to_key_salt_opaque (krb5_context context,
1071                                 krb5_enctype enctype,
1072                                 const char *password,
1073                                 krb5_salt salt,
1074                                 krb5_data opaque,
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_opaque(context, enctype,
1081                                                pw, salt, opaque, key);
1082 }
1083
1084 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1085 krb5_enctype_keysize(krb5_context context,
1086                      krb5_enctype type,
1087                      size_t *keysize)
1088 {
1089     struct encryption_type *et = _find_enctype(type);
1090     if(et == NULL) {
1091         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1092                                N_("encryption type %d not supported", ""),
1093                                type);
1094         return KRB5_PROG_ETYPE_NOSUPP;
1095     }
1096     *keysize = et->keytype->size;
1097     return 0;
1098 }
1099
1100 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1101 krb5_enctype_keybits(krb5_context context,
1102                      krb5_enctype type,
1103                      size_t *keybits)
1104 {
1105     struct encryption_type *et = _find_enctype(type);
1106     if(et == NULL) {
1107         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1108                                "encryption type %d not supported",
1109                                type);
1110         return KRB5_PROG_ETYPE_NOSUPP;
1111     }
1112     *keybits = et->keytype->bits;
1113     return 0;
1114 }
1115
1116 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1117 krb5_generate_random_keyblock(krb5_context context,
1118                               krb5_enctype type,
1119                               krb5_keyblock *key)
1120 {
1121     krb5_error_code ret;
1122     struct encryption_type *et = _find_enctype(type);
1123     if(et == NULL) {
1124         krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1125                                N_("encryption type %d not supported", ""),
1126                                type);
1127         return KRB5_PROG_ETYPE_NOSUPP;
1128     }
1129     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
1130     if(ret)
1131         return ret;
1132     key->keytype = type;
1133     if(et->keytype->random_key)
1134         (*et->keytype->random_key)(context, key);
1135     else
1136         krb5_generate_random_block(key->keyvalue.data,
1137                                    key->keyvalue.length);
1138     return 0;
1139 }
1140
1141 static krb5_error_code
1142 _key_schedule(krb5_context context,
1143               struct key_data *key)
1144 {
1145     krb5_error_code ret;
1146     struct encryption_type *et = _find_enctype(key->key->keytype);
1147     struct key_type *kt;
1148
1149     if (et == NULL) {
1150         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
1151                                 N_("encryption type %d not supported", ""),
1152                                 key->key->keytype);
1153         return KRB5_PROG_ETYPE_NOSUPP;
1154     }
1155
1156     kt = et->keytype;
1157
1158     if(kt->schedule == NULL)
1159         return 0;
1160     if (key->schedule != NULL)
1161         return 0;
1162     ALLOC(key->schedule, 1);
1163     if(key->schedule == NULL) {
1164         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1165         return ENOMEM;
1166     }
1167     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
1168     if(ret) {
1169         free(key->schedule);
1170         key->schedule = NULL;
1171         return ret;
1172     }
1173     (*kt->schedule)(context, kt, key);
1174     return 0;
1175 }
1176
1177 /************************************************************
1178  *                                                          *
1179  ************************************************************/
1180
1181 static krb5_error_code
1182 NONE_checksum(krb5_context context,
1183               struct key_data *key,
1184               const void *data,
1185               size_t len,
1186               unsigned usage,
1187               Checksum *C)
1188 {
1189     return 0;
1190 }
1191
1192 #if defined(DES3_OLD_ENCTYPE) || defined(HEIM_WEAK_CRYPTO)
1193
1194 static krb5_error_code
1195 des_checksum(krb5_context context,
1196              const EVP_MD *evp_md,
1197              struct key_data *key,
1198              const void *data,
1199              size_t len,
1200              Checksum *cksum)
1201 {
1202     struct evp_schedule *ctx = key->schedule->data;
1203     EVP_MD_CTX *m;
1204     DES_cblock ivec;
1205     unsigned char *p = cksum->checksum.data;
1206
1207     krb5_generate_random_block(p, 8);
1208
1209     m = EVP_MD_CTX_create();
1210     if (m == NULL) {
1211         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1212         return ENOMEM;
1213     }
1214
1215     EVP_DigestInit_ex(m, evp_md, NULL);
1216     EVP_DigestUpdate(m, p, 8);
1217     EVP_DigestUpdate(m, data, len);
1218     EVP_DigestFinal_ex (m, p + 8, NULL);
1219     EVP_MD_CTX_destroy(m);
1220     memset (&ivec, 0, sizeof(ivec));
1221     EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1);
1222     EVP_Cipher(&ctx->ectx, p, p, 24);
1223
1224     return 0;
1225 }
1226
1227 static krb5_error_code
1228 des_verify(krb5_context context,
1229            const EVP_MD *evp_md,
1230            struct key_data *key,
1231            const void *data,
1232            size_t len,
1233            Checksum *C)
1234 {
1235     struct evp_schedule *ctx = key->schedule->data;
1236     EVP_MD_CTX *m;
1237     unsigned char tmp[24];
1238     unsigned char res[16];
1239     DES_cblock ivec;
1240     krb5_error_code ret = 0;
1241
1242     m = EVP_MD_CTX_create();
1243     if (m == NULL) {
1244         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1245         return ENOMEM;
1246     }
1247
1248     memset(&ivec, 0, sizeof(ivec));
1249     EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1);
1250     EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24);
1251
1252     EVP_DigestInit_ex(m, evp_md, NULL);
1253     EVP_DigestUpdate(m, tmp, 8); /* confounder */
1254     EVP_DigestUpdate(m, data, len);
1255     EVP_DigestFinal_ex (m, res, NULL);
1256     EVP_MD_CTX_destroy(m);
1257     if(ct_memcmp(res, tmp + 8, sizeof(res)) != 0) {
1258         krb5_clear_error_message (context);
1259         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1260     }
1261     memset(tmp, 0, sizeof(tmp));
1262     memset(res, 0, sizeof(res));
1263     return ret;
1264 }
1265
1266 #endif
1267
1268 #ifdef HEIM_WEAK_CRYPTO
1269
1270 static krb5_error_code
1271 CRC32_checksum(krb5_context context,
1272                struct key_data *key,
1273                const void *data,
1274                size_t len,
1275                unsigned usage,
1276                Checksum *C)
1277 {
1278     uint32_t crc;
1279     unsigned char *r = C->checksum.data;
1280     _krb5_crc_init_table ();
1281     crc = _krb5_crc_update (data, len, 0);
1282     r[0] = crc & 0xff;
1283     r[1] = (crc >> 8)  & 0xff;
1284     r[2] = (crc >> 16) & 0xff;
1285     r[3] = (crc >> 24) & 0xff;
1286     return 0;
1287 }
1288
1289 static krb5_error_code
1290 RSA_MD4_checksum(krb5_context context,
1291                  struct key_data *key,
1292                  const void *data,
1293                  size_t len,
1294                  unsigned usage,
1295                  Checksum *C)
1296 {
1297     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1)
1298         krb5_abortx(context, "md4 checksum failed");
1299     return 0;
1300 }
1301
1302 static krb5_error_code
1303 RSA_MD4_DES_checksum(krb5_context context,
1304                      struct key_data *key,
1305                      const void *data,
1306                      size_t len,
1307                      unsigned usage,
1308                      Checksum *cksum)
1309 {
1310     return des_checksum(context, EVP_md4(), key, data, len, cksum);
1311 }
1312
1313 static krb5_error_code
1314 RSA_MD4_DES_verify(krb5_context context,
1315                    struct key_data *key,
1316                    const void *data,
1317                    size_t len,
1318                    unsigned usage,
1319                    Checksum *C)
1320 {
1321     return des_verify(context, EVP_md5(), key, data, len, C);
1322 }
1323
1324 static krb5_error_code
1325 RSA_MD5_DES_checksum(krb5_context context,
1326                      struct key_data *key,
1327                      const void *data,
1328                      size_t len,
1329                      unsigned usage,
1330                      Checksum *C)
1331 {
1332     return des_checksum(context, EVP_md5(), key, data, len, C);
1333 }
1334
1335 static krb5_error_code
1336 RSA_MD5_DES_verify(krb5_context context,
1337                    struct key_data *key,
1338                    const void *data,
1339                    size_t len,
1340                    unsigned usage,
1341                    Checksum *C)
1342 {
1343     return des_verify(context, EVP_md5(), key, data, len, C);
1344 }
1345
1346 #endif /* HEIM_WEAK_CRYPTO */
1347
1348 #ifdef DES3_OLD_ENCTYPE
1349 static krb5_error_code
1350 RSA_MD5_DES3_checksum(krb5_context context,
1351                       struct key_data *key,
1352                       const void *data,
1353                       size_t len,
1354                       unsigned usage,
1355                       Checksum *C)
1356 {
1357     return des_checksum(context, EVP_md5(), key, data, len, C);
1358 }
1359
1360 static krb5_error_code
1361 RSA_MD5_DES3_verify(krb5_context context,
1362                     struct key_data *key,
1363                     const void *data,
1364                     size_t len,
1365                     unsigned usage,
1366                     Checksum *C)
1367 {
1368     return des_verify(context, EVP_md5(), key, data, len, C);
1369 }
1370 #endif
1371
1372 static krb5_error_code
1373 SHA1_checksum(krb5_context context,
1374               struct key_data *key,
1375               const void *data,
1376               size_t len,
1377               unsigned usage,
1378               Checksum *C)
1379 {
1380     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
1381         krb5_abortx(context, "sha1 checksum failed");
1382     return 0;
1383 }
1384
1385 /* HMAC according to RFC2104 */
1386 static krb5_error_code
1387 hmac(krb5_context context,
1388      struct checksum_type *cm,
1389      const void *data,
1390      size_t len,
1391      unsigned usage,
1392      struct key_data *keyblock,
1393      Checksum *result)
1394 {
1395     unsigned char *ipad, *opad;
1396     unsigned char *key;
1397     size_t key_len;
1398     int i;
1399
1400     ipad = malloc(cm->blocksize + len);
1401     if (ipad == NULL)
1402         return ENOMEM;
1403     opad = malloc(cm->blocksize + cm->checksumsize);
1404     if (opad == NULL) {
1405         free(ipad);
1406         return ENOMEM;
1407     }
1408     memset(ipad, 0x36, cm->blocksize);
1409     memset(opad, 0x5c, cm->blocksize);
1410
1411     if(keyblock->key->keyvalue.length > cm->blocksize){
1412         (*cm->checksum)(context,
1413                         keyblock,
1414                         keyblock->key->keyvalue.data,
1415                         keyblock->key->keyvalue.length,
1416                         usage,
1417                         result);
1418         key = result->checksum.data;
1419         key_len = result->checksum.length;
1420     } else {
1421         key = keyblock->key->keyvalue.data;
1422         key_len = keyblock->key->keyvalue.length;
1423     }
1424     for(i = 0; i < key_len; i++){
1425         ipad[i] ^= key[i];
1426         opad[i] ^= key[i];
1427     }
1428     memcpy(ipad + cm->blocksize, data, len);
1429     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1430                     usage, result);
1431     memcpy(opad + cm->blocksize, result->checksum.data,
1432            result->checksum.length);
1433     (*cm->checksum)(context, keyblock, opad,
1434                     cm->blocksize + cm->checksumsize, usage, result);
1435     memset(ipad, 0, cm->blocksize + len);
1436     free(ipad);
1437     memset(opad, 0, cm->blocksize + cm->checksumsize);
1438     free(opad);
1439
1440     return 0;
1441 }
1442
1443 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1444 krb5_hmac(krb5_context context,
1445           krb5_cksumtype cktype,
1446           const void *data,
1447           size_t len,
1448           unsigned usage,
1449           krb5_keyblock *key,
1450           Checksum *result)
1451 {
1452     struct checksum_type *c = _find_checksum(cktype);
1453     struct key_data kd;
1454     krb5_error_code ret;
1455
1456     if (c == NULL) {
1457         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1458                                 N_("checksum type %d not supported", ""),
1459                                 cktype);
1460         return KRB5_PROG_SUMTYPE_NOSUPP;
1461     }
1462
1463     kd.key = key;
1464     kd.schedule = NULL;
1465
1466     ret = hmac(context, c, data, len, usage, &kd, result);
1467
1468     if (kd.schedule)
1469         krb5_free_data(context, kd.schedule);
1470
1471     return ret;
1472 }
1473
1474 static krb5_error_code
1475 SP_HMAC_SHA1_checksum(krb5_context context,
1476                       struct key_data *key,
1477                       const void *data,
1478                       size_t len,
1479                       unsigned usage,
1480                       Checksum *result)
1481 {
1482     struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1483     Checksum res;
1484     char sha1_data[20];
1485     krb5_error_code ret;
1486
1487     res.checksum.data = sha1_data;
1488     res.checksum.length = sizeof(sha1_data);
1489
1490     ret = hmac(context, c, data, len, usage, key, &res);
1491     if (ret)
1492         krb5_abortx(context, "hmac failed");
1493     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
1494     return 0;
1495 }
1496
1497 /*
1498  * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1499  *
1500  * This function made available to PAC routines
1501  */
1502
1503 static krb5_error_code
1504 HMAC_MD5_checksum(krb5_context context,
1505                   struct key_data *key,
1506                   const void *data,
1507                   size_t len,
1508                   unsigned usage,
1509                   Checksum *result)
1510 {
1511     EVP_MD_CTX *m;
1512     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1513     const char signature[] = "signaturekey";
1514     Checksum ksign_c;
1515     struct key_data ksign;
1516     krb5_keyblock kb;
1517     unsigned char t[4];
1518     unsigned char tmp[16];
1519     unsigned char ksign_c_data[16];
1520     krb5_error_code ret;
1521
1522     m = EVP_MD_CTX_create();
1523     if (m == NULL) {
1524         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1525         return ENOMEM;
1526     }
1527     ksign_c.checksum.length = sizeof(ksign_c_data);
1528     ksign_c.checksum.data   = ksign_c_data;
1529     ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1530     if (ret) {
1531         EVP_MD_CTX_destroy(m);
1532         return ret;
1533     }
1534     ksign.key = &kb;
1535     kb.keyvalue = ksign_c.checksum;
1536     EVP_DigestInit_ex(m, EVP_md5(), NULL);
1537     t[0] = (usage >>  0) & 0xFF;
1538     t[1] = (usage >>  8) & 0xFF;
1539     t[2] = (usage >> 16) & 0xFF;
1540     t[3] = (usage >> 24) & 0xFF;
1541     EVP_DigestUpdate(m, t, 4);
1542     EVP_DigestUpdate(m, data, len);
1543     EVP_DigestFinal_ex (m, tmp, NULL);
1544     EVP_MD_CTX_destroy(m);
1545
1546     ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1547     if (ret)
1548         return ret;
1549     return 0;
1550 }
1551
1552 /* HMAC-MD5 checksum over any key (needed for the PAC routines) */
1553 krb5_error_code
1554 HMAC_MD5_any_checksum(krb5_context context,
1555                       const krb5_keyblock *key,
1556                       const void *data,
1557                       size_t len,
1558                       unsigned usage,
1559                       Checksum *result)
1560 {
1561         krb5_error_code ret;
1562         struct key_data local_key;
1563         ret = krb5_copy_keyblock(context, key, &local_key.key);
1564         if (ret)
1565             return ret;
1566
1567         local_key.schedule = NULL;
1568         ret = krb5_data_alloc (&result->checksum, 16);
1569         if (ret)
1570             return ret;
1571
1572         result->cksumtype = CKSUMTYPE_HMAC_MD5;
1573         ret = HMAC_MD5_checksum(context, &local_key, data, len, usage, result);
1574
1575         if (ret)
1576                 krb5_data_free(&result->checksum);
1577
1578         krb5_free_keyblock(context, local_key.key);
1579         return ret;
1580 }
1581
1582 static struct checksum_type checksum_none = {
1583     CKSUMTYPE_NONE,
1584     "none",
1585     1,
1586     0,
1587     0,
1588     NONE_checksum,
1589     NULL
1590 };
1591 #ifdef HEIM_WEAK_CRYPTO
1592 static struct checksum_type checksum_crc32 = {
1593     CKSUMTYPE_CRC32,
1594     "crc32",
1595     1,
1596     4,
1597     0,
1598     CRC32_checksum,
1599     NULL
1600 };
1601 static struct checksum_type checksum_rsa_md4 = {
1602     CKSUMTYPE_RSA_MD4,
1603     "rsa-md4",
1604     64,
1605     16,
1606     F_CPROOF,
1607     RSA_MD4_checksum,
1608     NULL
1609 };
1610 static struct checksum_type checksum_rsa_md4_des = {
1611     CKSUMTYPE_RSA_MD4_DES,
1612     "rsa-md4-des",
1613     64,
1614     24,
1615     F_KEYED | F_CPROOF | F_VARIANT,
1616     RSA_MD4_DES_checksum,
1617     RSA_MD4_DES_verify
1618 };
1619 static struct checksum_type checksum_rsa_md5_des = {
1620     CKSUMTYPE_RSA_MD5_DES,
1621     "rsa-md5-des",
1622     64,
1623     24,
1624     F_KEYED | F_CPROOF | F_VARIANT,
1625     RSA_MD5_DES_checksum,
1626     RSA_MD5_DES_verify
1627 };
1628 #endif /* HEIM_WEAK_CRYPTO */
1629
1630 static krb5_error_code
1631 RSA_MD5_checksum(krb5_context context,
1632                  struct key_data *key,
1633                  const void *data,
1634                  size_t len,
1635                  unsigned usage,
1636                  Checksum *C)
1637 {
1638     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1)
1639         krb5_abortx(context, "md5 checksum failed");
1640     return 0;
1641 }
1642
1643 static struct checksum_type checksum_rsa_md5 = {
1644     CKSUMTYPE_RSA_MD5,
1645     "rsa-md5",
1646     64,
1647     16,
1648     F_CPROOF,
1649     RSA_MD5_checksum,
1650     NULL
1651 };
1652
1653 #ifdef DES3_OLD_ENCTYPE
1654 static struct checksum_type checksum_rsa_md5_des3 = {
1655     CKSUMTYPE_RSA_MD5_DES3,
1656     "rsa-md5-des3",
1657     64,
1658     24,
1659     F_KEYED | F_CPROOF | F_VARIANT,
1660     RSA_MD5_DES3_checksum,
1661     RSA_MD5_DES3_verify
1662 };
1663 #endif
1664 static struct checksum_type checksum_sha1 = {
1665     CKSUMTYPE_SHA1,
1666     "sha1",
1667     64,
1668     20,
1669     F_CPROOF,
1670     SHA1_checksum,
1671     NULL
1672 };
1673 static struct checksum_type checksum_hmac_sha1_des3 = {
1674     CKSUMTYPE_HMAC_SHA1_DES3,
1675     "hmac-sha1-des3",
1676     64,
1677     20,
1678     F_KEYED | F_CPROOF | F_DERIVED,
1679     SP_HMAC_SHA1_checksum,
1680     NULL
1681 };
1682
1683 static struct checksum_type checksum_hmac_sha1_aes128 = {
1684     CKSUMTYPE_HMAC_SHA1_96_AES_128,
1685     "hmac-sha1-96-aes128",
1686     64,
1687     12,
1688     F_KEYED | F_CPROOF | F_DERIVED,
1689     SP_HMAC_SHA1_checksum,
1690     NULL
1691 };
1692
1693 static struct checksum_type checksum_hmac_sha1_aes256 = {
1694     CKSUMTYPE_HMAC_SHA1_96_AES_256,
1695     "hmac-sha1-96-aes256",
1696     64,
1697     12,
1698     F_KEYED | F_CPROOF | F_DERIVED,
1699     SP_HMAC_SHA1_checksum,
1700     NULL
1701 };
1702
1703 static struct checksum_type checksum_hmac_md5 = {
1704     CKSUMTYPE_HMAC_MD5,
1705     "hmac-md5",
1706     64,
1707     16,
1708     F_KEYED | F_CPROOF,
1709     HMAC_MD5_checksum,
1710     NULL
1711 };
1712
1713 static struct checksum_type *checksum_types[] = {
1714     &checksum_none,
1715 #ifdef HEIM_WEAK_CRYPTO
1716     &checksum_crc32,
1717     &checksum_rsa_md4,
1718     &checksum_rsa_md4_des,
1719     &checksum_rsa_md5_des,
1720 #endif
1721 #ifdef DES3_OLD_ENCTYPE
1722     &checksum_rsa_md5_des3,
1723 #endif
1724     &checksum_rsa_md5,
1725     &checksum_sha1,
1726     &checksum_hmac_sha1_des3,
1727     &checksum_hmac_sha1_aes128,
1728     &checksum_hmac_sha1_aes256,
1729     &checksum_hmac_md5
1730 };
1731
1732 static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1733
1734 static struct checksum_type *
1735 _find_checksum(krb5_cksumtype type)
1736 {
1737     int i;
1738     for(i = 0; i < num_checksums; i++)
1739         if(checksum_types[i]->type == type)
1740             return checksum_types[i];
1741     return NULL;
1742 }
1743
1744 static krb5_error_code
1745 get_checksum_key(krb5_context context,
1746                  krb5_crypto crypto,
1747                  unsigned usage,  /* not krb5_key_usage */
1748                  struct checksum_type *ct,
1749                  struct key_data **key)
1750 {
1751     krb5_error_code ret = 0;
1752
1753     if(ct->flags & F_DERIVED)
1754         ret = _get_derived_key(context, crypto, usage, key);
1755     else if(ct->flags & F_VARIANT) {
1756         int i;
1757
1758         *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1759         if(*key == NULL) {
1760             krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1761             return ENOMEM;
1762         }
1763         ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1764         if(ret)
1765             return ret;
1766         for(i = 0; i < (*key)->key->keyvalue.length; i++)
1767             ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1768     } else {
1769         *key = &crypto->key;
1770     }
1771     if(ret == 0)
1772         ret = _key_schedule(context, *key);
1773     return ret;
1774 }
1775
1776 static krb5_error_code
1777 create_checksum (krb5_context context,
1778                  struct checksum_type *ct,
1779                  krb5_crypto crypto,
1780                  unsigned usage,
1781                  void *data,
1782                  size_t len,
1783                  Checksum *result)
1784 {
1785     krb5_error_code ret;
1786     struct key_data *dkey;
1787     int keyed_checksum;
1788
1789     if (ct->flags & F_DISABLED) {
1790         krb5_clear_error_message (context);
1791         return KRB5_PROG_SUMTYPE_NOSUPP;
1792     }
1793     keyed_checksum = (ct->flags & F_KEYED) != 0;
1794     if(keyed_checksum && crypto == NULL) {
1795         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1796                                 N_("Checksum type %s is keyed but no "
1797                                    "crypto context (key) was passed in", ""),
1798                                 ct->name);
1799         return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1800     }
1801     if(keyed_checksum) {
1802         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1803         if (ret)
1804             return ret;
1805     } else
1806         dkey = NULL;
1807     result->cksumtype = ct->type;
1808     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1809     if (ret)
1810         return (ret);
1811     return (*ct->checksum)(context, dkey, data, len, usage, result);
1812 }
1813
1814 static int
1815 arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
1816 {
1817     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1818         (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1819 }
1820
1821 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1822 krb5_create_checksum(krb5_context context,
1823                      krb5_crypto crypto,
1824                      krb5_key_usage usage,
1825                      int type,
1826                      void *data,
1827                      size_t len,
1828                      Checksum *result)
1829 {
1830     struct checksum_type *ct = NULL;
1831     unsigned keyusage;
1832
1833     /* type 0 -> pick from crypto */
1834     if (type) {
1835         ct = _find_checksum(type);
1836     } else if (crypto) {
1837         ct = crypto->et->keyed_checksum;
1838         if (ct == NULL)
1839             ct = crypto->et->checksum;
1840     }
1841
1842     if(ct == NULL) {
1843         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1844                                 N_("checksum type %d not supported", ""),
1845                                 type);
1846         return KRB5_PROG_SUMTYPE_NOSUPP;
1847     }
1848
1849     if (arcfour_checksum_p(ct, crypto)) {
1850         keyusage = usage;
1851         usage2arcfour(context, &keyusage);
1852     } else
1853         keyusage = CHECKSUM_USAGE(usage);
1854
1855     return create_checksum(context, ct, crypto, keyusage,
1856                            data, len, result);
1857 }
1858
1859 static krb5_error_code
1860 verify_checksum(krb5_context context,
1861                 krb5_crypto crypto,
1862                 unsigned usage, /* not krb5_key_usage */
1863                 void *data,
1864                 size_t len,
1865                 Checksum *cksum)
1866 {
1867     krb5_error_code ret;
1868     struct key_data *dkey;
1869     int keyed_checksum;
1870     Checksum c;
1871     struct checksum_type *ct;
1872
1873     ct = _find_checksum(cksum->cksumtype);
1874     if (ct == NULL || (ct->flags & F_DISABLED)) {
1875         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1876                                 N_("checksum type %d not supported", ""),
1877                                 cksum->cksumtype);
1878         return KRB5_PROG_SUMTYPE_NOSUPP;
1879     }
1880     if(ct->checksumsize != cksum->checksum.length) {
1881         krb5_clear_error_message (context);
1882         krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
1883                                N_("Decrypt integrity check failed for checksum type %s, "
1884                                   "length was %u, expected %u", ""),
1885                                ct->name, (unsigned)cksum->checksum.length,
1886                                (unsigned)ct->checksumsize);
1887
1888         return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1889     }
1890     keyed_checksum = (ct->flags & F_KEYED) != 0;
1891     if(keyed_checksum) {
1892         struct checksum_type *kct;
1893         if (crypto == NULL) {
1894             krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
1895                                    N_("Checksum type %s is keyed but no "
1896                                       "crypto context (key) was passed in", ""),
1897                                    ct->name);
1898             return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1899         }
1900         kct = crypto->et->keyed_checksum;
1901         if (kct != NULL && kct->type != ct->type) {
1902             krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
1903                                    N_("Checksum type %s is keyed, but "
1904                                       "the key type %s passed didnt have that checksum "
1905                                       "type as the keyed type", ""),
1906                                     ct->name, crypto->et->name);
1907             return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1908         }
1909
1910         ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1911         if (ret)
1912             return ret;
1913     } else
1914         dkey = NULL;
1915
1916     /*
1917      * If checksum have a verify function, lets use that instead of
1918      * calling ->checksum and then compare result.
1919      */
1920
1921     if(ct->verify) {
1922         ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
1923         if (ret)
1924             krb5_set_error_message(context, ret, 
1925                                    N_("Decrypt integrity check failed for checksum "
1926                                       "type %s, key type %s", ""),
1927                                    ct->name, crypto->et->name);
1928         return ret;
1929     }
1930
1931     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1932     if (ret)
1933         return ret;
1934
1935     ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
1936     if (ret) {
1937         krb5_data_free(&c.checksum);
1938         return ret;
1939     }
1940
1941     if(c.checksum.length != cksum->checksum.length ||
1942        ct_memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
1943         krb5_clear_error_message (context);
1944         ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1945         krb5_set_error_message(context, ret,
1946                                N_("Decrypt integrity check failed for checksum "
1947                                   "type %s, key type %s", ""),
1948                                ct->name, crypto ? crypto->et->name : "(unkeyed)");
1949     } else {
1950         ret = 0;
1951     }
1952     krb5_data_free (&c.checksum);
1953     return ret;
1954 }
1955
1956 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1957 krb5_verify_checksum(krb5_context context,
1958                      krb5_crypto crypto,
1959                      krb5_key_usage usage,
1960                      void *data,
1961                      size_t len,
1962                      Checksum *cksum)
1963 {
1964     struct checksum_type *ct;
1965     unsigned keyusage;
1966
1967     ct = _find_checksum(cksum->cksumtype);
1968     if(ct == NULL) {
1969         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
1970                                 N_("checksum type %d not supported", ""),
1971                                 cksum->cksumtype);
1972         return KRB5_PROG_SUMTYPE_NOSUPP;
1973     }
1974
1975     if (arcfour_checksum_p(ct, crypto)) {
1976         keyusage = usage;
1977         usage2arcfour(context, &keyusage);
1978     } else
1979         keyusage = CHECKSUM_USAGE(usage);
1980
1981     return verify_checksum(context, crypto, keyusage,
1982                            data, len, cksum);
1983 }
1984
1985 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1986 krb5_crypto_get_checksum_type(krb5_context context,
1987                               krb5_crypto crypto,
1988                               krb5_cksumtype *type)
1989 {
1990     struct checksum_type *ct = NULL;
1991
1992     if (crypto != NULL) {
1993         ct = crypto->et->keyed_checksum;
1994         if (ct == NULL)
1995             ct = crypto->et->checksum;
1996     }
1997
1998     if (ct == NULL) {
1999         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2000                                 N_("checksum type not found", ""));
2001         return KRB5_PROG_SUMTYPE_NOSUPP;
2002     }
2003
2004     *type = ct->type;
2005
2006     return 0;
2007 }
2008
2009
2010 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2011 krb5_checksumsize(krb5_context context,
2012                   krb5_cksumtype type,
2013                   size_t *size)
2014 {
2015     struct checksum_type *ct = _find_checksum(type);
2016     if(ct == NULL) {
2017         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2018                                 N_("checksum type %d not supported", ""),
2019                                 type);
2020         return KRB5_PROG_SUMTYPE_NOSUPP;
2021     }
2022     *size = ct->checksumsize;
2023     return 0;
2024 }
2025
2026 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2027 krb5_checksum_is_keyed(krb5_context context,
2028                        krb5_cksumtype type)
2029 {
2030     struct checksum_type *ct = _find_checksum(type);
2031     if(ct == NULL) {
2032         if (context)
2033             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2034                                     N_("checksum type %d not supported", ""),
2035                                     type);
2036         return KRB5_PROG_SUMTYPE_NOSUPP;
2037     }
2038     return ct->flags & F_KEYED;
2039 }
2040
2041 KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2042 krb5_checksum_is_collision_proof(krb5_context context,
2043                                  krb5_cksumtype type)
2044 {
2045     struct checksum_type *ct = _find_checksum(type);
2046     if(ct == NULL) {
2047         if (context)
2048             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2049                                     N_("checksum type %d not supported", ""),
2050                                     type);
2051         return KRB5_PROG_SUMTYPE_NOSUPP;
2052     }
2053     return ct->flags & F_CPROOF;
2054 }
2055
2056 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2057 krb5_checksum_disable(krb5_context context,
2058                       krb5_cksumtype type)
2059 {
2060     struct checksum_type *ct = _find_checksum(type);
2061     if(ct == NULL) {
2062         if (context)
2063             krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2064                                     N_("checksum type %d not supported", ""),
2065                                     type);
2066         return KRB5_PROG_SUMTYPE_NOSUPP;
2067     }
2068     ct->flags |= F_DISABLED;
2069     return 0;
2070 }
2071
2072 /************************************************************
2073  *                                                          *
2074  ************************************************************/
2075
2076 static krb5_error_code
2077 NULL_encrypt(krb5_context context,
2078              struct key_data *key,
2079              void *data,
2080              size_t len,
2081              krb5_boolean encryptp,
2082              int usage,
2083              void *ivec)
2084 {
2085     return 0;
2086 }
2087
2088 static krb5_error_code
2089 evp_encrypt(krb5_context context,
2090             struct key_data *key,
2091             void *data,
2092             size_t len,
2093             krb5_boolean encryptp,
2094             int usage,
2095             void *ivec)
2096 {
2097     struct evp_schedule *ctx = key->schedule->data;
2098     EVP_CIPHER_CTX *c;
2099     c = encryptp ? &ctx->ectx : &ctx->dctx;
2100     if (ivec == NULL) {
2101         /* alloca ? */
2102         size_t len2 = EVP_CIPHER_CTX_iv_length(c);
2103         void *loiv = malloc(len2);
2104         if (loiv == NULL) {
2105             krb5_clear_error_message(context);
2106             return ENOMEM;
2107         }
2108         memset(loiv, 0, len2);
2109         EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1);
2110         free(loiv);
2111     } else
2112         EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2113     EVP_Cipher(c, data, data, len);
2114     return 0;
2115 }
2116
2117 static const unsigned char zero_ivec[EVP_MAX_BLOCK_LENGTH] = { 0 };
2118
2119 static krb5_error_code
2120 evp_encrypt_cts(krb5_context context,
2121                 struct key_data *key,
2122                 void *data,
2123                 size_t len,
2124                 krb5_boolean encryptp,
2125                 int usage,
2126                 void *ivec)
2127 {
2128     size_t i, blocksize;
2129     struct evp_schedule *ctx = key->schedule->data;
2130     char tmp[EVP_MAX_BLOCK_LENGTH], ivec2[EVP_MAX_BLOCK_LENGTH];
2131     EVP_CIPHER_CTX *c;
2132     unsigned char *p;
2133
2134     c = encryptp ? &ctx->ectx : &ctx->dctx;
2135
2136     blocksize = EVP_CIPHER_CTX_block_size(c);
2137
2138     if (len < blocksize) {
2139         krb5_set_error_message(context, EINVAL,
2140                                "message block too short");
2141         return EINVAL;
2142     } else if (len == blocksize) {
2143         EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2144         EVP_Cipher(c, data, data, len);
2145         return 0;
2146     }
2147
2148     if (ivec)
2149         EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1);
2150     else
2151         EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2152
2153     if (encryptp) {
2154
2155         p = data;
2156         i = ((len - 1) / blocksize) * blocksize;
2157         EVP_Cipher(c, p, p, i);
2158         p += i - blocksize;
2159         len -= i;
2160         memcpy(ivec2, p, blocksize);
2161
2162         for (i = 0; i < len; i++)
2163             tmp[i] = p[i + blocksize] ^ ivec2[i];
2164         for (; i < blocksize; i++)
2165             tmp[i] = 0 ^ ivec2[i];
2166         
2167         EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2168         EVP_Cipher(c, p, tmp, blocksize);
2169         
2170         memcpy(p + blocksize, ivec2, len);
2171         if (ivec)
2172             memcpy(ivec, p, blocksize);
2173     } else { 
2174         char tmp2[EVP_MAX_BLOCK_LENGTH], tmp3[EVP_MAX_BLOCK_LENGTH];
2175
2176         p = data;
2177         if (len > blocksize * 2) {
2178             /* remove last two blocks and round up, decrypt this with cbc, then do cts dance */
2179             i = ((((len - blocksize * 2) + blocksize - 1) / blocksize) * blocksize);
2180             memcpy(ivec2, p + i - blocksize, blocksize);
2181             EVP_Cipher(c, p, p, i);
2182             p += i;
2183             len -= i + blocksize;
2184         } else {
2185             if (ivec)
2186                 memcpy(ivec2, ivec, blocksize);
2187             else
2188                 memcpy(ivec2, zero_ivec, blocksize);
2189             len -= blocksize;
2190         }
2191
2192         memcpy(tmp, p, blocksize);
2193         EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2194         EVP_Cipher(c, tmp2, p, blocksize);
2195
2196         memcpy(tmp3, p + blocksize, len);
2197         memcpy(tmp3 + len, tmp2 + len, blocksize - len); /* xor 0 */
2198
2199         for (i = 0; i < len; i++)
2200             p[i + blocksize] = tmp2[i] ^ tmp3[i];
2201
2202         EVP_CipherInit_ex(c, NULL, NULL, NULL, zero_ivec, -1);
2203         EVP_Cipher(c, p, tmp3, blocksize);
2204
2205         for (i = 0; i < blocksize; i++)
2206             p[i] ^= ivec2[i];
2207         if (ivec)
2208             memcpy(ivec, tmp, blocksize);
2209     }
2210     return 0;
2211 }
2212
2213 #ifdef HEIM_WEAK_CRYPTO
2214 static krb5_error_code
2215 evp_des_encrypt_null_ivec(krb5_context context,
2216                           struct key_data *key,
2217                           void *data,
2218                           size_t len,
2219                           krb5_boolean encryptp,
2220                           int usage,
2221                           void *ignore_ivec)
2222 {
2223     struct evp_schedule *ctx = key->schedule->data;
2224     EVP_CIPHER_CTX *c;
2225     DES_cblock ivec;
2226     memset(&ivec, 0, sizeof(ivec));
2227     c = encryptp ? &ctx->ectx : &ctx->dctx;
2228     EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2229     EVP_Cipher(c, data, data, len);
2230     return 0;
2231 }
2232
2233 static krb5_error_code
2234 evp_des_encrypt_key_ivec(krb5_context context,
2235                          struct key_data *key,
2236                          void *data,
2237                          size_t len,
2238                          krb5_boolean encryptp,
2239                          int usage,
2240                          void *ignore_ivec)
2241 {
2242     struct evp_schedule *ctx = key->schedule->data;
2243     EVP_CIPHER_CTX *c;
2244     DES_cblock ivec;
2245     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2246     c = encryptp ? &ctx->ectx : &ctx->dctx;
2247     EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1);
2248     EVP_Cipher(c, data, data, len);
2249     return 0;
2250 }
2251
2252 static krb5_error_code
2253 DES_CFB64_encrypt_null_ivec(krb5_context context,
2254                             struct key_data *key,
2255                             void *data,
2256                             size_t len,
2257                             krb5_boolean encryptp,
2258                             int usage,
2259                             void *ignore_ivec)
2260 {
2261     DES_cblock ivec;
2262     int num = 0;
2263     DES_key_schedule *s = key->schedule->data;
2264     memset(&ivec, 0, sizeof(ivec));
2265
2266     DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
2267     return 0;
2268 }
2269
2270 static krb5_error_code
2271 DES_PCBC_encrypt_key_ivec(krb5_context context,
2272                           struct key_data *key,
2273                           void *data,
2274                           size_t len,
2275                           krb5_boolean encryptp,
2276                           int usage,
2277                           void *ignore_ivec)
2278 {
2279     DES_cblock ivec;
2280     DES_key_schedule *s = key->schedule->data;
2281     memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2282
2283     DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
2284     return 0;
2285 }
2286 #endif
2287
2288 /*
2289  * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
2290  *
2291  * warning: not for small children
2292  */
2293
2294 static krb5_error_code
2295 ARCFOUR_subencrypt(krb5_context context,
2296                    struct key_data *key,
2297                    void *data,
2298                    size_t len,
2299                    unsigned usage,
2300                    void *ivec)
2301 {
2302     EVP_CIPHER_CTX ctx;
2303     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2304     Checksum k1_c, k2_c, k3_c, cksum;
2305     struct key_data ke;
2306     krb5_keyblock kb;
2307     unsigned char t[4];
2308     unsigned char *cdata = data;
2309     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2310     krb5_error_code ret;
2311
2312     t[0] = (usage >>  0) & 0xFF;
2313     t[1] = (usage >>  8) & 0xFF;
2314     t[2] = (usage >> 16) & 0xFF;
2315     t[3] = (usage >> 24) & 0xFF;
2316
2317     k1_c.checksum.length = sizeof(k1_c_data);
2318     k1_c.checksum.data   = k1_c_data;
2319
2320     ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2321     if (ret)
2322         krb5_abortx(context, "hmac failed");
2323
2324     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2325
2326     k2_c.checksum.length = sizeof(k2_c_data);
2327     k2_c.checksum.data   = k2_c_data;
2328
2329     ke.key = &kb;
2330     kb.keyvalue = k2_c.checksum;
2331
2332     cksum.checksum.length = 16;
2333     cksum.checksum.data   = data;
2334
2335     ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2336     if (ret)
2337         krb5_abortx(context, "hmac failed");
2338
2339     ke.key = &kb;
2340     kb.keyvalue = k1_c.checksum;
2341
2342     k3_c.checksum.length = sizeof(k3_c_data);
2343     k3_c.checksum.data   = k3_c_data;
2344
2345     ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2346     if (ret)
2347         krb5_abortx(context, "hmac failed");
2348
2349     EVP_CIPHER_CTX_init(&ctx);
2350
2351     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
2352     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2353     EVP_CIPHER_CTX_cleanup(&ctx);
2354
2355     memset (k1_c_data, 0, sizeof(k1_c_data));
2356     memset (k2_c_data, 0, sizeof(k2_c_data));
2357     memset (k3_c_data, 0, sizeof(k3_c_data));
2358     return 0;
2359 }
2360
2361 static krb5_error_code
2362 ARCFOUR_subdecrypt(krb5_context context,
2363                    struct key_data *key,
2364                    void *data,
2365                    size_t len,
2366                    unsigned usage,
2367                    void *ivec)
2368 {
2369     EVP_CIPHER_CTX ctx;
2370     struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
2371     Checksum k1_c, k2_c, k3_c, cksum;
2372     struct key_data ke;
2373     krb5_keyblock kb;
2374     unsigned char t[4];
2375     unsigned char *cdata = data;
2376     unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2377     unsigned char cksum_data[16];
2378     krb5_error_code ret;
2379
2380     t[0] = (usage >>  0) & 0xFF;
2381     t[1] = (usage >>  8) & 0xFF;
2382     t[2] = (usage >> 16) & 0xFF;
2383     t[3] = (usage >> 24) & 0xFF;
2384
2385     k1_c.checksum.length = sizeof(k1_c_data);
2386     k1_c.checksum.data   = k1_c_data;
2387
2388     ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2389     if (ret)
2390         krb5_abortx(context, "hmac failed");
2391
2392     memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
2393
2394     k2_c.checksum.length = sizeof(k2_c_data);
2395     k2_c.checksum.data   = k2_c_data;
2396
2397     ke.key = &kb;
2398     kb.keyvalue = k1_c.checksum;
2399
2400     k3_c.checksum.length = sizeof(k3_c_data);
2401     k3_c.checksum.data   = k3_c_data;
2402
2403     ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2404     if (ret)
2405         krb5_abortx(context, "hmac failed");
2406
2407     EVP_CIPHER_CTX_init(&ctx);
2408     EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
2409     EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
2410     EVP_CIPHER_CTX_cleanup(&ctx);
2411
2412     ke.key = &kb;
2413     kb.keyvalue = k2_c.checksum;
2414
2415     cksum.checksum.length = 16;
2416     cksum.checksum.data   = cksum_data;
2417
2418     ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2419     if (ret)
2420         krb5_abortx(context, "hmac failed");
2421
2422     memset (k1_c_data, 0, sizeof(k1_c_data));
2423     memset (k2_c_data, 0, sizeof(k2_c_data));
2424     memset (k3_c_data, 0, sizeof(k3_c_data));
2425
2426     if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
2427         krb5_clear_error_message (context);
2428         return KRB5KRB_AP_ERR_BAD_INTEGRITY;
2429     } else {
2430         return 0;
2431     }
2432 }
2433
2434 /*
2435  * convert the usage numbers used in
2436  * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2437  * draft-brezak-win2k-krb-rc4-hmac-04.txt
2438  */
2439
2440 static krb5_error_code
2441 usage2arcfour (krb5_context context, unsigned *usage)
2442 {
2443     switch (*usage) {
2444     case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2445         *usage = 8;
2446         return 0;
2447     case KRB5_KU_USAGE_SEAL :  /* 22 */
2448         *usage = 13;
2449         return 0;
2450     case KRB5_KU_USAGE_SIGN : /* 23 */
2451         *usage = 15;
2452         return 0;
2453     case KRB5_KU_USAGE_SEQ: /* 24 */
2454         *usage = 0;
2455         return 0;
2456     default :
2457         return 0;
2458     }
2459 }
2460
2461 static krb5_error_code
2462 ARCFOUR_encrypt(krb5_context context,
2463                 struct key_data *key,
2464                 void *data,
2465                 size_t len,
2466                 krb5_boolean encryptp,
2467                 int usage,
2468                 void *ivec)
2469 {
2470     krb5_error_code ret;
2471     unsigned keyusage = usage;
2472
2473     if((ret = usage2arcfour (context, &keyusage)) != 0)
2474         return ret;
2475
2476     if (encryptp)
2477         return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
2478     else
2479         return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
2480 }
2481
2482
2483 /*
2484  *
2485  */
2486
2487 static krb5_error_code
2488 AES_PRF(krb5_context context,
2489         krb5_crypto crypto,
2490         const krb5_data *in,
2491         krb5_data *out)
2492 {
2493     struct checksum_type *ct = crypto->et->checksum;
2494     krb5_error_code ret;
2495     Checksum result;
2496     krb5_keyblock *derived;
2497
2498     result.cksumtype = ct->type;
2499     ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2500     if (ret) {
2501         krb5_set_error_message(context, ret, N_("malloc: out memory", ""));
2502         return ret;
2503     }
2504
2505     ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2506     if (ret) {
2507         krb5_data_free(&result.checksum);
2508         return ret;
2509     }
2510
2511     if (result.checksum.length < crypto->et->blocksize)
2512         krb5_abortx(context, "internal prf error");
2513
2514     derived = NULL;
2515     ret = krb5_derive_key(context, crypto->key.key,
2516                           crypto->et->type, "prf", 3, &derived);
2517     if (ret)
2518         krb5_abortx(context, "krb5_derive_key");
2519
2520     ret = krb5_data_alloc(out, crypto->et->blocksize);
2521     if (ret)
2522         krb5_abortx(context, "malloc failed");
2523
2524     {
2525         const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
2526         EVP_CIPHER_CTX ctx;
2527
2528         EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
2529         EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
2530         EVP_Cipher(&ctx, out->data, result.checksum.data,
2531                    crypto->et->blocksize);
2532         EVP_CIPHER_CTX_cleanup(&ctx);
2533     }
2534
2535     krb5_data_free(&result.checksum);
2536     krb5_free_keyblock(context, derived);
2537
2538     return ret;
2539 }
2540
2541 /*
2542  * these should currently be in reverse preference order.
2543  * (only relevant for !F_PSEUDO) */
2544
2545 static struct encryption_type enctype_null = {
2546     ETYPE_NULL,
2547     "null",
2548     1,
2549     1,
2550     0,
2551     &keytype_null,
2552     &checksum_none,
2553     NULL,
2554     F_DISABLED,
2555     NULL_encrypt,
2556     0,
2557     NULL
2558 };
2559 static struct encryption_type enctype_arcfour_hmac_md5 = {
2560     ETYPE_ARCFOUR_HMAC_MD5,
2561     "arcfour-hmac-md5",
2562     1,
2563     1,
2564     8,
2565     &keytype_arcfour,
2566     &checksum_hmac_md5,
2567     NULL,
2568     F_SPECIAL,
2569     ARCFOUR_encrypt,
2570     0,
2571     NULL
2572 };
2573 #ifdef DES3_OLD_ENCTYPE
2574 static struct encryption_type enctype_des3_cbc_md5 = {
2575     ETYPE_DES3_CBC_MD5,
2576     "des3-cbc-md5",
2577     8,
2578     8,
2579     8,
2580     &keytype_des3,
2581     &checksum_rsa_md5,
2582     &checksum_rsa_md5_des3,
2583     0,
2584     evp_encrypt,
2585     0,
2586     NULL
2587 };
2588 #endif
2589 static struct encryption_type enctype_des3_cbc_sha1 = {
2590     ETYPE_DES3_CBC_SHA1,
2591     "des3-cbc-sha1",
2592     8,
2593     8,
2594     8,
2595     &keytype_des3_derived,
2596     &checksum_sha1,
2597     &checksum_hmac_sha1_des3,
2598     F_DERIVED,
2599     evp_encrypt,
2600     0,
2601     NULL
2602 };
2603 #ifdef DES3_OLD_ENCTYPE
2604 static struct encryption_type enctype_old_des3_cbc_sha1 = {
2605     ETYPE_OLD_DES3_CBC_SHA1,
2606     "old-des3-cbc-sha1",
2607     8,
2608     8,
2609     8,
2610     &keytype_des3,
2611     &checksum_sha1,
2612     &checksum_hmac_sha1_des3,
2613     0,
2614     evp_encrypt,
2615     0,
2616     NULL
2617 };
2618 #endif
2619 static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2620     ETYPE_AES128_CTS_HMAC_SHA1_96,
2621     "aes128-cts-hmac-sha1-96",
2622     16,
2623     1,
2624     16,
2625     &keytype_aes128,
2626     &checksum_sha1,
2627     &checksum_hmac_sha1_aes128,
2628     F_DERIVED,
2629     evp_encrypt_cts,
2630     16,
2631     AES_PRF
2632 };
2633 static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2634     ETYPE_AES256_CTS_HMAC_SHA1_96,
2635     "aes256-cts-hmac-sha1-96",
2636     16,
2637     1,
2638     16,
2639     &keytype_aes256,
2640     &checksum_sha1,
2641     &checksum_hmac_sha1_aes256,
2642     F_DERIVED,
2643     evp_encrypt_cts,
2644     16,
2645     AES_PRF
2646 };
2647 static struct encryption_type enctype_des3_cbc_none = {
2648     ETYPE_DES3_CBC_NONE,
2649     "des3-cbc-none",
2650     8,
2651     8,
2652     0,
2653     &keytype_des3_derived,
2654     &checksum_none,
2655     NULL,
2656     F_PSEUDO,
2657     evp_encrypt,
2658     0,
2659     NULL
2660 };
2661 #ifdef HEIM_WEAK_CRYPTO
2662 static struct encryption_type enctype_des_cbc_crc = {
2663     ETYPE_DES_CBC_CRC,
2664     "des-cbc-crc",
2665     8,
2666     8,
2667     8,
2668     &keytype_des,
2669     &checksum_crc32,
2670     NULL,
2671     F_DISABLED|F_WEAK,
2672     evp_des_encrypt_key_ivec,
2673     0,
2674     NULL
2675 };
2676 static struct encryption_type enctype_des_cbc_md4 = {
2677     ETYPE_DES_CBC_MD4,
2678     "des-cbc-md4",
2679     8,
2680     8,
2681     8,
2682     &keytype_des,
2683     &checksum_rsa_md4,
2684     &checksum_rsa_md4_des,
2685     F_DISABLED|F_WEAK,
2686     evp_des_encrypt_null_ivec,
2687     0,
2688     NULL
2689 };
2690 static struct encryption_type enctype_des_cbc_md5 = {
2691     ETYPE_DES_CBC_MD5,
2692     "des-cbc-md5",
2693     8,
2694     8,
2695     8,
2696     &keytype_des,
2697     &checksum_rsa_md5,
2698     &checksum_rsa_md5_des,
2699     F_DISABLED|F_WEAK,
2700     evp_des_encrypt_null_ivec,
2701     0,
2702     NULL
2703 };
2704 static struct encryption_type enctype_des_cbc_none = {
2705     ETYPE_DES_CBC_NONE,
2706     "des-cbc-none",
2707     8,
2708     8,
2709     0,
2710     &keytype_des,
2711     &checksum_none,
2712     NULL,
2713     F_PSEUDO|F_DISABLED|F_WEAK,
2714     evp_des_encrypt_null_ivec,
2715     0,
2716     NULL
2717 };
2718 static struct encryption_type enctype_des_cfb64_none = {
2719     ETYPE_DES_CFB64_NONE,
2720     "des-cfb64-none",
2721     1,
2722     1,
2723     0,
2724     &keytype_des_old,
2725     &checksum_none,
2726     NULL,
2727     F_PSEUDO|F_DISABLED|F_WEAK,
2728     DES_CFB64_encrypt_null_ivec,
2729     0,
2730     NULL
2731 };
2732 static struct encryption_type enctype_des_pcbc_none = {
2733     ETYPE_DES_PCBC_NONE,
2734     "des-pcbc-none",
2735     8,
2736     8,
2737     0,
2738     &keytype_des_old,
2739     &checksum_none,
2740     NULL,
2741     F_PSEUDO|F_DISABLED|F_WEAK,
2742     DES_PCBC_encrypt_key_ivec,
2743     0,
2744     NULL
2745 };
2746 #endif /* HEIM_WEAK_CRYPTO */
2747
2748 static struct encryption_type *etypes[] = {
2749     &enctype_aes256_cts_hmac_sha1,
2750     &enctype_aes128_cts_hmac_sha1,
2751     &enctype_des3_cbc_sha1,
2752     &enctype_des3_cbc_none, /* used by the gss-api mech */
2753     &enctype_arcfour_hmac_md5,
2754 #ifdef DES3_OLD_ENCTYPE
2755     &enctype_des3_cbc_md5,
2756     &enctype_old_des3_cbc_sha1,
2757 #endif
2758 #ifdef HEIM_WEAK_CRYPTO
2759     &enctype_des_cbc_crc,
2760     &enctype_des_cbc_md4,
2761     &enctype_des_cbc_md5,
2762     &enctype_des_cbc_none,
2763     &enctype_des_cfb64_none,
2764     &enctype_des_pcbc_none,
2765 #endif
2766     &enctype_null
2767 };
2768
2769 static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
2770
2771
2772 static struct encryption_type *
2773 _find_enctype(krb5_enctype type)
2774 {
2775     int i;
2776     for(i = 0; i < num_etypes; i++)
2777         if(etypes[i]->type == type)
2778             return etypes[i];
2779     return NULL;
2780 }
2781
2782
2783 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2784 krb5_enctype_to_string(krb5_context context,
2785                        krb5_enctype etype,
2786                        char **string)
2787 {
2788     struct encryption_type *e;
2789     e = _find_enctype(etype);
2790     if(e == NULL) {
2791         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2792                                 N_("encryption type %d not supported", ""),
2793                                 etype);
2794         *string = NULL;
2795         return KRB5_PROG_ETYPE_NOSUPP;
2796     }
2797     *string = strdup(e->name);
2798     if(*string == NULL) {
2799         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2800         return ENOMEM;
2801     }
2802     return 0;
2803 }
2804
2805 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2806 krb5_string_to_enctype(krb5_context context,
2807                        const char *string,
2808                        krb5_enctype *etype)
2809 {
2810     int i;
2811     for(i = 0; i < num_etypes; i++)
2812         if(strcasecmp(etypes[i]->name, string) == 0){
2813             *etype = etypes[i]->type;
2814             return 0;
2815         }
2816     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2817                             N_("encryption type %s not supported", ""),
2818                             string);
2819     return KRB5_PROG_ETYPE_NOSUPP;
2820 }
2821
2822 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2823 krb5_enctype_to_keytype(krb5_context context,
2824                         krb5_enctype etype,
2825                         krb5_keytype *keytype)
2826 {
2827     struct encryption_type *e = _find_enctype(etype);
2828     if(e == NULL) {
2829         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2830                                 N_("encryption type %d not supported", ""),
2831                                 etype);
2832         return KRB5_PROG_ETYPE_NOSUPP;
2833     }
2834     *keytype = e->keytype->type; /* XXX */
2835     return 0;
2836 }
2837
2838 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2839 krb5_enctype_valid(krb5_context context,
2840                    krb5_enctype etype)
2841 {
2842     struct encryption_type *e = _find_enctype(etype);
2843     if(e == NULL) {
2844         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2845                                 N_("encryption type %d not supported", ""),
2846                                 etype);
2847         return KRB5_PROG_ETYPE_NOSUPP;
2848     }
2849     if (e->flags & F_DISABLED) {
2850         krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2851                                 N_("encryption type %s is disabled", ""),
2852                                 e->name);
2853         return KRB5_PROG_ETYPE_NOSUPP;
2854     }
2855     return 0;
2856 }
2857
2858 /**
2859  * Return the coresponding encryption type for a checksum type.
2860  *
2861  * @param context Kerberos context
2862  * @param ctype The checksum type to get the result enctype for
2863  * @param etype The returned encryption, when the matching etype is
2864  * not found, etype is set to ETYPE_NULL.
2865  *
2866  * @return Return an error code for an failure or 0 on success.
2867  * @ingroup krb5_crypto
2868  */
2869
2870
2871 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2872 krb5_cksumtype_to_enctype(krb5_context context,
2873                           krb5_cksumtype ctype,
2874                           krb5_enctype *etype)
2875 {
2876     int i;
2877
2878     *etype = ETYPE_NULL;
2879
2880     for(i = 0; i < num_etypes; i++) {
2881         if(etypes[i]->keyed_checksum &&
2882            etypes[i]->keyed_checksum->type == ctype)
2883             {
2884                 *etype = etypes[i]->type;
2885                 return 0;
2886             }
2887     }
2888
2889     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2890                             N_("checksum type %d not supported", ""),
2891                             (int)ctype);
2892     return KRB5_PROG_SUMTYPE_NOSUPP;
2893 }
2894
2895
2896 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2897 krb5_cksumtype_valid(krb5_context context,
2898                      krb5_cksumtype ctype)
2899 {
2900     struct checksum_type *c = _find_checksum(ctype);
2901     if (c == NULL) {
2902         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2903                                 N_("checksum type %d not supported", ""),
2904                                 ctype);
2905         return KRB5_PROG_SUMTYPE_NOSUPP;
2906     }
2907     if (c->flags & F_DISABLED) {
2908         krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
2909                                 N_("checksum type %s is disabled", ""),
2910                                 c->name);
2911         return KRB5_PROG_SUMTYPE_NOSUPP;
2912     }
2913     return 0;
2914 }
2915
2916
2917 static krb5_boolean
2918 derived_crypto(krb5_context context,
2919                krb5_crypto crypto)
2920 {
2921     return (crypto->et->flags & F_DERIVED) != 0;
2922 }
2923
2924 static krb5_boolean
2925 special_crypto(krb5_context context,
2926                krb5_crypto crypto)
2927 {
2928     return (crypto->et->flags & F_SPECIAL) != 0;
2929 }
2930
2931 #define CHECKSUMSIZE(C) ((C)->checksumsize)
2932 #define CHECKSUMTYPE(C) ((C)->type)
2933
2934 static krb5_error_code
2935 encrypt_internal_derived(krb5_context context,
2936                          krb5_crypto crypto,
2937                          unsigned usage,
2938                          const void *data,
2939                          size_t len,
2940                          krb5_data *result,
2941                          void *ivec)
2942 {
2943     size_t sz, block_sz, checksum_sz, total_sz;
2944     Checksum cksum;
2945     unsigned char *p, *q;
2946     krb5_error_code ret;
2947     struct key_data *dkey;
2948     const struct encryption_type *et = crypto->et;
2949
2950     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2951
2952     sz = et->confoundersize + len;
2953     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
2954     total_sz = block_sz + checksum_sz;
2955     p = calloc(1, total_sz);
2956     if(p == NULL) {
2957         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2958         return ENOMEM;
2959     }
2960
2961     q = p;
2962     krb5_generate_random_block(q, et->confoundersize); /* XXX */
2963     q += et->confoundersize;
2964     memcpy(q, data, len);
2965
2966     ret = create_checksum(context,
2967                           et->keyed_checksum,
2968                           crypto,
2969                           INTEGRITY_USAGE(usage),
2970                           p,
2971                           block_sz,
2972                           &cksum);
2973     if(ret == 0 && cksum.checksum.length != checksum_sz) {
2974         free_Checksum (&cksum);
2975         krb5_clear_error_message (context);
2976         ret = KRB5_CRYPTO_INTERNAL;
2977     }
2978     if(ret)
2979         goto fail;
2980     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2981     free_Checksum (&cksum);
2982     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2983     if(ret)
2984         goto fail;
2985     ret = _key_schedule(context, dkey);
2986     if(ret)
2987         goto fail;
2988     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
2989     if (ret)
2990         goto fail;
2991     result->data = p;
2992     result->length = total_sz;
2993     return 0;
2994  fail:
2995     memset(p, 0, total_sz);
2996     free(p);
2997     return ret;
2998 }
2999
3000
3001 static krb5_error_code
3002 encrypt_internal(krb5_context context,
3003                  krb5_crypto crypto,
3004                  const void *data,
3005                  size_t len,
3006                  krb5_data *result,
3007                  void *ivec)
3008 {
3009     size_t sz, block_sz, checksum_sz;
3010     Checksum cksum;
3011     unsigned char *p, *q;
3012     krb5_error_code ret;
3013     const struct encryption_type *et = crypto->et;
3014
3015     checksum_sz = CHECKSUMSIZE(et->checksum);
3016
3017     sz = et->confoundersize + checksum_sz + len;
3018     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3019     p = calloc(1, block_sz);
3020     if(p == NULL) {
3021         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3022         return ENOMEM;
3023     }
3024
3025     q = p;
3026     krb5_generate_random_block(q, et->confoundersize); /* XXX */
3027     q += et->confoundersize;
3028     memset(q, 0, checksum_sz);
3029     q += checksum_sz;
3030     memcpy(q, data, len);
3031
3032     ret = create_checksum(context,
3033                           et->checksum,
3034                           crypto,
3035                           0,
3036                           p,
3037                           block_sz,
3038                           &cksum);
3039     if(ret == 0 && cksum.checksum.length != checksum_sz) {
3040         krb5_clear_error_message (context);
3041         free_Checksum(&cksum);
3042         ret = KRB5_CRYPTO_INTERNAL;
3043     }
3044     if(ret)
3045         goto fail;
3046     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
3047     free_Checksum(&cksum);
3048     ret = _key_schedule(context, &crypto->key);
3049     if(ret)
3050         goto fail;
3051     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
3052     if (ret) {
3053         memset(p, 0, block_sz);
3054         free(p);
3055         return ret;
3056     }
3057     result->data = p;
3058     result->length = block_sz;
3059     return 0;
3060  fail:
3061     memset(p, 0, block_sz);
3062     free(p);
3063     return ret;
3064 }
3065
3066 static krb5_error_code
3067 encrypt_internal_special(krb5_context context,
3068                          krb5_crypto crypto,
3069                          int usage,
3070                          const void *data,
3071                          size_t len,
3072                          krb5_data *result,
3073                          void *ivec)
3074 {
3075     struct encryption_type *et = crypto->et;
3076     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3077     size_t sz = len + cksum_sz + et->confoundersize;
3078     char *tmp, *p;
3079     krb5_error_code ret;
3080
3081     tmp = malloc (sz);
3082     if (tmp == NULL) {
3083         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3084         return ENOMEM;
3085     }
3086     p = tmp;
3087     memset (p, 0, cksum_sz);
3088     p += cksum_sz;
3089     krb5_generate_random_block(p, et->confoundersize);
3090     p += et->confoundersize;
3091     memcpy (p, data, len);
3092     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
3093     if (ret) {
3094         memset(tmp, 0, sz);
3095         free(tmp);
3096         return ret;
3097     }
3098     result->data   = tmp;
3099     result->length = sz;
3100     return 0;
3101 }
3102
3103 static krb5_error_code
3104 decrypt_internal_derived(krb5_context context,
3105                          krb5_crypto crypto,
3106                          unsigned usage,
3107                          void *data,
3108                          size_t len,
3109                          krb5_data *result,
3110                          void *ivec)
3111 {
3112     size_t checksum_sz;
3113     Checksum cksum;
3114     unsigned char *p;
3115     krb5_error_code ret;
3116     struct key_data *dkey;
3117     struct encryption_type *et = crypto->et;
3118     unsigned long l;
3119
3120     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
3121     if (len < checksum_sz + et->confoundersize) {
3122         krb5_set_error_message(context, KRB5_BAD_MSIZE,
3123                                N_("Encrypted data shorter then "
3124                                   "checksum + confunder", ""));
3125         return KRB5_BAD_MSIZE;
3126     }
3127
3128     if (((len - checksum_sz) % et->padsize) != 0) {
3129         krb5_clear_error_message(context);
3130         return KRB5_BAD_MSIZE;
3131     }
3132
3133     p = malloc(len);
3134     if(len != 0 && p == NULL) {
3135         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3136         return ENOMEM;
3137     }
3138     memcpy(p, data, len);
3139
3140     len -= checksum_sz;
3141
3142     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3143     if(ret) {
3144         free(p);
3145         return ret;
3146     }
3147     ret = _key_schedule(context, dkey);
3148     if(ret) {
3149         free(p);
3150         return ret;
3151     }
3152     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3153     if (ret) {
3154         free(p);
3155         return ret;
3156     }
3157
3158     cksum.checksum.data   = p + len;
3159     cksum.checksum.length = checksum_sz;
3160     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
3161
3162     ret = verify_checksum(context,
3163                           crypto,
3164                           INTEGRITY_USAGE(usage),
3165                           p,
3166                           len,
3167                           &cksum);
3168     if(ret) {
3169         free(p);
3170         return ret;
3171     }
3172     l = len - et->confoundersize;
3173     memmove(p, p + et->confoundersize, l);
3174     result->data = realloc(p, l);
3175     if(result->data == NULL && l != 0) {
3176         free(p);
3177         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3178         return ENOMEM;
3179     }
3180     result->length = l;
3181     return 0;
3182 }
3183
3184 static krb5_error_code
3185 decrypt_internal(krb5_context context,
3186                  krb5_crypto crypto,
3187                  void *data,
3188                  size_t len,
3189                  krb5_data *result,
3190                  void *ivec)
3191 {
3192     krb5_error_code ret;
3193     unsigned char *p;
3194     Checksum cksum;
3195     size_t checksum_sz, l;
3196     struct encryption_type *et = crypto->et;
3197
3198     if ((len % et->padsize) != 0) {
3199         krb5_clear_error_message(context);
3200         return KRB5_BAD_MSIZE;
3201     }
3202     checksum_sz = CHECKSUMSIZE(et->checksum);
3203     if (len < checksum_sz + et->confoundersize) {
3204         krb5_set_error_message(context, KRB5_BAD_MSIZE,
3205                                N_("Encrypted data shorter then "
3206                                   "checksum + confunder", ""));
3207         return KRB5_BAD_MSIZE;
3208     }
3209
3210     p = malloc(len);
3211     if(len != 0 && p == NULL) {
3212         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3213         return ENOMEM;
3214     }
3215     memcpy(p, data, len);
3216
3217     ret = _key_schedule(context, &crypto->key);
3218     if(ret) {
3219         free(p);
3220         return ret;
3221     }
3222     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
3223     if (ret) {
3224         free(p);
3225         return ret;
3226     }
3227     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
3228     if(ret) {
3229         free(p);
3230         return ret;
3231     }
3232     memset(p + et->confoundersize, 0, checksum_sz);
3233     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
3234     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
3235     free_Checksum(&cksum);
3236     if(ret) {
3237         free(p);
3238         return ret;
3239     }
3240     l = len - et->confoundersize - checksum_sz;
3241     memmove(p, p + et->confoundersize + checksum_sz, l);
3242     result->data = realloc(p, l);
3243     if(result->data == NULL && l != 0) {
3244         free(p);
3245         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3246         return ENOMEM;
3247     }
3248     result->length = l;
3249     return 0;
3250 }
3251
3252 static krb5_error_code
3253 decrypt_internal_special(krb5_context context,
3254                          krb5_crypto crypto,
3255                          int usage,
3256                          void *data,
3257                          size_t len,
3258                          krb5_data *result,
3259                          void *ivec)
3260 {
3261     struct encryption_type *et = crypto->et;
3262     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
3263     size_t sz = len - cksum_sz - et->confoundersize;
3264     unsigned char *p;
3265     krb5_error_code ret;
3266
3267     if ((len % et->padsize) != 0) {
3268         krb5_clear_error_message(context);
3269         return KRB5_BAD_MSIZE;
3270     }
3271     if (len < cksum_sz + et->confoundersize) {
3272         krb5_set_error_message(context, KRB5_BAD_MSIZE,
3273                                N_("Encrypted data shorter then "
3274                                   "checksum + confunder", ""));
3275         return KRB5_BAD_MSIZE;
3276     }
3277
3278     p = malloc (len);
3279     if (p == NULL) {
3280         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3281         return ENOMEM;
3282     }
3283     memcpy(p, data, len);
3284
3285     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
3286     if (ret) {
3287         free(p);
3288         return ret;
3289     }
3290
3291     memmove (p, p + cksum_sz + et->confoundersize, sz);
3292     result->data = realloc(p, sz);
3293     if(result->data == NULL && sz != 0) {
3294         free(p);
3295         krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
3296         return ENOMEM;
3297     }
3298     result->length = sz;
3299     return 0;
3300 }
3301
3302 static krb5_crypto_iov *
3303 find_iv(krb5_crypto_iov *data, int num_data, int type)
3304 {
3305     int i;
3306     for (i = 0; i < num_data; i++)
3307         if (data[i].flags == type)
3308             return &data[i];
3309     return NULL;
3310 }
3311
3312 /**
3313  * Inline encrypt a kerberos message
3314  *
3315  * @param context Kerberos context
3316  * @param crypto Kerberos crypto context
3317  * @param usage Key usage for this buffer
3318  * @param data array of buffers to process
3319  * @param num_data length of array
3320  * @param ivec initial cbc/cts vector
3321  *
3322  * @return Return an error code or 0.
3323  * @ingroup krb5_crypto
3324  *
3325  * Kerberos encrypted data look like this:
3326  *
3327  * 1. KRB5_CRYPTO_TYPE_HEADER
3328  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
3329  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
3330  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
3331  *    commonly used headers and trailers.
3332  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
3333  * 4. KRB5_CRYPTO_TYPE_TRAILER
3334  */
3335
3336 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3337 krb5_encrypt_iov_ivec(krb5_context context,
3338                       krb5_crypto crypto,
3339                       unsigned usage,
3340                       krb5_crypto_iov *data,
3341                       int num_data,
3342                       void *ivec)
3343 {
3344     size_t headersz, trailersz, len;
3345     int i;
3346     size_t sz, block_sz, pad_sz;
3347     Checksum cksum;
3348     unsigned char *p, *q;
3349     krb5_error_code ret;
3350     struct key_data *dkey;
3351     const struct encryption_type *et = crypto->et;
3352     krb5_crypto_iov *tiv, *piv, *hiv;
3353
3354     if (num_data < 0) {
3355         krb5_clear_error_message(context);
3356         return KRB5_CRYPTO_INTERNAL;
3357     }
3358
3359     if(!derived_crypto(context, crypto)) {
3360         krb5_clear_error_message(context);
3361         return KRB5_CRYPTO_INTERNAL;
3362     }
3363
3364     headersz = et->confoundersize;
3365     trailersz = CHECKSUMSIZE(et->keyed_checksum);
3366
3367     for (len = 0, i = 0; i < num_data; i++) {
3368         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3369             continue;
3370         len += data[i].data.length;
3371     }
3372
3373     sz = headersz + len;
3374     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
3375
3376     pad_sz = block_sz - sz;
3377
3378     /* header */
3379
3380     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3381     if (hiv == NULL || hiv->data.length != headersz)
3382         return KRB5_BAD_MSIZE;
3383
3384     krb5_generate_random_block(hiv->data.data, hiv->data.length);
3385
3386     /* padding */
3387     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
3388     /* its ok to have no TYPE_PADDING if there is no padding */
3389     if (piv == NULL && pad_sz != 0)
3390         return KRB5_BAD_MSIZE;
3391     if (piv) {
3392         if (piv->data.length < pad_sz)
3393             return KRB5_BAD_MSIZE;
3394         piv->data.length = pad_sz;
3395         if (pad_sz)
3396             memset(piv->data.data, pad_sz, pad_sz);
3397         else
3398             piv = NULL;
3399     }
3400
3401     /* trailer */
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
3406     /*
3407      * XXX replace with EVP_Sign? at least make create_checksum an iov
3408      * function.
3409      * XXX CTS EVP is broken, can't handle multi buffers :(
3410      */
3411
3412     len = block_sz;
3413     for (i = 0; i < num_data; i++) {
3414         if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3415             continue;
3416         len += data[i].data.length;
3417     }
3418
3419     p = q = malloc(len);
3420
3421     memcpy(q, hiv->data.data, hiv->data.length);
3422     q += hiv->data.length;
3423     for (i = 0; i < num_data; i++) {
3424         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
3425             data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3426             continue;
3427         memcpy(q, data[i].data.data, data[i].data.length);
3428         q += data[i].data.length;
3429     }
3430     if (piv)
3431         memset(q, 0, piv->data.length);
3432
3433     ret = create_checksum(context,
3434                           et->keyed_checksum,
3435                           crypto,
3436                           INTEGRITY_USAGE(usage),
3437                           p,
3438                           len,
3439                           &cksum);
3440     free(p);
3441     if(ret == 0 && cksum.checksum.length != trailersz) {
3442         free_Checksum (&cksum);
3443         krb5_clear_error_message (context);
3444         ret = KRB5_CRYPTO_INTERNAL;
3445     }
3446     if(ret)
3447         return ret;
3448
3449     /* save cksum at end */
3450     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
3451     free_Checksum (&cksum);
3452
3453     /* XXX replace with EVP_Cipher */
3454     p = q = malloc(block_sz);
3455     if(p == NULL)
3456         return ENOMEM;
3457
3458     memcpy(q, hiv->data.data, hiv->data.length);
3459     q += hiv->data.length;
3460
3461     for (i = 0; i < num_data; i++) {
3462         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3463             continue;
3464         memcpy(q, data[i].data.data, data[i].data.length);
3465         q += data[i].data.length;
3466     }
3467     if (piv)
3468         memset(q, 0, piv->data.length);
3469
3470
3471     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3472     if(ret) {
3473         free(p);
3474         return ret;
3475     }
3476     ret = _key_schedule(context, dkey);
3477     if(ret) {
3478         free(p);
3479         return ret;
3480     }
3481
3482     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
3483     if (ret) {
3484         free(p);
3485         return ret;
3486     }
3487
3488     /* now copy data back to buffers */
3489     q = p;
3490
3491     memcpy(hiv->data.data, q, hiv->data.length);
3492     q += hiv->data.length;
3493
3494     for (i = 0; i < num_data; i++) {
3495         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3496             continue;
3497         memcpy(data[i].data.data, q, data[i].data.length);
3498         q += data[i].data.length;
3499     }
3500     if (piv)
3501         memcpy(piv->data.data, q, pad_sz);
3502
3503     free(p);
3504
3505     return ret;
3506 }
3507
3508 /**
3509  * Inline decrypt a Kerberos message.
3510  *
3511  * @param context Kerberos context
3512  * @param crypto Kerberos crypto context
3513  * @param usage Key usage for this buffer
3514  * @param data array of buffers to process
3515  * @param num_data length of array
3516  * @param ivec initial cbc/cts vector
3517  *
3518  * @return Return an error code or 0.
3519  * @ingroup krb5_crypto
3520  *
3521  * 1. KRB5_CRYPTO_TYPE_HEADER
3522  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
3523  *  any order, however the receiver have to aware of the
3524  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
3525  *  protocol headers and trailers. The output data will be of same
3526  *  size as the input data or shorter.
3527  */
3528
3529 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
3530 krb5_decrypt_iov_ivec(krb5_context context,
3531                       krb5_crypto crypto,
3532                       unsigned usage,
3533                       krb5_crypto_iov *data,
3534                       unsigned int num_data,
3535                       void *ivec)
3536 {
3537     unsigned int i;
3538     size_t headersz, trailersz, len;
3539     Checksum cksum;
3540     unsigned char *p, *q;
3541     krb5_error_code ret;
3542     struct key_data *dkey;
3543     struct encryption_type *et = crypto->et;
3544     krb5_crypto_iov *tiv, *hiv;
3545
3546     if (num_data < 0) {
3547         krb5_clear_error_message(context);
3548         return KRB5_CRYPTO_INTERNAL;
3549     }
3550
3551     if(!derived_crypto(context, crypto)) {
3552         krb5_clear_error_message(context);
3553         return KRB5_CRYPTO_INTERNAL;
3554     }
3555
3556     headersz = et->confoundersize;
3557
3558     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
3559     if (hiv == NULL || hiv->data.length != headersz)
3560         return KRB5_BAD_MSIZE;
3561
3562     /* trailer */
3563     trailersz = CHECKSUMSIZE(et->keyed_checksum);
3564
3565     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
3566     if (tiv->data.length != trailersz)
3567         return KRB5_BAD_MSIZE;
3568
3569     /* Find length of data we will decrypt */
3570
3571     len = headersz;
3572     for (i = 0; i < num_data; i++) {
3573         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3574             continue;
3575         len += data[i].data.length;
3576     }
3577
3578     if ((len % et->padsize) != 0) {
3579         krb5_clear_error_message(context);
3580         return KRB5_BAD_MSIZE;
3581     }
3582
3583     /* XXX replace with EVP_Cipher */
3584
3585     p = q = malloc(len);
3586     if (p == NULL)
3587         return ENOMEM;
3588
3589     memcpy(q, hiv->data.data, hiv->data.length);
3590     q += hiv->data.length;
3591
3592     for (i = 0; i < num_data; i++) {
3593         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3594             continue;
3595         memcpy(q, data[i].data.data, data[i].data.length);
3596         q += data[i].data.length;
3597     }
3598
3599     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
3600     if(ret) {
3601         free(p);
3602         return ret;
3603     }
3604     ret = _key_schedule(context, dkey);
3605     if(ret) {
3606         free(p);
3607         return ret;
3608     }
3609
3610     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
3611     if (ret) {
3612         free(p);
3613         return ret;
3614     }
3615
3616     /* copy data back to buffers */
3617     memcpy(hiv->data.data, p, hiv->data.length);
3618     q = p + hiv->data.length;
3619     for (i = 0; i < num_data; i++) {
3620         if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
3621             continue;
3622         memcpy(data[i].data.data, q, data[i].data.length);
3623         q += data[i].data.length;
3624     }
3625
3626     free(p);
3627
3628     /* check signature */
3629     for (i = 0; i < num_data; i++) {
3630         if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
3631             continue;
3632         len += data[i].data.length;