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