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