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