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