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