crypto.c revision 72448
1/*
2 * Copyright (c) 1997 - 2001 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,v 1.29 2000/01/25 23:06:55 assar Exp $");
36/* RCSID("$FreeBSD: head/crypto/heimdal/lib/krb5/crypto.c 72448 2001-02-13 16:52:56Z assar $"); */
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
71struct salt_type {
72    krb5_salttype type;
73    const char *name;
74    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
75				     krb5_salt, krb5_keyblock*);
76};
77
78struct key_type {
79    krb5_keytype type; /* XXX */
80    const char *name;
81    size_t bits;
82    size_t size;
83    size_t schedule_size;
84#if 0
85    krb5_enctype best_etype;
86#endif
87    void (*random_key)(krb5_context, krb5_keyblock*);
88    void (*schedule)(krb5_context, struct key_data *);
89    struct salt_type *string_to_key;
90};
91
92struct checksum_type {
93    krb5_cksumtype type;
94    const char *name;
95    size_t blocksize;
96    size_t checksumsize;
97    unsigned flags;
98    void (*checksum)(krb5_context context,
99		     struct key_data *key,
100		     const void *buf, size_t len,
101		     unsigned usage,
102		     Checksum *csum);
103    krb5_error_code (*verify)(krb5_context context,
104			      struct key_data *key,
105			      const void *buf, size_t len,
106			      unsigned usage,
107			      Checksum *csum);
108};
109
110struct encryption_type {
111    krb5_enctype type;
112    const char *name;
113    size_t blocksize;
114    size_t confoundersize;
115    struct key_type *keytype;
116    struct checksum_type *cksumtype;
117    struct checksum_type *keyed_checksum;
118    unsigned flags;
119    krb5_error_code (*encrypt)(struct key_data *key,
120			       void *data, size_t len,
121			       krb5_boolean encrypt,
122			       int usage,
123			       void *ivec);
124};
125
126#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
127#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
128#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
129
130static struct checksum_type *_find_checksum(krb5_cksumtype type);
131static struct encryption_type *_find_enctype(krb5_enctype type);
132static struct key_type *_find_keytype(krb5_keytype type);
133static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
134					unsigned, struct key_data**);
135static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
136
137/************************************************************
138 *                                                          *
139 ************************************************************/
140
141static void
142DES_random_key(krb5_context context,
143	       krb5_keyblock *key)
144{
145    des_cblock *k = key->keyvalue.data;
146    do {
147	krb5_generate_random_block(k, sizeof(des_cblock));
148	des_set_odd_parity(k);
149    } while(des_is_weak_key(k));
150}
151
152static void
153DES_schedule(krb5_context context,
154	     struct key_data *key)
155{
156    des_set_key(key->key->keyvalue.data, key->schedule->data);
157}
158
159static krb5_error_code
160DES_string_to_key(krb5_context context,
161		  krb5_enctype enctype,
162		  krb5_data password,
163		  krb5_salt salt,
164		  krb5_keyblock *key)
165{
166    char *s;
167    size_t len;
168    des_cblock tmp;
169
170    len = password.length + salt.saltvalue.length + 1;
171    s = malloc(len);
172    if(s == NULL)
173	return ENOMEM;
174    memcpy(s, password.data, password.length);
175    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
176    s[len - 1] = '\0';
177    des_string_to_key(s, &tmp);
178    key->keytype = enctype;
179    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
180    memset(&tmp, 0, sizeof(tmp));
181    memset(s, 0, len);
182    free(s);
183    return 0;
184}
185
186/* This defines the Andrew string_to_key function.  It accepts a password
187 * string as input and converts its via a one-way encryption algorithm to a DES
188 * encryption key.  It is compatible with the original Andrew authentication
189 * service password database.
190 */
191
192/*
193 * Short passwords, i.e 8 characters or less.
194 */
195static void
196DES_AFS3_CMU_string_to_key (krb5_data pw,
197			    krb5_data cell,
198			    des_cblock *key)
199{
200    char  password[8+1];	/* crypt is limited to 8 chars anyway */
201    int   i;
202
203    for(i = 0; i < 8; i++) {
204	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
205		 ((i < cell.length) ?
206		  tolower(((unsigned char*)cell.data)[i]) : 0);
207	password[i] = c ? c : 'X';
208    }
209    password[8] = '\0';
210
211    memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
212
213    /* parity is inserted into the LSB so left shift each byte up one
214       bit. This allows ascii characters with a zero MSB to retain as
215       much significance as possible. */
216    for (i = 0; i < sizeof(des_cblock); i++)
217	((unsigned char*)key)[i] <<= 1;
218    des_set_odd_parity (key);
219}
220
221/*
222 * Long passwords, i.e 9 characters or more.
223 */
224static void
225DES_AFS3_Transarc_string_to_key (krb5_data pw,
226				 krb5_data cell,
227				 des_cblock *key)
228{
229    des_key_schedule schedule;
230    des_cblock temp_key;
231    des_cblock ivec;
232    char password[512];
233    size_t passlen;
234
235    memcpy(password, pw.data, min(pw.length, sizeof(password)));
236    if(pw.length < sizeof(password)) {
237	int len = min(cell.length, sizeof(password) - pw.length);
238	int i;
239
240	memcpy(password + pw.length, cell.data, len);
241	for (i = pw.length; i < pw.length + len; ++i)
242	    password[i] = tolower((unsigned char)password[i]);
243    }
244    passlen = min(sizeof(password), pw.length + cell.length);
245    memcpy(&ivec, "kerberos", 8);
246    memcpy(&temp_key, "kerberos", 8);
247    des_set_odd_parity (&temp_key);
248    des_set_key (&temp_key, schedule);
249    des_cbc_cksum ((des_cblock *)password, &ivec, passlen, schedule, &ivec);
250
251    memcpy(&temp_key, &ivec, 8);
252    des_set_odd_parity (&temp_key);
253    des_set_key (&temp_key, schedule);
254    des_cbc_cksum ((des_cblock *)password, key, passlen, schedule, &ivec);
255    memset(&schedule, 0, sizeof(schedule));
256    memset(&temp_key, 0, sizeof(temp_key));
257    memset(&ivec, 0, sizeof(ivec));
258    memset(password, 0, sizeof(password));
259
260    des_set_odd_parity (key);
261}
262
263static krb5_error_code
264DES_AFS3_string_to_key(krb5_context context,
265		       krb5_enctype enctype,
266		       krb5_data password,
267		       krb5_salt salt,
268		       krb5_keyblock *key)
269{
270    des_cblock tmp;
271    if(password.length > 8)
272	DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
273    else
274	DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
275    key->keytype = enctype;
276    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
277    memset(&key, 0, sizeof(key));
278    return 0;
279}
280
281static void
282DES3_random_key(krb5_context context,
283		krb5_keyblock *key)
284{
285    des_cblock *k = key->keyvalue.data;
286    do {
287	krb5_generate_random_block(k, 3 * sizeof(des_cblock));
288	des_set_odd_parity(&k[0]);
289	des_set_odd_parity(&k[1]);
290	des_set_odd_parity(&k[2]);
291    } while(des_is_weak_key(&k[0]) ||
292	    des_is_weak_key(&k[1]) ||
293	    des_is_weak_key(&k[2]));
294}
295
296static void
297DES3_schedule(krb5_context context,
298	      struct key_data *key)
299{
300    des_cblock *k = key->key->keyvalue.data;
301    des_key_schedule *s = key->schedule->data;
302    des_set_key(&k[0], s[0]);
303    des_set_key(&k[1], s[1]);
304    des_set_key(&k[2], s[2]);
305}
306
307/*
308 * A = A xor B. A & B are 8 bytes.
309 */
310
311static void
312xor (des_cblock *key, const unsigned char *b)
313{
314    unsigned char *a = (unsigned char*)key;
315    a[0] ^= b[0];
316    a[1] ^= b[1];
317    a[2] ^= b[2];
318    a[3] ^= b[3];
319    a[4] ^= b[4];
320    a[5] ^= b[5];
321    a[6] ^= b[6];
322    a[7] ^= b[7];
323}
324
325static krb5_error_code
326DES3_string_to_key(krb5_context context,
327		   krb5_enctype enctype,
328		   krb5_data password,
329		   krb5_salt salt,
330		   krb5_keyblock *key)
331{
332    char *str;
333    size_t len;
334    unsigned char tmp[24];
335    des_cblock keys[3];
336
337    len = password.length + salt.saltvalue.length;
338    str = malloc(len);
339    if(len != 0 && str == NULL)
340	return ENOMEM;
341    memcpy(str, password.data, password.length);
342    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
343    {
344	des_cblock ivec;
345	des_key_schedule s[3];
346	int i;
347
348	_krb5_n_fold(str, len, tmp, 24);
349
350	for(i = 0; i < 3; i++){
351	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
352	    des_set_odd_parity(keys + i);
353	    if(des_is_weak_key(keys + i))
354		xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
355	    des_set_key(keys + i, s[i]);
356	}
357	memset(&ivec, 0, sizeof(ivec));
358	des_ede3_cbc_encrypt((des_cblock *)tmp,
359			     (des_cblock *)tmp, sizeof(tmp),
360			     s[0], s[1], s[2], &ivec, DES_ENCRYPT);
361	memset(s, 0, sizeof(s));
362	memset(&ivec, 0, sizeof(ivec));
363	for(i = 0; i < 3; i++){
364	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
365	    des_set_odd_parity(keys + i);
366	    if(des_is_weak_key(keys + i))
367		xor(keys + i, (unsigned char*)"\0\0\0\0\0\0\0\xf0");
368	}
369	memset(tmp, 0, sizeof(tmp));
370    }
371    key->keytype = enctype;
372    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
373    memset(keys, 0, sizeof(keys));
374    memset(str, 0, len);
375    free(str);
376    return 0;
377}
378
379static krb5_error_code
380DES3_string_to_key_derived(krb5_context context,
381			   krb5_enctype enctype,
382			   krb5_data password,
383			   krb5_salt salt,
384			   krb5_keyblock *key)
385{
386    krb5_error_code ret;
387    size_t len = password.length + salt.saltvalue.length;
388    char *s;
389
390    s = malloc(len);
391    if(len != 0 && s == NULL)
392	return ENOMEM;
393    memcpy(s, password.data, password.length);
394    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
395    ret = krb5_string_to_key_derived(context,
396				     s,
397				     len,
398				     enctype,
399				     key);
400    memset(s, 0, len);
401    free(s);
402    return ret;
403}
404
405/*
406 * ARCFOUR
407 */
408
409static void
410ARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
411{
412    krb5_generate_random_block (key->keyvalue.data,
413				key->keyvalue.length);
414}
415
416static void
417ARCFOUR_schedule(krb5_context context, struct key_data *kd)
418{
419    RC4_set_key (kd->schedule->data,
420		 kd->key->keyvalue.length, kd->key->keyvalue.data);
421}
422
423static krb5_error_code
424ARCFOUR_string_to_key(krb5_context context,
425		  krb5_enctype enctype,
426		  krb5_data password,
427		  krb5_salt salt,
428		  krb5_keyblock *key)
429{
430    char *s, *p;
431    size_t len;
432    int i;
433    MD4_CTX m;
434
435    len = 2 * password.length;
436    s = malloc (len);
437    if (len != 0 && s == NULL)
438	return ENOMEM;
439    for (p = s, i = 0; i < password.length; ++i) {
440	*p++ = ((char *)password.data)[i];
441	*p++ = 0;
442    }
443    MD4_Init (&m);
444    MD4_Update (&m, s, len);
445    key->keytype = enctype;
446    krb5_data_alloc (&key->keyvalue, 16);
447    MD4_Final (key->keyvalue.data, &m);
448    memset (s, 0, len);
449    free (s);
450    return 0;
451}
452
453extern struct salt_type des_salt[],
454    des3_salt[], des3_salt_derived[], arcfour_salt[];
455
456struct key_type keytype_null = {
457    KEYTYPE_NULL,
458    "null",
459    0,
460    0,
461    0,
462    NULL,
463    NULL,
464    NULL
465};
466
467struct key_type keytype_des = {
468    KEYTYPE_DES,
469    "des",
470    56,
471    sizeof(des_cblock),
472    sizeof(des_key_schedule),
473    DES_random_key,
474    DES_schedule,
475    des_salt
476};
477
478struct key_type keytype_des3 = {
479    KEYTYPE_DES3,
480    "des3",
481    168,
482    3 * sizeof(des_cblock),
483    3 * sizeof(des_key_schedule),
484    DES3_random_key,
485    DES3_schedule,
486    des3_salt
487};
488
489struct key_type keytype_des3_derived = {
490    KEYTYPE_DES3,
491    "des3",
492    168,
493    3 * sizeof(des_cblock),
494    3 * sizeof(des_key_schedule),
495    DES3_random_key,
496    DES3_schedule,
497    des3_salt_derived
498};
499
500struct key_type keytype_arcfour = {
501    KEYTYPE_ARCFOUR,
502    "arcfour",
503    128,
504    16,
505    sizeof(RC4_KEY),
506    ARCFOUR_random_key,
507    ARCFOUR_schedule,
508    arcfour_salt
509};
510
511struct key_type *keytypes[] = {
512    &keytype_null,
513    &keytype_des,
514    &keytype_des3_derived,
515    &keytype_des3,
516    &keytype_arcfour
517};
518
519static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
520
521static struct key_type *
522_find_keytype(krb5_keytype type)
523{
524    int i;
525    for(i = 0; i < num_keytypes; i++)
526	if(keytypes[i]->type == type)
527	    return keytypes[i];
528    return NULL;
529}
530
531
532struct salt_type des_salt[] = {
533    {
534	KRB5_PW_SALT,
535	"pw-salt",
536	DES_string_to_key
537    },
538    {
539	KRB5_AFS3_SALT,
540	"afs3-salt",
541	DES_AFS3_string_to_key
542    },
543    { 0 }
544};
545
546struct salt_type des3_salt[] = {
547    {
548	KRB5_PW_SALT,
549	"pw-salt",
550	DES3_string_to_key
551    },
552    { 0 }
553};
554
555struct salt_type des3_salt_derived[] = {
556    {
557	KRB5_PW_SALT,
558	"pw-salt",
559	DES3_string_to_key_derived
560    },
561    { 0 }
562};
563
564struct salt_type arcfour_salt[] = {
565    {
566	KRB5_PW_SALT,
567	"pw-salt",
568	ARCFOUR_string_to_key
569    },
570    { 0 }
571};
572
573krb5_error_code
574krb5_salttype_to_string (krb5_context context,
575			 krb5_enctype etype,
576			 krb5_salttype stype,
577			 char **string)
578{
579    struct encryption_type *e;
580    struct salt_type *st;
581
582    e = _find_enctype (etype);
583    if (e == NULL)
584	return KRB5_PROG_ETYPE_NOSUPP;
585    for (st = e->keytype->string_to_key; st && st->type; st++) {
586	if (st->type == stype) {
587	    *string = strdup (st->name);
588	    if (*string == NULL)
589		return ENOMEM;
590	    return 0;
591	}
592    }
593    return HEIM_ERR_SALTTYPE_NOSUPP;
594}
595
596krb5_error_code
597krb5_string_to_salttype (krb5_context context,
598			 krb5_enctype etype,
599			 const char *string,
600			 krb5_salttype *salttype)
601{
602    struct encryption_type *e;
603    struct salt_type *st;
604
605    e = _find_enctype (etype);
606    if (e == NULL)
607	return KRB5_PROG_ETYPE_NOSUPP;
608    for (st = e->keytype->string_to_key; st && st->type; st++) {
609	if (strcasecmp (st->name, string) == 0) {
610	    *salttype = st->type;
611	    return 0;
612	}
613    }
614    return HEIM_ERR_SALTTYPE_NOSUPP;
615}
616
617krb5_error_code
618krb5_get_pw_salt(krb5_context context,
619		 krb5_const_principal principal,
620		 krb5_salt *salt)
621{
622    size_t len;
623    int i;
624    krb5_error_code ret;
625    char *p;
626
627    salt->salttype = KRB5_PW_SALT;
628    len = strlen(principal->realm);
629    for (i = 0; i < principal->name.name_string.len; ++i)
630	len += strlen(principal->name.name_string.val[i]);
631    ret = krb5_data_alloc (&salt->saltvalue, len);
632    if (ret)
633	return ret;
634    p = salt->saltvalue.data;
635    memcpy (p, principal->realm, strlen(principal->realm));
636    p += strlen(principal->realm);
637    for (i = 0; i < principal->name.name_string.len; ++i) {
638	memcpy (p,
639		principal->name.name_string.val[i],
640		strlen(principal->name.name_string.val[i]));
641	p += strlen(principal->name.name_string.val[i]);
642    }
643    return 0;
644}
645
646krb5_error_code
647krb5_free_salt(krb5_context context,
648	       krb5_salt salt)
649{
650    krb5_data_free(&salt.saltvalue);
651    return 0;
652}
653
654krb5_error_code
655krb5_string_to_key_data (krb5_context context,
656			 krb5_enctype enctype,
657			 krb5_data password,
658			 krb5_principal principal,
659			 krb5_keyblock *key)
660{
661    krb5_error_code ret;
662    krb5_salt salt;
663
664    ret = krb5_get_pw_salt(context, principal, &salt);
665    if(ret)
666	return ret;
667    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
668    krb5_free_salt(context, salt);
669    return ret;
670}
671
672krb5_error_code
673krb5_string_to_key (krb5_context context,
674		    krb5_enctype enctype,
675		    const char *password,
676		    krb5_principal principal,
677		    krb5_keyblock *key)
678{
679    krb5_data pw;
680    pw.data = (void*)password;
681    pw.length = strlen(password);
682    return krb5_string_to_key_data(context, enctype, pw, principal, key);
683}
684
685/*
686 * Do a string -> key for encryption type `enctype' operation on
687 * `password' (with salt `salt'), returning the resulting key in `key'
688 */
689
690krb5_error_code
691krb5_string_to_key_data_salt (krb5_context context,
692			      krb5_enctype enctype,
693			      krb5_data password,
694			      krb5_salt salt,
695			      krb5_keyblock *key)
696{
697    struct encryption_type *et =_find_enctype(enctype);
698    struct salt_type *st;
699    if(et == NULL)
700	return KRB5_PROG_ETYPE_NOSUPP;
701    for(st = et->keytype->string_to_key; st && st->type; st++)
702	if(st->type == salt.salttype)
703	    return (*st->string_to_key)(context, enctype, password, salt, key);
704    return HEIM_ERR_SALTTYPE_NOSUPP;
705}
706
707/*
708 * Do a string -> key for encryption type `enctype' operation on the
709 * string `password' (with salt `salt'), returning the resulting key
710 * in `key'
711 */
712
713krb5_error_code
714krb5_string_to_key_salt (krb5_context context,
715			 krb5_enctype enctype,
716			 const char *password,
717			 krb5_salt salt,
718			 krb5_keyblock *key)
719{
720    krb5_data pw;
721    pw.data = (void*)password;
722    pw.length = strlen(password);
723    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
724}
725
726krb5_error_code
727krb5_keytype_to_string(krb5_context context,
728		       krb5_keytype keytype,
729		       char **string)
730{
731    struct key_type *kt = _find_keytype(keytype);
732    if(kt == NULL)
733	return KRB5_PROG_KEYTYPE_NOSUPP;
734    *string = strdup(kt->name);
735    if(*string == NULL)
736	return ENOMEM;
737    return 0;
738}
739
740krb5_error_code
741krb5_string_to_keytype(krb5_context context,
742		       const char *string,
743		       krb5_keytype *keytype)
744{
745    int i;
746    for(i = 0; i < num_keytypes; i++)
747	if(strcasecmp(keytypes[i]->name, string) == 0){
748	    *keytype = keytypes[i]->type;
749	    return 0;
750	}
751    return KRB5_PROG_KEYTYPE_NOSUPP;
752}
753
754krb5_error_code
755krb5_generate_random_keyblock(krb5_context context,
756			      krb5_enctype type,
757			      krb5_keyblock *key)
758{
759    krb5_error_code ret;
760    struct encryption_type *et = _find_enctype(type);
761    if(et == NULL)
762	return KRB5_PROG_ETYPE_NOSUPP;
763    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
764    if(ret)
765	return ret;
766    key->keytype = type;
767    if(et->keytype->random_key)
768	(*et->keytype->random_key)(context, key);
769    else
770	krb5_generate_random_block(key->keyvalue.data,
771				   key->keyvalue.length);
772    return 0;
773}
774
775static krb5_error_code
776_key_schedule(krb5_context context,
777	      struct key_data *key)
778{
779    krb5_error_code ret;
780    struct encryption_type *et = _find_enctype(key->key->keytype);
781    struct key_type *kt = et->keytype;
782
783    if(kt->schedule == NULL)
784	return 0;
785    if (key->schedule != NULL)
786	return 0;
787    ALLOC(key->schedule, 1);
788    if(key->schedule == NULL)
789	return ENOMEM;
790    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
791    if(ret) {
792	free(key->schedule);
793	key->schedule = NULL;
794	return ret;
795    }
796    (*kt->schedule)(context, key);
797    return 0;
798}
799
800/************************************************************
801 *                                                          *
802 ************************************************************/
803
804static void
805NONE_checksum(krb5_context context,
806	      struct key_data *key,
807	      const void *data,
808	      size_t len,
809	      unsigned usage,
810	      Checksum *C)
811{
812}
813
814static void
815CRC32_checksum(krb5_context context,
816	       struct key_data *key,
817	       const void *data,
818	       size_t len,
819	       unsigned usage,
820	       Checksum *C)
821{
822    u_int32_t crc;
823    unsigned char *r = C->checksum.data;
824    _krb5_crc_init_table ();
825    crc = _krb5_crc_update (data, len, 0);
826    r[0] = crc & 0xff;
827    r[1] = (crc >> 8)  & 0xff;
828    r[2] = (crc >> 16) & 0xff;
829    r[3] = (crc >> 24) & 0xff;
830}
831
832static void
833RSA_MD4_checksum(krb5_context context,
834		 struct key_data *key,
835		 const void *data,
836		 size_t len,
837		 unsigned usage,
838		 Checksum *C)
839{
840    MD4_CTX m;
841
842    MD4_Init (&m);
843    MD4_Update (&m, data, len);
844    MD4_Final (C->checksum.data, &m);
845}
846
847static void
848RSA_MD4_DES_checksum(krb5_context context,
849		     struct key_data *key,
850		     const void *data,
851		     size_t len,
852		     unsigned usage,
853		     Checksum *cksum)
854{
855    MD4_CTX md4;
856    des_cblock ivec;
857    unsigned char *p = cksum->checksum.data;
858
859    krb5_generate_random_block(p, 8);
860    MD4_Init (&md4);
861    MD4_Update (&md4, p, 8);
862    MD4_Update (&md4, data, len);
863    MD4_Final (p + 8, &md4);
864    memset (&ivec, 0, sizeof(ivec));
865    des_cbc_encrypt((des_cblock*)p,
866		    (des_cblock*)p,
867		    24,
868		    key->schedule->data,
869		    &ivec,
870		    DES_ENCRYPT);
871}
872
873static krb5_error_code
874RSA_MD4_DES_verify(krb5_context context,
875		   struct key_data *key,
876		   const void *data,
877		   size_t len,
878		   unsigned usage,
879		   Checksum *C)
880{
881    MD4_CTX md4;
882    unsigned char tmp[24];
883    unsigned char res[16];
884    des_cblock ivec;
885    krb5_error_code ret = 0;
886
887    memset(&ivec, 0, sizeof(ivec));
888    des_cbc_encrypt(C->checksum.data,
889		    (void*)tmp,
890		    C->checksum.length,
891		    key->schedule->data,
892		    &ivec,
893		    DES_DECRYPT);
894    MD4_Init (&md4);
895    MD4_Update (&md4, tmp, 8); /* confounder */
896    MD4_Update (&md4, data, len);
897    MD4_Final (res, &md4);
898    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
899	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
900    memset(tmp, 0, sizeof(tmp));
901    memset(res, 0, sizeof(res));
902    return ret;
903}
904
905static void
906RSA_MD5_checksum(krb5_context context,
907		 struct key_data *key,
908		 const void *data,
909		 size_t len,
910		 unsigned usage,
911		 Checksum *C)
912{
913    MD5_CTX m;
914
915    MD5_Init  (&m);
916    MD5_Update(&m, data, len);
917    MD5_Final (C->checksum.data, &m);
918}
919
920static void
921RSA_MD5_DES_checksum(krb5_context context,
922		     struct key_data *key,
923		     const void *data,
924		     size_t len,
925		     unsigned usage,
926		     Checksum *C)
927{
928    MD5_CTX md5;
929    des_cblock ivec;
930    unsigned char *p = C->checksum.data;
931
932    krb5_generate_random_block(p, 8);
933    MD5_Init (&md5);
934    MD5_Update (&md5, p, 8);
935    MD5_Update (&md5, data, len);
936    MD5_Final (p + 8, &md5);
937    memset (&ivec, 0, sizeof(ivec));
938    des_cbc_encrypt((des_cblock*)p,
939		    (des_cblock*)p,
940		    24,
941		    key->schedule->data,
942		    &ivec,
943		    DES_ENCRYPT);
944}
945
946static krb5_error_code
947RSA_MD5_DES_verify(krb5_context context,
948		   struct key_data *key,
949		   const void *data,
950		   size_t len,
951		   unsigned usage,
952		   Checksum *C)
953{
954    MD5_CTX md5;
955    unsigned char tmp[24];
956    unsigned char res[16];
957    des_cblock ivec;
958    des_key_schedule *sched = key->schedule->data;
959    krb5_error_code ret = 0;
960
961    memset(&ivec, 0, sizeof(ivec));
962    des_cbc_encrypt(C->checksum.data,
963		    (void*)tmp,
964		    C->checksum.length,
965		    sched[0],
966		    &ivec,
967		    DES_DECRYPT);
968    MD5_Init (&md5);
969    MD5_Update (&md5, tmp, 8); /* confounder */
970    MD5_Update (&md5, data, len);
971    MD5_Final (res, &md5);
972    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
973	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
974    memset(tmp, 0, sizeof(tmp));
975    memset(res, 0, sizeof(res));
976    return ret;
977}
978
979static void
980RSA_MD5_DES3_checksum(krb5_context context,
981		      struct key_data *key,
982		      const void *data,
983		      size_t len,
984		      unsigned usage,
985		      Checksum *C)
986{
987    MD5_CTX md5;
988    des_cblock ivec;
989    unsigned char *p = C->checksum.data;
990    des_key_schedule *sched = key->schedule->data;
991
992    krb5_generate_random_block(p, 8);
993    MD5_Init (&md5);
994    MD5_Update (&md5, p, 8);
995    MD5_Update (&md5, data, len);
996    MD5_Final (p + 8, &md5);
997    memset (&ivec, 0, sizeof(ivec));
998    des_ede3_cbc_encrypt((des_cblock*)p,
999			 (des_cblock*)p,
1000			 24,
1001			 sched[0], sched[1], sched[2],
1002			 &ivec,
1003			 DES_ENCRYPT);
1004}
1005
1006static krb5_error_code
1007RSA_MD5_DES3_verify(krb5_context context,
1008		    struct key_data *key,
1009		    const void *data,
1010		    size_t len,
1011		    unsigned usage,
1012		    Checksum *C)
1013{
1014    MD5_CTX md5;
1015    unsigned char tmp[24];
1016    unsigned char res[16];
1017    des_cblock ivec;
1018    des_key_schedule *sched = key->schedule->data;
1019    krb5_error_code ret = 0;
1020
1021    memset(&ivec, 0, sizeof(ivec));
1022    des_ede3_cbc_encrypt(C->checksum.data,
1023			 (void*)tmp,
1024			 C->checksum.length,
1025			 sched[0], sched[1], sched[2],
1026			 &ivec,
1027			 DES_DECRYPT);
1028    MD5_Init (&md5);
1029    MD5_Update (&md5, tmp, 8); /* confounder */
1030    MD5_Update (&md5, data, len);
1031    MD5_Final (res, &md5);
1032    if(memcmp(res, tmp + 8, sizeof(res)) != 0)
1033	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1034    memset(tmp, 0, sizeof(tmp));
1035    memset(res, 0, sizeof(res));
1036    return ret;
1037}
1038
1039static void
1040SHA1_checksum(krb5_context context,
1041	      struct key_data *key,
1042	      const void *data,
1043	      size_t len,
1044	      unsigned usage,
1045	      Checksum *C)
1046{
1047    SHA_CTX m;
1048
1049    SHA1_Init(&m);
1050    SHA1_Update(&m, data, len);
1051    SHA1_Final(C->checksum.data, &m);
1052}
1053
1054/* HMAC according to RFC2104 */
1055static void
1056hmac(krb5_context context,
1057     struct checksum_type *cm,
1058     const void *data,
1059     size_t len,
1060     unsigned usage,
1061     struct key_data *keyblock,
1062     Checksum *result)
1063{
1064    unsigned char *ipad, *opad;
1065    unsigned char *key;
1066    size_t key_len;
1067    int i;
1068
1069    if(keyblock->key->keyvalue.length > cm->blocksize){
1070	(*cm->checksum)(context,
1071			keyblock,
1072			keyblock->key->keyvalue.data,
1073			keyblock->key->keyvalue.length,
1074			usage,
1075			result);
1076	key = result->checksum.data;
1077	key_len = result->checksum.length;
1078    } else {
1079	key = keyblock->key->keyvalue.data;
1080	key_len = keyblock->key->keyvalue.length;
1081    }
1082    ipad = malloc(cm->blocksize + len);
1083    opad = malloc(cm->blocksize + cm->checksumsize);
1084    memset(ipad, 0x36, cm->blocksize);
1085    memset(opad, 0x5c, cm->blocksize);
1086    for(i = 0; i < key_len; i++){
1087	ipad[i] ^= key[i];
1088	opad[i] ^= key[i];
1089    }
1090    memcpy(ipad + cm->blocksize, data, len);
1091    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
1092		    usage, result);
1093    memcpy(opad + cm->blocksize, result->checksum.data,
1094	   result->checksum.length);
1095    (*cm->checksum)(context, keyblock, opad,
1096		    cm->blocksize + cm->checksumsize, usage, result);
1097    memset(ipad, 0, cm->blocksize + len);
1098    free(ipad);
1099    memset(opad, 0, cm->blocksize + cm->checksumsize);
1100    free(opad);
1101}
1102
1103static void
1104HMAC_SHA1_DES3_checksum(krb5_context context,
1105			struct key_data *key,
1106			const void *data,
1107			size_t len,
1108			unsigned usage,
1109			Checksum *result)
1110{
1111    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1112
1113    hmac(context, c, data, len, usage, key, result);
1114}
1115
1116/*
1117 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
1118 */
1119
1120static void
1121HMAC_MD5_checksum(krb5_context context,
1122		  struct key_data *key,
1123		  const void *data,
1124		  size_t len,
1125		  unsigned usage,
1126		  Checksum *result)
1127{
1128    MD5_CTX md5;
1129    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1130    const char signature[] = "signaturekey";
1131    Checksum ksign_c;
1132    struct key_data ksign;
1133    krb5_keyblock kb;
1134    unsigned char t[4];
1135    unsigned char tmp[16];
1136    unsigned char ksign_c_data[16];
1137
1138    ksign_c.checksum.length = sizeof(ksign_c_data);
1139    ksign_c.checksum.data   = ksign_c_data;
1140    hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1141    ksign.key = &kb;
1142    kb.keyvalue = ksign_c.checksum;
1143    MD5_Init (&md5);
1144    t[0] = (usage >>  0) & 0xFF;
1145    t[1] = (usage >>  8) & 0xFF;
1146    t[2] = (usage >> 16) & 0xFF;
1147    t[3] = (usage >> 24) & 0xFF;
1148    MD5_Update (&md5, t, 4);
1149    MD5_Update (&md5, data, len);
1150    MD5_Final (tmp, &md5);
1151    hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1152}
1153
1154/*
1155 * same as previous but being used while encrypting.
1156 */
1157
1158static void
1159HMAC_MD5_checksum_enc(krb5_context context,
1160		      struct key_data *key,
1161		      const void *data,
1162		      size_t len,
1163		      unsigned usage,
1164		      Checksum *result)
1165{
1166    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1167    Checksum ksign_c;
1168    struct key_data ksign;
1169    krb5_keyblock kb;
1170    unsigned char t[4];
1171    unsigned char ksign_c_data[16];
1172
1173    t[0] = (usage >>  0) & 0xFF;
1174    t[1] = (usage >>  8) & 0xFF;
1175    t[2] = (usage >> 16) & 0xFF;
1176    t[3] = (usage >> 24) & 0xFF;
1177
1178    ksign_c.checksum.length = sizeof(ksign_c_data);
1179    ksign_c.checksum.data   = ksign_c_data;
1180    hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
1181    ksign.key = &kb;
1182    kb.keyvalue = ksign_c.checksum;
1183    hmac(context, c, data, len, 0, &ksign, result);
1184}
1185
1186struct checksum_type checksum_none = {
1187    CKSUMTYPE_NONE,
1188    "none",
1189    1,
1190    0,
1191    0,
1192    NONE_checksum,
1193    NULL
1194};
1195struct checksum_type checksum_crc32 = {
1196    CKSUMTYPE_CRC32,
1197    "crc32",
1198    1,
1199    4,
1200    0,
1201    CRC32_checksum,
1202    NULL
1203};
1204struct checksum_type checksum_rsa_md4 = {
1205    CKSUMTYPE_RSA_MD4,
1206    "rsa-md4",
1207    64,
1208    16,
1209    F_CPROOF,
1210    RSA_MD4_checksum,
1211    NULL
1212};
1213struct checksum_type checksum_rsa_md4_des = {
1214    CKSUMTYPE_RSA_MD4_DES,
1215    "rsa-md4-des",
1216    64,
1217    24,
1218    F_KEYED | F_CPROOF | F_VARIANT,
1219    RSA_MD4_DES_checksum,
1220    RSA_MD4_DES_verify
1221};
1222#if 0
1223struct checksum_type checksum_des_mac = {
1224    CKSUMTYPE_DES_MAC,
1225    "des-mac",
1226    0,
1227    0,
1228    0,
1229    DES_MAC_checksum
1230};
1231struct checksum_type checksum_des_mac_k = {
1232    CKSUMTYPE_DES_MAC_K,
1233    "des-mac-k",
1234    0,
1235    0,
1236    0,
1237    DES_MAC_K_checksum
1238};
1239struct checksum_type checksum_rsa_md4_des_k = {
1240    CKSUMTYPE_RSA_MD4_DES_K,
1241    "rsa-md4-des-k",
1242    0,
1243    0,
1244    0,
1245    RSA_MD4_DES_K_checksum,
1246    RSA_MD4_DES_K_verify
1247};
1248#endif
1249struct checksum_type checksum_rsa_md5 = {
1250    CKSUMTYPE_RSA_MD5,
1251    "rsa-md5",
1252    64,
1253    16,
1254    F_CPROOF,
1255    RSA_MD5_checksum,
1256    NULL
1257};
1258struct checksum_type checksum_rsa_md5_des = {
1259    CKSUMTYPE_RSA_MD5_DES,
1260    "rsa-md5-des",
1261    64,
1262    24,
1263    F_KEYED | F_CPROOF | F_VARIANT,
1264    RSA_MD5_DES_checksum,
1265    RSA_MD5_DES_verify
1266};
1267struct checksum_type checksum_rsa_md5_des3 = {
1268    CKSUMTYPE_RSA_MD5_DES3,
1269    "rsa-md5-des3",
1270    64,
1271    24,
1272    F_KEYED | F_CPROOF | F_VARIANT,
1273    RSA_MD5_DES3_checksum,
1274    RSA_MD5_DES3_verify
1275};
1276struct checksum_type checksum_sha1 = {
1277    CKSUMTYPE_SHA1,
1278    "sha1",
1279    64,
1280    20,
1281    F_CPROOF,
1282    SHA1_checksum,
1283    NULL
1284};
1285struct checksum_type checksum_hmac_sha1_des3 = {
1286    CKSUMTYPE_HMAC_SHA1_DES3,
1287    "hmac-sha1-des3",
1288    64,
1289    20,
1290    F_KEYED | F_CPROOF | F_DERIVED,
1291    HMAC_SHA1_DES3_checksum,
1292    NULL
1293};
1294
1295struct checksum_type checksum_hmac_md5 = {
1296    CKSUMTYPE_HMAC_MD5,
1297    "hmac-md5",
1298    64,
1299    16,
1300    F_KEYED | F_CPROOF,
1301    HMAC_MD5_checksum,
1302    NULL
1303};
1304
1305struct checksum_type checksum_hmac_md5_enc = {
1306    CKSUMTYPE_HMAC_MD5_ENC,
1307    "hmac-md5-enc",
1308    64,
1309    16,
1310    F_KEYED | F_CPROOF | F_PSEUDO,
1311    HMAC_MD5_checksum_enc,
1312    NULL
1313};
1314
1315struct checksum_type *checksum_types[] = {
1316    &checksum_none,
1317    &checksum_crc32,
1318    &checksum_rsa_md4,
1319    &checksum_rsa_md4_des,
1320#if 0
1321    &checksum_des_mac,
1322    &checksum_des_mac_k,
1323    &checksum_rsa_md4_des_k,
1324#endif
1325    &checksum_rsa_md5,
1326    &checksum_rsa_md5_des,
1327    &checksum_rsa_md5_des3,
1328    &checksum_sha1,
1329    &checksum_hmac_sha1_des3,
1330    &checksum_hmac_md5,
1331    &checksum_hmac_md5_enc
1332};
1333
1334static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
1335
1336static struct checksum_type *
1337_find_checksum(krb5_cksumtype type)
1338{
1339    int i;
1340    for(i = 0; i < num_checksums; i++)
1341	if(checksum_types[i]->type == type)
1342	    return checksum_types[i];
1343    return NULL;
1344}
1345
1346static krb5_error_code
1347get_checksum_key(krb5_context context,
1348		 krb5_crypto crypto,
1349		 unsigned usage,  /* not krb5_key_usage */
1350		 struct checksum_type *ct,
1351		 struct key_data **key)
1352{
1353    krb5_error_code ret = 0;
1354
1355    if(ct->flags & F_DERIVED)
1356	ret = _get_derived_key(context, crypto, usage, key);
1357    else if(ct->flags & F_VARIANT) {
1358	int i;
1359
1360	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
1361	if(*key == NULL)
1362	    return ENOMEM;
1363	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
1364	if(ret)
1365	    return ret;
1366	for(i = 0; i < (*key)->key->keyvalue.length; i++)
1367	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
1368    } else {
1369	*key = &crypto->key;
1370    }
1371    if(ret == 0)
1372	ret = _key_schedule(context, *key);
1373    return ret;
1374}
1375
1376static krb5_error_code
1377do_checksum (krb5_context context,
1378	     struct checksum_type *ct,
1379	     krb5_crypto crypto,
1380	     unsigned usage,
1381	     void *data,
1382	     size_t len,
1383	     Checksum *result)
1384{
1385    krb5_error_code ret;
1386    struct key_data *dkey;
1387    int keyed_checksum;
1388
1389    keyed_checksum = (ct->flags & F_KEYED) != 0;
1390    if(keyed_checksum && crypto == NULL)
1391	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1392    if(keyed_checksum) {
1393	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1394	if (ret)
1395	    return ret;
1396    } else
1397	dkey = NULL;
1398    result->cksumtype = ct->type;
1399    krb5_data_alloc(&result->checksum, ct->checksumsize);
1400    (*ct->checksum)(context, dkey, data, len, usage, result);
1401    return 0;
1402}
1403
1404static krb5_error_code
1405create_checksum(krb5_context context,
1406		krb5_crypto crypto,
1407		unsigned usage, /* not krb5_key_usage */
1408		krb5_cksumtype type, /* if crypto == NULL */
1409		void *data,
1410		size_t len,
1411		Checksum *result)
1412{
1413    struct checksum_type *ct;
1414
1415    if(crypto) {
1416	ct = crypto->et->keyed_checksum;
1417	if(ct == NULL)
1418	    ct = crypto->et->cksumtype;
1419    } else
1420	ct = _find_checksum(type);
1421    if(ct == NULL)
1422	return KRB5_PROG_SUMTYPE_NOSUPP;
1423    return do_checksum (context, ct, crypto, usage, data, len, result);
1424}
1425
1426krb5_error_code
1427krb5_create_checksum(krb5_context context,
1428		     krb5_crypto crypto,
1429		     unsigned usage_or_type,
1430		     void *data,
1431		     size_t len,
1432		     Checksum *result)
1433{
1434    return create_checksum(context, crypto,
1435			   CHECKSUM_USAGE(usage_or_type),
1436			   usage_or_type, data, len, result);
1437}
1438
1439static krb5_error_code
1440verify_checksum(krb5_context context,
1441		krb5_crypto crypto,
1442		unsigned usage, /* not krb5_key_usage */
1443		void *data,
1444		size_t len,
1445		Checksum *cksum)
1446{
1447    krb5_error_code ret;
1448    struct key_data *dkey;
1449    int keyed_checksum;
1450    Checksum c;
1451    struct checksum_type *ct;
1452
1453    ct = _find_checksum(cksum->cksumtype);
1454    if(ct == NULL)
1455	return KRB5_PROG_SUMTYPE_NOSUPP;
1456    if(ct->checksumsize != cksum->checksum.length)
1457	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
1458    keyed_checksum = (ct->flags & F_KEYED) != 0;
1459    if(keyed_checksum && crypto == NULL)
1460	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
1461    if(keyed_checksum)
1462	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
1463    else
1464	dkey = NULL;
1465    if(ct->verify)
1466	return (*ct->verify)(context, dkey, data, len, usage, cksum);
1467
1468    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
1469    if (ret)
1470	return ret;
1471
1472    (*ct->checksum)(context, dkey, data, len, usage, &c);
1473
1474    if(c.checksum.length != cksum->checksum.length ||
1475       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length))
1476	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
1477    else
1478	ret = 0;
1479    krb5_data_free (&c.checksum);
1480    return ret;
1481}
1482
1483krb5_error_code
1484krb5_verify_checksum(krb5_context context,
1485		     krb5_crypto crypto,
1486		     krb5_key_usage usage,
1487		     void *data,
1488		     size_t len,
1489		     Checksum *cksum)
1490{
1491    return verify_checksum(context, crypto,
1492			   CHECKSUM_USAGE(usage), data, len, cksum);
1493}
1494
1495krb5_error_code
1496krb5_checksumsize(krb5_context context,
1497		  krb5_cksumtype type,
1498		  size_t *size)
1499{
1500    struct checksum_type *ct = _find_checksum(type);
1501    if(ct == NULL)
1502	return KRB5_PROG_SUMTYPE_NOSUPP;
1503    *size = ct->checksumsize;
1504    return 0;
1505}
1506
1507krb5_boolean
1508krb5_checksum_is_keyed(krb5_context context,
1509		       krb5_cksumtype type)
1510{
1511    struct checksum_type *ct = _find_checksum(type);
1512    if(ct == NULL)
1513	return KRB5_PROG_SUMTYPE_NOSUPP;
1514    return ct->flags & F_KEYED;
1515}
1516
1517krb5_boolean
1518krb5_checksum_is_collision_proof(krb5_context context,
1519				 krb5_cksumtype type)
1520{
1521    struct checksum_type *ct = _find_checksum(type);
1522    if(ct == NULL)
1523	return KRB5_PROG_SUMTYPE_NOSUPP;
1524    return ct->flags & F_CPROOF;
1525}
1526
1527/************************************************************
1528 *                                                          *
1529 ************************************************************/
1530
1531static krb5_error_code
1532NULL_encrypt(struct key_data *key,
1533	     void *data,
1534	     size_t len,
1535	     krb5_boolean encrypt,
1536	     int usage,
1537	     void *ivec)
1538{
1539    return 0;
1540}
1541
1542static krb5_error_code
1543DES_CBC_encrypt_null_ivec(struct key_data *key,
1544			  void *data,
1545			  size_t len,
1546			  krb5_boolean encrypt,
1547			  int usage,
1548			  void *ignore_ivec)
1549{
1550    des_cblock ivec;
1551    des_key_schedule *s = key->schedule->data;
1552    memset(&ivec, 0, sizeof(ivec));
1553    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1554    return 0;
1555}
1556
1557static krb5_error_code
1558DES_CBC_encrypt_key_ivec(struct key_data *key,
1559			 void *data,
1560			 size_t len,
1561			 krb5_boolean encrypt,
1562			 int usage,
1563			 void *ignore_ivec)
1564{
1565    des_cblock ivec;
1566    des_key_schedule *s = key->schedule->data;
1567    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1568    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
1569    return 0;
1570}
1571
1572static krb5_error_code
1573DES3_CBC_encrypt(struct key_data *key,
1574		 void *data,
1575		 size_t len,
1576		 krb5_boolean encrypt,
1577		 int usage,
1578		 void *ignore_ivec)
1579{
1580    des_cblock ivec;
1581    des_key_schedule *s = key->schedule->data;
1582    memset(&ivec, 0, sizeof(ivec));
1583    des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], &ivec, encrypt);
1584    return 0;
1585}
1586
1587static krb5_error_code
1588DES3_CBC_encrypt_ivec(struct key_data *key,
1589		      void *data,
1590		      size_t len,
1591		      krb5_boolean encrypt,
1592		      int usage,
1593		      void *ivec)
1594{
1595    des_key_schedule *s = key->schedule->data;
1596
1597    des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt);
1598    return 0;
1599}
1600
1601static krb5_error_code
1602DES_CFB64_encrypt_null_ivec(struct key_data *key,
1603			    void *data,
1604			    size_t len,
1605			    krb5_boolean encrypt,
1606			    int usage,
1607			    void *ignore_ivec)
1608{
1609    des_cblock ivec;
1610    int num = 0;
1611    des_key_schedule *s = key->schedule->data;
1612    memset(&ivec, 0, sizeof(ivec));
1613
1614    des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
1615    return 0;
1616}
1617
1618static krb5_error_code
1619DES_PCBC_encrypt_key_ivec(struct key_data *key,
1620			  void *data,
1621			  size_t len,
1622			  krb5_boolean encrypt,
1623			  int usage,
1624			  void *ignore_ivec)
1625{
1626    des_cblock ivec;
1627    des_key_schedule *s = key->schedule->data;
1628    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
1629
1630    des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
1631    return 0;
1632}
1633
1634/*
1635 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
1636 *
1637 * warning: not for small children
1638 */
1639
1640static krb5_error_code
1641ARCFOUR_subencrypt(struct key_data *key,
1642		   void *data,
1643		   size_t len,
1644		   int usage,
1645		   void *ivec)
1646{
1647    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1648    Checksum k1_c, k2_c, k3_c, cksum;
1649    struct key_data ke;
1650    krb5_keyblock kb;
1651    unsigned char t[4];
1652    RC4_KEY rc4_key;
1653    char *cdata = (char *)data;
1654    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1655
1656    t[0] = (usage >>  0) & 0xFF;
1657    t[1] = (usage >>  8) & 0xFF;
1658    t[2] = (usage >> 16) & 0xFF;
1659    t[3] = (usage >> 24) & 0xFF;
1660
1661    k1_c.checksum.length = sizeof(k1_c_data);
1662    k1_c.checksum.data   = k1_c_data;
1663
1664    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1665
1666    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1667
1668    k2_c.checksum.length = sizeof(k2_c_data);
1669    k2_c.checksum.data   = k2_c_data;
1670
1671    ke.key = &kb;
1672    kb.keyvalue = k2_c.checksum;
1673
1674    cksum.checksum.length = 16;
1675    cksum.checksum.data   = data;
1676
1677    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1678
1679    ke.key = &kb;
1680    kb.keyvalue = k1_c.checksum;
1681
1682    k3_c.checksum.length = sizeof(k3_c_data);
1683    k3_c.checksum.data   = k3_c_data;
1684
1685    hmac(NULL, c, data, 16, 0, &ke, &k3_c);
1686
1687    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1688    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1689    memset (k1_c_data, 0, sizeof(k1_c_data));
1690    memset (k2_c_data, 0, sizeof(k2_c_data));
1691    memset (k3_c_data, 0, sizeof(k3_c_data));
1692    return 0;
1693}
1694
1695static krb5_error_code
1696ARCFOUR_subdecrypt(struct key_data *key,
1697		   void *data,
1698		   size_t len,
1699		   int usage,
1700		   void *ivec)
1701{
1702    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
1703    Checksum k1_c, k2_c, k3_c, cksum;
1704    struct key_data ke;
1705    krb5_keyblock kb;
1706    unsigned char t[4];
1707    RC4_KEY rc4_key;
1708    char *cdata = (char *)data;
1709    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
1710    unsigned char cksum_data[16];
1711
1712    t[0] = (usage >>  0) & 0xFF;
1713    t[1] = (usage >>  8) & 0xFF;
1714    t[2] = (usage >> 16) & 0xFF;
1715    t[3] = (usage >> 24) & 0xFF;
1716
1717    k1_c.checksum.length = sizeof(k1_c_data);
1718    k1_c.checksum.data   = k1_c_data;
1719
1720    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
1721
1722    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
1723
1724    k2_c.checksum.length = sizeof(k2_c_data);
1725    k2_c.checksum.data   = k2_c_data;
1726
1727    ke.key = &kb;
1728    kb.keyvalue = k1_c.checksum;
1729
1730    k3_c.checksum.length = sizeof(k3_c_data);
1731    k3_c.checksum.data   = k3_c_data;
1732
1733    hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
1734
1735    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
1736    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
1737
1738    ke.key = &kb;
1739    kb.keyvalue = k2_c.checksum;
1740
1741    cksum.checksum.length = 16;
1742    cksum.checksum.data   = cksum_data;
1743
1744    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
1745
1746    memset (k1_c_data, 0, sizeof(k1_c_data));
1747    memset (k2_c_data, 0, sizeof(k2_c_data));
1748    memset (k3_c_data, 0, sizeof(k3_c_data));
1749
1750    if (memcmp (cksum.checksum.data, data, 16) != 0)
1751	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
1752    else
1753	return 0;
1754}
1755
1756/*
1757 * convert the usage numbers used in
1758 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
1759 * draft-brezak-win2k-krb-rc4-hmac-03.txt
1760 */
1761
1762static int
1763usage2arcfour (int usage)
1764{
1765    switch (usage) {
1766    case KRB5_KU_PA_ENC_TIMESTAMP :
1767	return 1;
1768    case KRB5_KU_TICKET :
1769	return 8;
1770    case KRB5_KU_AS_REP_ENC_PART :
1771	return 8;
1772    case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
1773    case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
1774    case KRB5_KU_TGS_REQ_AUTH_CKSUM :
1775    case KRB5_KU_TGS_REQ_AUTH :
1776	return 7;
1777    case KRB5_KU_TGS_REP_ENC_PART_SESSION :
1778    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1779	return 8;
1780    case KRB5_KU_AP_REQ_AUTH_CKSUM :
1781    case KRB5_KU_AP_REQ_AUTH :
1782    case KRB5_KU_AP_REQ_ENC_PART :
1783	return 11;
1784    case KRB5_KU_KRB_PRIV :
1785	return 0;
1786    case KRB5_KU_KRB_CRED :
1787    case KRB5_KU_KRB_SAFE_CKSUM :
1788    case KRB5_KU_OTHER_ENCRYPTED :
1789    case KRB5_KU_OTHER_CKSUM :
1790    case KRB5_KU_KRB_ERROR :
1791    case KRB5_KU_AD_KDC_ISSUED :
1792    case KRB5_KU_MANDATORY_TICKET_EXTENSION :
1793    case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
1794    case KRB5_KU_USAGE_SEAL :
1795    case KRB5_KU_USAGE_SIGN :
1796    case KRB5_KU_USAGE_SEQ :
1797    default :
1798	abort ();
1799    }
1800}
1801
1802static krb5_error_code
1803ARCFOUR_encrypt(struct key_data *key,
1804		void *data,
1805		size_t len,
1806		krb5_boolean encrypt,
1807		int usage,
1808		void *ivec)
1809{
1810    usage = usage2arcfour (usage);
1811
1812    if (encrypt)
1813	return ARCFOUR_subencrypt (key, data, len, usage, ivec);
1814    else
1815	return ARCFOUR_subdecrypt (key, data, len, usage, ivec);
1816}
1817
1818
1819/*
1820 * these should currently be in reverse preference order.
1821 * (only relevant for !F_PSEUDO) */
1822
1823static struct encryption_type etypes[] = {
1824    {
1825	ETYPE_NULL,
1826	"null",
1827	1,
1828	0,
1829	&keytype_null,
1830	&checksum_none,
1831	NULL,
1832	0,
1833	NULL_encrypt,
1834    },
1835    {
1836	ETYPE_DES_CBC_CRC,
1837	"des-cbc-crc",
1838	8,
1839	8,
1840	&keytype_des,
1841	&checksum_crc32,
1842	NULL,
1843	0,
1844	DES_CBC_encrypt_key_ivec,
1845    },
1846    {
1847	ETYPE_DES_CBC_MD4,
1848	"des-cbc-md4",
1849	8,
1850	8,
1851	&keytype_des,
1852	&checksum_rsa_md4,
1853	&checksum_rsa_md4_des,
1854	0,
1855	DES_CBC_encrypt_null_ivec,
1856    },
1857    {
1858	ETYPE_DES_CBC_MD5,
1859	"des-cbc-md5",
1860	8,
1861	8,
1862	&keytype_des,
1863	&checksum_rsa_md5,
1864	&checksum_rsa_md5_des,
1865	0,
1866	DES_CBC_encrypt_null_ivec,
1867    },
1868    {
1869	ETYPE_ARCFOUR_HMAC_MD5,
1870	"arcfour-hmac-md5",
1871	1,
1872	8,
1873	&keytype_arcfour,
1874	&checksum_hmac_md5_enc,
1875	&checksum_hmac_md5_enc,
1876	F_SPECIAL,
1877	ARCFOUR_encrypt
1878    },
1879    {
1880	ETYPE_DES3_CBC_MD5,
1881	"des3-cbc-md5",
1882	8,
1883	8,
1884	&keytype_des3,
1885	&checksum_rsa_md5,
1886	&checksum_rsa_md5_des3,
1887	0,
1888 	DES3_CBC_encrypt,
1889    },
1890    {
1891	ETYPE_DES3_CBC_SHA1,
1892	"des3-cbc-sha1",
1893	8,
1894	8,
1895	&keytype_des3_derived,
1896	&checksum_sha1,
1897	&checksum_hmac_sha1_des3,
1898	F_DERIVED,
1899 	DES3_CBC_encrypt,
1900    },
1901    {
1902	ETYPE_OLD_DES3_CBC_SHA1,
1903	"old-des3-cbc-sha1",
1904	8,
1905	8,
1906	&keytype_des3,
1907	&checksum_sha1,
1908	&checksum_hmac_sha1_des3,
1909	0,
1910 	DES3_CBC_encrypt,
1911    },
1912    {
1913	ETYPE_DES_CBC_NONE,
1914	"des-cbc-none",
1915	8,
1916	0,
1917	&keytype_des,
1918	&checksum_none,
1919	NULL,
1920	F_PSEUDO,
1921	DES_CBC_encrypt_null_ivec,
1922    },
1923    {
1924	ETYPE_DES_CFB64_NONE,
1925	"des-cfb64-none",
1926	1,
1927	0,
1928	&keytype_des,
1929	&checksum_none,
1930	NULL,
1931	F_PSEUDO,
1932	DES_CFB64_encrypt_null_ivec,
1933    },
1934    {
1935	ETYPE_DES_PCBC_NONE,
1936	"des-pcbc-none",
1937	8,
1938	0,
1939	&keytype_des,
1940	&checksum_none,
1941	NULL,
1942	F_PSEUDO,
1943	DES_PCBC_encrypt_key_ivec,
1944    },
1945    {
1946	ETYPE_DES3_CBC_NONE,
1947	"des3-cbc-none",
1948	8,
1949	0,
1950	&keytype_des3_derived,
1951	&checksum_none,
1952	NULL,
1953	F_PSEUDO,
1954	DES3_CBC_encrypt,
1955    },
1956    {
1957	ETYPE_DES3_CBC_NONE_IVEC,
1958	"des3-cbc-none-ivec",
1959	8,
1960	0,
1961	&keytype_des3_derived,
1962	&checksum_none,
1963	NULL,
1964	F_PSEUDO,
1965	DES3_CBC_encrypt_ivec,
1966    }
1967};
1968
1969static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
1970
1971
1972static struct encryption_type *
1973_find_enctype(krb5_enctype type)
1974{
1975    int i;
1976    for(i = 0; i < num_etypes; i++)
1977	if(etypes[i].type == type)
1978	    return &etypes[i];
1979    return NULL;
1980}
1981
1982
1983krb5_error_code
1984krb5_enctype_to_string(krb5_context context,
1985		       krb5_enctype etype,
1986		       char **string)
1987{
1988    struct encryption_type *e;
1989    e = _find_enctype(etype);
1990    if(e == NULL)
1991	return KRB5_PROG_ETYPE_NOSUPP;
1992    *string = strdup(e->name);
1993    if(*string == NULL)
1994	return ENOMEM;
1995    return 0;
1996}
1997
1998krb5_error_code
1999krb5_string_to_enctype(krb5_context context,
2000		       const char *string,
2001		       krb5_enctype *etype)
2002{
2003    int i;
2004    for(i = 0; i < num_etypes; i++)
2005	if(strcasecmp(etypes[i].name, string) == 0){
2006	    *etype = etypes[i].type;
2007	    return 0;
2008	}
2009    return KRB5_PROG_ETYPE_NOSUPP;
2010}
2011
2012krb5_error_code
2013krb5_enctype_to_keytype(krb5_context context,
2014			krb5_enctype etype,
2015			krb5_keytype *keytype)
2016{
2017    struct encryption_type *e = _find_enctype(etype);
2018    if(e == NULL)
2019	return KRB5_PROG_ETYPE_NOSUPP;
2020    *keytype = e->keytype->type; /* XXX */
2021    return 0;
2022}
2023
2024#if 0
2025krb5_error_code
2026krb5_keytype_to_enctype(krb5_context context,
2027			krb5_keytype keytype,
2028			krb5_enctype *etype)
2029{
2030    struct key_type *kt = _find_keytype(keytype);
2031    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
2032    if(kt == NULL)
2033	return KRB5_PROG_KEYTYPE_NOSUPP;
2034    *etype = kt->best_etype;
2035    return 0;
2036}
2037#endif
2038
2039krb5_error_code
2040krb5_keytype_to_enctypes (krb5_context context,
2041			  krb5_keytype keytype,
2042			  unsigned *len,
2043			  int **val)
2044{
2045    int i;
2046    unsigned n = 0;
2047    int *ret;
2048
2049    for (i = num_etypes - 1; i >= 0; --i) {
2050	if (etypes[i].keytype->type == keytype
2051	    && !(etypes[i].flags & F_PSEUDO))
2052	    ++n;
2053    }
2054    ret = malloc(n * sizeof(int));
2055    if (ret == NULL && n != 0)
2056	return ENOMEM;
2057    n = 0;
2058    for (i = num_etypes - 1; i >= 0; --i) {
2059	if (etypes[i].keytype->type == keytype
2060	    && !(etypes[i].flags & F_PSEUDO))
2061	    ret[n++] = etypes[i].type;
2062    }
2063    *len = n;
2064    *val = ret;
2065    return 0;
2066}
2067
2068/*
2069 * First take the configured list of etypes for `keytype' if available,
2070 * else, do `krb5_keytype_to_enctypes'.
2071 */
2072
2073krb5_error_code
2074krb5_keytype_to_enctypes_default (krb5_context context,
2075				  krb5_keytype keytype,
2076				  unsigned *len,
2077				  int **val)
2078{
2079    int i, n;
2080    int *ret;
2081
2082    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
2083	return krb5_keytype_to_enctypes (context, keytype, len, val);
2084
2085    for (n = 0; context->etypes_des[n]; ++n)
2086	;
2087    ret = malloc (n * sizeof(*ret));
2088    if (ret == NULL && n != 0)
2089	return ENOMEM;
2090    for (i = 0; i < n; ++i)
2091	ret[i] = context->etypes_des[i];
2092    *len = n;
2093    *val = ret;
2094    return 0;
2095}
2096
2097krb5_error_code
2098krb5_enctype_valid(krb5_context context,
2099		 krb5_enctype etype)
2100{
2101    return _find_enctype(etype) != NULL;
2102}
2103
2104/* if two enctypes have compatible keys */
2105krb5_boolean
2106krb5_enctypes_compatible_keys(krb5_context context,
2107			      krb5_enctype etype1,
2108			      krb5_enctype etype2)
2109{
2110    struct encryption_type *e1 = _find_enctype(etype1);
2111    struct encryption_type *e2 = _find_enctype(etype2);
2112    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2113}
2114
2115static krb5_boolean
2116derived_crypto(krb5_context context,
2117	       krb5_crypto crypto)
2118{
2119    return (crypto->et->flags & F_DERIVED) != 0;
2120}
2121
2122static krb5_boolean
2123special_crypto(krb5_context context,
2124	       krb5_crypto crypto)
2125{
2126    return (crypto->et->flags & F_SPECIAL) != 0;
2127}
2128
2129#define CHECKSUMSIZE(C) ((C)->checksumsize)
2130#define CHECKSUMTYPE(C) ((C)->type)
2131
2132static krb5_error_code
2133encrypt_internal_derived(krb5_context context,
2134			 krb5_crypto crypto,
2135			 unsigned usage,
2136			 void *data,
2137			 size_t len,
2138			 krb5_data *result,
2139			 void *ivec)
2140{
2141    size_t sz, block_sz, checksum_sz;
2142    Checksum cksum;
2143    unsigned char *p, *q;
2144    krb5_error_code ret;
2145    struct key_data *dkey;
2146    struct encryption_type *et = crypto->et;
2147
2148    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2149
2150    sz = et->confoundersize + /* 4 - length */ len;
2151    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2152    p = calloc(1, block_sz + checksum_sz);
2153    if(p == NULL)
2154	return ENOMEM;
2155
2156    q = p;
2157    krb5_generate_random_block(q, et->confoundersize); /* XXX */
2158    q += et->confoundersize;
2159    memcpy(q, data, len);
2160
2161    ret = create_checksum(context,
2162			  crypto,
2163			  INTEGRITY_USAGE(usage),
2164			  0,
2165			  p,
2166			  block_sz,
2167			  &cksum);
2168    if(ret == 0 && cksum.checksum.length != checksum_sz) {
2169	free_Checksum (&cksum);
2170	ret = KRB5_CRYPTO_INTERNAL;
2171    }
2172    if(ret) {
2173	memset(p, 0, block_sz + checksum_sz);
2174	free(p);
2175	return ret;
2176    }
2177    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
2178    free_Checksum (&cksum);
2179    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2180    if(ret) {
2181	memset(p, 0, block_sz + checksum_sz);
2182	free(p);
2183	return ret;
2184    }
2185    ret = _key_schedule(context, dkey);
2186    if(ret) {
2187	memset(p, 0, block_sz);
2188	free(p);
2189	return ret;
2190    }
2191#ifdef CRYPTO_DEBUG
2192    krb5_crypto_debug(context, 1, block_sz, dkey->key);
2193#endif
2194    (*et->encrypt)(dkey, p, block_sz, 1, usage, ivec);
2195    result->data = p;
2196    result->length = block_sz + checksum_sz;
2197    return 0;
2198}
2199
2200static krb5_error_code
2201encrypt_internal(krb5_context context,
2202		 krb5_crypto crypto,
2203		 void *data,
2204		 size_t len,
2205		 krb5_data *result,
2206		 void *ivec)
2207{
2208    size_t sz, block_sz, checksum_sz;
2209    Checksum cksum;
2210    unsigned char *p, *q;
2211    krb5_error_code ret;
2212    struct encryption_type *et = crypto->et;
2213
2214    checksum_sz = CHECKSUMSIZE(et->cksumtype);
2215
2216    sz = et->confoundersize + checksum_sz + len;
2217    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
2218    p = calloc(1, block_sz);
2219    if(p == NULL)
2220	return ENOMEM;
2221
2222    q = p;
2223    krb5_generate_random_block(q, et->confoundersize); /* XXX */
2224    q += et->confoundersize;
2225    memset(q, 0, checksum_sz);
2226    q += checksum_sz;
2227    memcpy(q, data, len);
2228
2229    ret = create_checksum(context,
2230			  NULL,
2231			  0,
2232			  CHECKSUMTYPE(et->cksumtype),
2233			  p,
2234			  block_sz,
2235			  &cksum);
2236    if(ret == 0 && cksum.checksum.length != checksum_sz) {
2237	free_Checksum (&cksum);
2238	ret = KRB5_CRYPTO_INTERNAL;
2239    }
2240    if(ret) {
2241	memset(p, 0, block_sz);
2242	free(p);
2243	free_Checksum(&cksum);
2244	return ret;
2245    }
2246    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
2247    free_Checksum(&cksum);
2248    ret = _key_schedule(context, &crypto->key);
2249    if(ret) {
2250	memset(p, 0, block_sz);
2251	free(p);
2252	return ret;
2253    }
2254#ifdef CRYPTO_DEBUG
2255    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
2256#endif
2257    (*et->encrypt)(&crypto->key, p, block_sz, 1, 0, ivec);
2258    result->data = p;
2259    result->length = block_sz;
2260    return 0;
2261}
2262
2263static krb5_error_code
2264encrypt_internal_special(krb5_context context,
2265			 krb5_crypto crypto,
2266			 int usage,
2267			 void *data,
2268			 size_t len,
2269			 krb5_data *result,
2270			 void *ivec)
2271{
2272    struct encryption_type *et = crypto->et;
2273    size_t cksum_sz = CHECKSUMSIZE(et->cksumtype);
2274    size_t sz = len + cksum_sz + et->confoundersize;
2275    char *tmp, *p;
2276
2277    tmp = malloc (sz);
2278    if (tmp == NULL)
2279	return ENOMEM;
2280    p = tmp;
2281    memset (p, 0, cksum_sz);
2282    p += cksum_sz;
2283    krb5_generate_random_block(p, et->confoundersize);
2284    p += et->confoundersize;
2285    memcpy (p, data, len);
2286    (*et->encrypt)(&crypto->key, tmp, sz, TRUE, usage, ivec);
2287    result->data   = tmp;
2288    result->length = sz;
2289    return 0;
2290}
2291
2292static krb5_error_code
2293decrypt_internal_derived(krb5_context context,
2294			 krb5_crypto crypto,
2295			 unsigned usage,
2296			 void *data,
2297			 size_t len,
2298			 krb5_data *result,
2299			 void *ivec)
2300{
2301    size_t checksum_sz;
2302    Checksum cksum;
2303    unsigned char *p;
2304    krb5_error_code ret;
2305    struct key_data *dkey;
2306    struct encryption_type *et = crypto->et;
2307    unsigned long l;
2308
2309    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
2310    if (len < checksum_sz)
2311	return EINVAL;		/* better error code? */
2312
2313    p = malloc(len);
2314    if(len != 0 && p == NULL)
2315	return ENOMEM;
2316    memcpy(p, data, len);
2317
2318    len -= checksum_sz;
2319
2320    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
2321    if(ret) {
2322	free(p);
2323	return ret;
2324    }
2325    ret = _key_schedule(context, dkey);
2326    if(ret) {
2327	free(p);
2328	return ret;
2329    }
2330#ifdef CRYPTO_DEBUG
2331    krb5_crypto_debug(context, 0, len, dkey->key);
2332#endif
2333    (*et->encrypt)(dkey, p, len, 0, usage, ivec);
2334
2335    cksum.checksum.data   = p + len;
2336    cksum.checksum.length = checksum_sz;
2337    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
2338
2339    ret = verify_checksum(context,
2340			  crypto,
2341			  INTEGRITY_USAGE(usage),
2342			  p,
2343			  len,
2344			  &cksum);
2345    if(ret) {
2346	free(p);
2347	return ret;
2348    }
2349    l = len - et->confoundersize;
2350    memmove(p, p + et->confoundersize, l);
2351    result->data = realloc(p, l);
2352    if(p == NULL) {
2353	free(p);
2354	return ENOMEM;
2355    }
2356    result->length = l;
2357    return 0;
2358}
2359
2360static krb5_error_code
2361decrypt_internal(krb5_context context,
2362		 krb5_crypto crypto,
2363		 void *data,
2364		 size_t len,
2365		 krb5_data *result,
2366		 void *ivec)
2367{
2368    krb5_error_code ret;
2369    unsigned char *p;
2370    Checksum cksum;
2371    size_t checksum_sz, l;
2372    struct encryption_type *et = crypto->et;
2373
2374    checksum_sz = CHECKSUMSIZE(et->cksumtype);
2375    p = malloc(len);
2376    if(len != 0 && p == NULL)
2377	return ENOMEM;
2378    memcpy(p, data, len);
2379
2380    ret = _key_schedule(context, &crypto->key);
2381    if(ret) {
2382	free(p);
2383	return ret;
2384    }
2385#ifdef CRYPTO_DEBUG
2386    krb5_crypto_debug(context, 0, len, crypto->key.key);
2387#endif
2388    (*et->encrypt)(&crypto->key, p, len, 0, 0, ivec);
2389    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
2390    if(ret) {
2391 	free(p);
2392 	return ret;
2393    }
2394    memset(p + et->confoundersize, 0, checksum_sz);
2395    cksum.cksumtype = CHECKSUMTYPE(et->cksumtype);
2396    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
2397    free_Checksum(&cksum);
2398    if(ret) {
2399	free(p);
2400	return ret;
2401    }
2402    l = len - et->confoundersize - checksum_sz;
2403    memmove(p, p + et->confoundersize + checksum_sz, l);
2404    result->data = realloc(p, l);
2405    if(result->data == NULL) {
2406	free(p);
2407	return ENOMEM;
2408    }
2409    result->length = l;
2410    return 0;
2411}
2412
2413static krb5_error_code
2414decrypt_internal_special(krb5_context context,
2415			 krb5_crypto crypto,
2416			 int usage,
2417			 void *data,
2418			 size_t len,
2419			 krb5_data *result,
2420			 void *ivec)
2421{
2422    struct encryption_type *et = crypto->et;
2423    size_t cksum_sz = CHECKSUMSIZE(et->cksumtype);
2424    size_t sz = len - cksum_sz - et->confoundersize;
2425    char *cdata = (char *)data;
2426    char *tmp;
2427
2428    tmp = malloc (sz);
2429    if (tmp == NULL)
2430	return ENOMEM;
2431
2432    (*et->encrypt)(&crypto->key, data, len, FALSE, usage, ivec);
2433
2434    memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
2435
2436    result->data   = tmp;
2437    result->length = sz;
2438    return 0;
2439}
2440
2441
2442krb5_error_code
2443krb5_encrypt_ivec(krb5_context context,
2444		  krb5_crypto crypto,
2445		  unsigned usage,
2446		  void *data,
2447		  size_t len,
2448		  krb5_data *result,
2449		  void *ivec)
2450{
2451    if(derived_crypto(context, crypto))
2452	return encrypt_internal_derived(context, crypto, usage,
2453					data, len, result, ivec);
2454    else if (special_crypto(context, crypto))
2455	return encrypt_internal_special (context, crypto, usage,
2456					 data, len, result, ivec);
2457    else
2458	return encrypt_internal(context, crypto, data, len, result, ivec);
2459}
2460
2461krb5_error_code
2462krb5_encrypt(krb5_context context,
2463	     krb5_crypto crypto,
2464	     unsigned usage,
2465	     void *data,
2466	     size_t len,
2467	     krb5_data *result)
2468{
2469    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
2470}
2471
2472krb5_error_code
2473krb5_encrypt_EncryptedData(krb5_context context,
2474			   krb5_crypto crypto,
2475			   unsigned usage,
2476			   void *data,
2477			   size_t len,
2478			   int kvno,
2479			   EncryptedData *result)
2480{
2481    result->etype = CRYPTO_ETYPE(crypto);
2482    if(kvno){
2483	ALLOC(result->kvno, 1);
2484	*result->kvno = kvno;
2485    }else
2486	result->kvno = NULL;
2487    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
2488}
2489
2490krb5_error_code
2491krb5_decrypt_ivec(krb5_context context,
2492		  krb5_crypto crypto,
2493		  unsigned usage,
2494		  void *data,
2495		  size_t len,
2496		  krb5_data *result,
2497		  void *ivec)
2498{
2499    if(derived_crypto(context, crypto))
2500	return decrypt_internal_derived(context, crypto, usage,
2501					data, len, result, ivec);
2502    else if (special_crypto (context, crypto))
2503	return decrypt_internal_special(context, crypto, usage,
2504					data, len, result, ivec);
2505    else
2506	return decrypt_internal(context, crypto, data, len, result, ivec);
2507}
2508
2509krb5_error_code
2510krb5_decrypt(krb5_context context,
2511	     krb5_crypto crypto,
2512	     unsigned usage,
2513	     void *data,
2514	     size_t len,
2515	     krb5_data *result)
2516{
2517    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
2518			      NULL);
2519}
2520
2521krb5_error_code
2522krb5_decrypt_EncryptedData(krb5_context context,
2523			   krb5_crypto crypto,
2524			   unsigned usage,
2525			   const EncryptedData *e,
2526			   krb5_data *result)
2527{
2528    return krb5_decrypt(context, crypto, usage,
2529			e->cipher.data, e->cipher.length, result);
2530}
2531
2532/************************************************************
2533 *                                                          *
2534 ************************************************************/
2535
2536void
2537krb5_generate_random_block(void *buf, size_t len)
2538{
2539    des_cblock key, out;
2540    static des_cblock counter;
2541    static des_key_schedule schedule;
2542    int i;
2543    static int initialized = 0;
2544
2545    if(!initialized) {
2546	des_new_random_key(&key);
2547	des_set_key(&key, schedule);
2548	memset(&key, 0, sizeof(key));
2549	des_new_random_key(&counter);
2550    }
2551    while(len > 0) {
2552	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
2553	for(i = 7; i >=0; i--)
2554	    if(counter[i]++)
2555		break;
2556	memcpy(buf, out, min(len, sizeof(out)));
2557	len -= min(len, sizeof(out));
2558	buf = (char*)buf + sizeof(out);
2559    }
2560}
2561
2562static void
2563DES3_postproc(krb5_context context,
2564	      unsigned char *k, size_t len, struct key_data *key)
2565{
2566    unsigned char x[24];
2567    int i, j;
2568
2569    memset(x, 0, sizeof(x));
2570    for (i = 0; i < 3; ++i) {
2571	unsigned char foo;
2572
2573	for (j = 0; j < 7; ++j) {
2574	    unsigned char b = k[7 * i + j];
2575
2576	    x[8 * i + j] = b;
2577	}
2578	foo = 0;
2579	for (j = 6; j >= 0; --j) {
2580	    foo |= k[7 * i + j] & 1;
2581	    foo <<= 1;
2582	}
2583	x[8 * i + 7] = foo;
2584    }
2585    k = key->key->keyvalue.data;
2586    memcpy(k, x, 24);
2587    memset(x, 0, sizeof(x));
2588    if (key->schedule) {
2589	krb5_free_data(context, key->schedule);
2590	key->schedule = NULL;
2591    }
2592    des_set_odd_parity((des_cblock*)k);
2593    des_set_odd_parity((des_cblock*)(k + 8));
2594    des_set_odd_parity((des_cblock*)(k + 16));
2595}
2596
2597static krb5_error_code
2598derive_key(krb5_context context,
2599	   struct encryption_type *et,
2600	   struct key_data *key,
2601	   void *constant,
2602	   size_t len)
2603{
2604    unsigned char *k;
2605    unsigned int nblocks = 0, i;
2606    krb5_error_code ret = 0;
2607
2608    struct key_type *kt = et->keytype;
2609    ret = _key_schedule(context, key);
2610    if(ret)
2611	return ret;
2612    if(et->blocksize * 8 < kt->bits ||
2613       len != et->blocksize) {
2614	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
2615	k = malloc(nblocks * et->blocksize);
2616	if(k == NULL)
2617	    return ENOMEM;
2618	_krb5_n_fold(constant, len, k, et->blocksize);
2619	for(i = 0; i < nblocks; i++) {
2620	    if(i > 0)
2621		memcpy(k + i * et->blocksize,
2622		       k + (i - 1) * et->blocksize,
2623		       et->blocksize);
2624	    (*et->encrypt)(key, k + i * et->blocksize, et->blocksize, 1, 0,
2625			   NULL);
2626	}
2627    } else {
2628	/* this case is probably broken, but won't be run anyway */
2629	void *c = malloc(len);
2630	size_t res_len = (kt->bits + 7) / 8;
2631
2632	if(len != 0 && c == NULL)
2633	    return ENOMEM;
2634	memcpy(c, constant, len);
2635	(*et->encrypt)(key, c, len, 1, 0, NULL);
2636	k = malloc(res_len);
2637	if(res_len != 0 && k == NULL)
2638	    return ENOMEM;
2639	_krb5_n_fold(c, len, k, res_len);
2640	free(c);
2641    }
2642
2643    /* XXX keytype dependent post-processing */
2644    switch(kt->type) {
2645    case KEYTYPE_DES3:
2646	DES3_postproc(context, k, nblocks * et->blocksize, key);
2647	break;
2648    default:
2649	krb5_warnx(context, "derive_key() called with unknown keytype (%u)",
2650		   kt->type);
2651	ret = KRB5_CRYPTO_INTERNAL;
2652	break;
2653    }
2654    memset(k, 0, nblocks * et->blocksize);
2655    free(k);
2656    return ret;
2657}
2658
2659static struct key_data *
2660_new_derived_key(krb5_crypto crypto, unsigned usage)
2661{
2662    struct key_usage *d = crypto->key_usage;
2663    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
2664    if(d == NULL)
2665	return NULL;
2666    crypto->key_usage = d;
2667    d += crypto->num_key_usage++;
2668    memset(d, 0, sizeof(*d));
2669    d->usage = usage;
2670    return &d->key;
2671}
2672
2673static krb5_error_code
2674_get_derived_key(krb5_context context,
2675		 krb5_crypto crypto,
2676		 unsigned usage,
2677		 struct key_data **key)
2678{
2679    int i;
2680    struct key_data *d;
2681    unsigned char constant[5];
2682
2683    for(i = 0; i < crypto->num_key_usage; i++)
2684	if(crypto->key_usage[i].usage == usage) {
2685	    *key = &crypto->key_usage[i].key;
2686	    return 0;
2687	}
2688    d = _new_derived_key(crypto, usage);
2689    if(d == NULL)
2690	return ENOMEM;
2691    krb5_copy_keyblock(context, crypto->key.key, &d->key);
2692    _krb5_put_int(constant, usage, 5);
2693    derive_key(context, crypto->et, d, constant, sizeof(constant));
2694    *key = d;
2695    return 0;
2696}
2697
2698
2699krb5_error_code
2700krb5_crypto_init(krb5_context context,
2701		 krb5_keyblock *key,
2702		 krb5_enctype etype,
2703		 krb5_crypto *crypto)
2704{
2705    krb5_error_code ret;
2706    ALLOC(*crypto, 1);
2707    if(*crypto == NULL)
2708	return ENOMEM;
2709    if(etype == ETYPE_NULL)
2710	etype = key->keytype;
2711    (*crypto)->et = _find_enctype(etype);
2712    if((*crypto)->et == NULL) {
2713	free(*crypto);
2714	return KRB5_PROG_ETYPE_NOSUPP;
2715    }
2716    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2717    if(ret) {
2718	free(*crypto);
2719	return ret;
2720    }
2721    (*crypto)->key.schedule = NULL;
2722    (*crypto)->num_key_usage = 0;
2723    (*crypto)->key_usage = NULL;
2724    return 0;
2725}
2726
2727static void
2728free_key_data(krb5_context context, struct key_data *key)
2729{
2730    krb5_free_keyblock(context, key->key);
2731    if(key->schedule) {
2732	memset(key->schedule->data, 0, key->schedule->length);
2733	krb5_free_data(context, key->schedule);
2734    }
2735}
2736
2737static void
2738free_key_usage(krb5_context context, struct key_usage *ku)
2739{
2740    free_key_data(context, &ku->key);
2741}
2742
2743krb5_error_code
2744krb5_crypto_destroy(krb5_context context,
2745		    krb5_crypto crypto)
2746{
2747    int i;
2748
2749    for(i = 0; i < crypto->num_key_usage; i++)
2750	free_key_usage(context, &crypto->key_usage[i]);
2751    free(crypto->key_usage);
2752    free_key_data(context, &crypto->key);
2753    free (crypto);
2754    return 0;
2755}
2756
2757krb5_error_code
2758krb5_string_to_key_derived(krb5_context context,
2759			   const void *str,
2760			   size_t len,
2761			   krb5_enctype etype,
2762			   krb5_keyblock *key)
2763{
2764    struct encryption_type *et = _find_enctype(etype);
2765    krb5_error_code ret;
2766    struct key_data kd;
2767    u_char *tmp;
2768
2769    if(et == NULL)
2770	return KRB5_PROG_ETYPE_NOSUPP;
2771    ALLOC(kd.key, 1);
2772    kd.key->keytype = etype;
2773    tmp = malloc (et->keytype->bits / 8);
2774    _krb5_n_fold(str, len, tmp, et->keytype->bits / 8);
2775    krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
2776    kd.schedule = NULL;
2777    DES3_postproc (context, tmp, et->keytype->bits / 8, &kd); /* XXX */
2778    ret = derive_key(context,
2779		     et,
2780		     &kd,
2781		     "kerberos", /* XXX well known constant */
2782		     strlen("kerberos"));
2783    ret = krb5_copy_keyblock_contents(context, kd.key, key);
2784    free_key_data(context, &kd);
2785    return ret;
2786}
2787
2788static size_t
2789wrapped_length (krb5_context context,
2790		krb5_crypto  crypto,
2791		size_t       data_len)
2792{
2793    struct encryption_type *et = crypto->et;
2794    size_t blocksize = et->blocksize;
2795    size_t res;
2796
2797    res =  et->confoundersize + et->cksumtype->checksumsize + data_len;
2798    res =  (res + blocksize - 1) / blocksize * blocksize;
2799    return res;
2800}
2801
2802static size_t
2803wrapped_length_dervied (krb5_context context,
2804			krb5_crypto  crypto,
2805			size_t       data_len)
2806{
2807    struct encryption_type *et = crypto->et;
2808    size_t blocksize = et->blocksize;
2809    size_t res;
2810
2811    res =  et->confoundersize + data_len;
2812    res =  (res + blocksize - 1) / blocksize * blocksize;
2813    res += et->cksumtype->checksumsize;
2814    return res;
2815}
2816
2817/*
2818 * Return the size of an encrypted packet of length `data_len'
2819 */
2820
2821size_t
2822krb5_get_wrapped_length (krb5_context context,
2823			 krb5_crypto  crypto,
2824			 size_t       data_len)
2825{
2826    if (derived_crypto (context, crypto))
2827	return wrapped_length_dervied (context, crypto, data_len);
2828    else
2829	return wrapped_length (context, crypto, data_len);
2830}
2831
2832#ifdef CRYPTO_DEBUG
2833
2834static krb5_error_code
2835krb5_get_keyid(krb5_context context,
2836	       krb5_keyblock *key,
2837	       u_int32_t *keyid)
2838{
2839    MD5_CTX md5;
2840    unsigned char tmp[16];
2841
2842    MD5_Init (&md5);
2843    MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
2844    MD5_Final (tmp, &md5);
2845    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
2846    return 0;
2847}
2848
2849static void
2850krb5_crypto_debug(krb5_context context,
2851		  int encrypt,
2852		  size_t len,
2853		  krb5_keyblock *key)
2854{
2855    u_int32_t keyid;
2856    char *kt;
2857    krb5_get_keyid(context, key, &keyid);
2858    krb5_enctype_to_string(context, key->keytype, &kt);
2859    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
2860	       encrypt ? "encrypting" : "decrypting",
2861	       (unsigned long)len,
2862	       keyid,
2863	       kt);
2864    free(kt);
2865}
2866
2867#endif /* CRYPTO_DEBUG */
2868
2869#if 0
2870int
2871main()
2872{
2873#if 0
2874    int i;
2875    krb5_context context;
2876    krb5_crypto crypto;
2877    struct key_data *d;
2878    krb5_keyblock key;
2879    char constant[4];
2880    unsigned usage = ENCRYPTION_USAGE(3);
2881    krb5_error_code ret;
2882
2883    ret = krb5_init_context(&context);
2884    if (ret)
2885	errx (1, "krb5_init_context failed: %d", ret);
2886
2887    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
2888    key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
2889	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
2890	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
2891    key.keyvalue.length = 24;
2892
2893    krb5_crypto_init(context, &key, 0, &crypto);
2894
2895    d = _new_derived_key(crypto, usage);
2896    if(d == NULL)
2897	return ENOMEM;
2898    krb5_copy_keyblock(context, crypto->key.key, &d->key);
2899    _krb5_put_int(constant, usage, 4);
2900    derive_key(context, crypto->et, d, constant, sizeof(constant));
2901    return 0;
2902#else
2903    int i;
2904    krb5_context context;
2905    krb5_crypto crypto;
2906    struct key_data *d;
2907    krb5_keyblock key;
2908    krb5_error_code ret;
2909    Checksum res;
2910
2911    char *data = "what do ya want for nothing?";
2912
2913    ret = krb5_init_context(&context);
2914    if (ret)
2915	errx (1, "krb5_init_context failed: %d", ret);
2916
2917    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
2918    key.keyvalue.data = "Jefe";
2919    /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
2920       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
2921    key.keyvalue.length = 4;
2922
2923    d = calloc(1, sizeof(*d));
2924
2925    d->key = &key;
2926    res.checksum.length = 20;
2927    res.checksum.data = malloc(res.checksum.length);
2928    HMAC_SHA1_DES3_checksum(context, d, data, 28, &res);
2929
2930    return 0;
2931#endif
2932}
2933#endif
2934