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