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