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