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