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