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