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