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