crypto.c revision 103426
155682Smarkm/*
290929Snectar * Copyright (c) 1997 - 2002 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "krb5_locl.h"
35103426SnectarRCSID("$Id: crypto.c,v 1.66 2002/09/03 19:58:15 joda Exp $");
3657428Smarkm/* RCSID("$FreeBSD: head/crypto/heimdal/lib/krb5/crypto.c 103426 2002-09-16 21:07:11Z nectar $"); */
3755682Smarkm
3855682Smarkm#undef CRYPTO_DEBUG
3955682Smarkm#ifdef CRYPTO_DEBUG
4055682Smarkmstatic void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
4155682Smarkm#endif
4255682Smarkm
4355682Smarkm
4455682Smarkmstruct key_data {
4555682Smarkm    krb5_keyblock *key;
4655682Smarkm    krb5_data *schedule;
4755682Smarkm};
4855682Smarkm
4955682Smarkmstruct key_usage {
5055682Smarkm    unsigned usage;
5155682Smarkm    struct key_data key;
5255682Smarkm};
5355682Smarkm
5455682Smarkmstruct krb5_crypto_data {
5555682Smarkm    struct encryption_type *et;
5655682Smarkm    struct key_data key;
5755682Smarkm    int num_key_usage;
5855682Smarkm    struct key_usage *key_usage;
5955682Smarkm};
6055682Smarkm
6155682Smarkm#define CRYPTO_ETYPE(C) ((C)->et->type)
6255682Smarkm
6355682Smarkm/* bits for `flags' below */
6455682Smarkm#define F_KEYED		 1	/* checksum is keyed */
6555682Smarkm#define F_CPROOF	 2	/* checksum is collision proof */
6655682Smarkm#define F_DERIVED	 4	/* uses derived keys */
6755682Smarkm#define F_VARIANT	 8	/* uses `variant' keys (6.4.3) */
6855682Smarkm#define F_PSEUDO	16	/* not a real protocol type */
6972448Sassar#define F_SPECIAL	32	/* backwards */
7055682Smarkm
7155682Smarkmstruct salt_type {
7255682Smarkm    krb5_salttype type;
7355682Smarkm    const char *name;
7455682Smarkm    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
7555682Smarkm				     krb5_salt, krb5_keyblock*);
7655682Smarkm};
7755682Smarkm
7855682Smarkmstruct key_type {
7955682Smarkm    krb5_keytype type; /* XXX */
8055682Smarkm    const char *name;
8155682Smarkm    size_t bits;
8255682Smarkm    size_t size;
8355682Smarkm    size_t schedule_size;
8455682Smarkm#if 0
8555682Smarkm    krb5_enctype best_etype;
8655682Smarkm#endif
8755682Smarkm    void (*random_key)(krb5_context, krb5_keyblock*);
8855682Smarkm    void (*schedule)(krb5_context, struct key_data *);
8955682Smarkm    struct salt_type *string_to_key;
9055682Smarkm};
9155682Smarkm
9255682Smarkmstruct checksum_type {
9355682Smarkm    krb5_cksumtype type;
9455682Smarkm    const char *name;
9555682Smarkm    size_t blocksize;
9655682Smarkm    size_t checksumsize;
9755682Smarkm    unsigned flags;
9872448Sassar    void (*checksum)(krb5_context context,
9972448Sassar		     struct key_data *key,
10072448Sassar		     const void *buf, size_t len,
10172448Sassar		     unsigned usage,
10272448Sassar		     Checksum *csum);
10372448Sassar    krb5_error_code (*verify)(krb5_context context,
10472448Sassar			      struct key_data *key,
10572448Sassar			      const void *buf, size_t len,
10672448Sassar			      unsigned usage,
10772448Sassar			      Checksum *csum);
10855682Smarkm};
10955682Smarkm
11055682Smarkmstruct encryption_type {
11155682Smarkm    krb5_enctype type;
11255682Smarkm    const char *name;
11355682Smarkm    size_t blocksize;
11455682Smarkm    size_t confoundersize;
11555682Smarkm    struct key_type *keytype;
11678536Sassar    struct checksum_type *checksum;
11755682Smarkm    struct checksum_type *keyed_checksum;
11855682Smarkm    unsigned flags;
11978536Sassar    krb5_error_code (*encrypt)(krb5_context context,
12078536Sassar			       struct key_data *key,
12172448Sassar			       void *data, size_t len,
12272448Sassar			       krb5_boolean encrypt,
12372448Sassar			       int usage,
12472448Sassar			       void *ivec);
12555682Smarkm};
12655682Smarkm
12755682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
12855682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
12955682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
13055682Smarkm
13155682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type);
13255682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type);
13355682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type);
13455682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
13555682Smarkm					unsigned, struct key_data**);
13655682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
13755682Smarkm
13855682Smarkm/************************************************************
13955682Smarkm *                                                          *
14055682Smarkm ************************************************************/
14155682Smarkm
14255682Smarkmstatic void
143102647Snectarkrb5_DES_random_key(krb5_context context,
14455682Smarkm	       krb5_keyblock *key)
14555682Smarkm{
14655682Smarkm    des_cblock *k = key->keyvalue.data;
14755682Smarkm    do {
14855682Smarkm	krb5_generate_random_block(k, sizeof(des_cblock));
14955682Smarkm	des_set_odd_parity(k);
15055682Smarkm    } while(des_is_weak_key(k));
15155682Smarkm}
15255682Smarkm
15355682Smarkmstatic void
154102647Snectarkrb5_DES_schedule(krb5_context context,
15555682Smarkm	     struct key_data *key)
15655682Smarkm{
15755682Smarkm    des_set_key(key->key->keyvalue.data, key->schedule->data);
15855682Smarkm}
15955682Smarkm
16090929Snectarstatic void
16190929SnectarDES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key)
16290929Snectar{
16390929Snectar    des_key_schedule schedule;
16490929Snectar    int i;
16590929Snectar    int reverse = 0;
16690929Snectar    unsigned char *p;
16790929Snectar
16890929Snectar    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
16990929Snectar			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
17090929Snectar    memset(key, 0, 8);
17190929Snectar
17290929Snectar    p = (unsigned char*)key;
17390929Snectar    for (i = 0; i < length; i++) {
17490929Snectar	unsigned char tmp = data[i];
17590929Snectar	if (!reverse)
17690929Snectar	    *p++ ^= (tmp << 1);
17790929Snectar	else
17890929Snectar	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
17990929Snectar	if((i % 8) == 7)
18090929Snectar	    reverse = !reverse;
18190929Snectar    }
18290929Snectar    des_set_odd_parity(key);
18390929Snectar    if(des_is_weak_key(key))
18490929Snectar	(*key)[7] ^= 0xF0;
18590929Snectar    des_set_key(key, schedule);
18690929Snectar    des_cbc_cksum((void*)data, key, length, schedule, key);
18790929Snectar    memset(schedule, 0, sizeof(schedule));
18890929Snectar    des_set_odd_parity(key);
18990929Snectar}
19090929Snectar
19155682Smarkmstatic krb5_error_code
192102647Snectarkrb5_DES_string_to_key(krb5_context context,
19355682Smarkm		  krb5_enctype enctype,
19455682Smarkm		  krb5_data password,
19555682Smarkm		  krb5_salt salt,
19655682Smarkm		  krb5_keyblock *key)
19755682Smarkm{
19890929Snectar    unsigned char *s;
19955682Smarkm    size_t len;
20055682Smarkm    des_cblock tmp;
20155682Smarkm
20290929Snectar    len = password.length + salt.saltvalue.length;
20355682Smarkm    s = malloc(len);
20490929Snectar    if(len > 0 && s == NULL) {
20578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
20655682Smarkm	return ENOMEM;
20778536Sassar    }
20855682Smarkm    memcpy(s, password.data, password.length);
20955682Smarkm    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
21090929Snectar    DES_string_to_key_int(s, len, &tmp);
21155682Smarkm    key->keytype = enctype;
21255682Smarkm    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
21355682Smarkm    memset(&tmp, 0, sizeof(tmp));
21455682Smarkm    memset(s, 0, len);
21555682Smarkm    free(s);
21655682Smarkm    return 0;
21755682Smarkm}
21855682Smarkm
21955682Smarkm/* This defines the Andrew string_to_key function.  It accepts a password
22055682Smarkm * string as input and converts its via a one-way encryption algorithm to a DES
22155682Smarkm * encryption key.  It is compatible with the original Andrew authentication
22255682Smarkm * service password database.
22355682Smarkm */
22455682Smarkm
22555682Smarkm/*
22655682Smarkm * Short passwords, i.e 8 characters or less.
22755682Smarkm */
22855682Smarkmstatic void
229102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
23055682Smarkm			    krb5_data cell,
23155682Smarkm			    des_cblock *key)
23255682Smarkm{
23355682Smarkm    char  password[8+1];	/* crypt is limited to 8 chars anyway */
23455682Smarkm    int   i;
23555682Smarkm
23655682Smarkm    for(i = 0; i < 8; i++) {
23755682Smarkm	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
23872448Sassar		 ((i < cell.length) ?
23972448Sassar		  tolower(((unsigned char*)cell.data)[i]) : 0);
24055682Smarkm	password[i] = c ? c : 'X';
24155682Smarkm    }
24255682Smarkm    password[8] = '\0';
24355682Smarkm
24455682Smarkm    memcpy(key, crypt(password, "#~") + 2, sizeof(des_cblock));
24555682Smarkm
24655682Smarkm    /* parity is inserted into the LSB so left shift each byte up one
24755682Smarkm       bit. This allows ascii characters with a zero MSB to retain as
24855682Smarkm       much significance as possible. */
24955682Smarkm    for (i = 0; i < sizeof(des_cblock); i++)
25055682Smarkm	((unsigned char*)key)[i] <<= 1;
25155682Smarkm    des_set_odd_parity (key);
25255682Smarkm}
25355682Smarkm
25455682Smarkm/*
25555682Smarkm * Long passwords, i.e 9 characters or more.
25655682Smarkm */
25755682Smarkmstatic void
258102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
25955682Smarkm				 krb5_data cell,
26055682Smarkm				 des_cblock *key)
26155682Smarkm{
26255682Smarkm    des_key_schedule schedule;
26355682Smarkm    des_cblock temp_key;
26455682Smarkm    des_cblock ivec;
26555682Smarkm    char password[512];
26655682Smarkm    size_t passlen;
26755682Smarkm
26855682Smarkm    memcpy(password, pw.data, min(pw.length, sizeof(password)));
26972448Sassar    if(pw.length < sizeof(password)) {
27072448Sassar	int len = min(cell.length, sizeof(password) - pw.length);
27172448Sassar	int i;
27272448Sassar
27372448Sassar	memcpy(password + pw.length, cell.data, len);
27472448Sassar	for (i = pw.length; i < pw.length + len; ++i)
27572448Sassar	    password[i] = tolower((unsigned char)password[i]);
27672448Sassar    }
27755682Smarkm    passlen = min(sizeof(password), pw.length + cell.length);
27855682Smarkm    memcpy(&ivec, "kerberos", 8);
27955682Smarkm    memcpy(&temp_key, "kerberos", 8);
28055682Smarkm    des_set_odd_parity (&temp_key);
28155682Smarkm    des_set_key (&temp_key, schedule);
28290929Snectar    des_cbc_cksum (password, &ivec, passlen, schedule, &ivec);
28355682Smarkm
28455682Smarkm    memcpy(&temp_key, &ivec, 8);
28555682Smarkm    des_set_odd_parity (&temp_key);
28655682Smarkm    des_set_key (&temp_key, schedule);
28790929Snectar    des_cbc_cksum (password, key, passlen, schedule, &ivec);
28855682Smarkm    memset(&schedule, 0, sizeof(schedule));
28955682Smarkm    memset(&temp_key, 0, sizeof(temp_key));
29055682Smarkm    memset(&ivec, 0, sizeof(ivec));
29155682Smarkm    memset(password, 0, sizeof(password));
29255682Smarkm
29355682Smarkm    des_set_odd_parity (key);
29455682Smarkm}
29555682Smarkm
29655682Smarkmstatic krb5_error_code
29755682SmarkmDES_AFS3_string_to_key(krb5_context context,
29855682Smarkm		       krb5_enctype enctype,
29955682Smarkm		       krb5_data password,
30055682Smarkm		       krb5_salt salt,
30155682Smarkm		       krb5_keyblock *key)
30255682Smarkm{
30355682Smarkm    des_cblock tmp;
30455682Smarkm    if(password.length > 8)
305102647Snectar	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
30655682Smarkm    else
307102647Snectar	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
30855682Smarkm    key->keytype = enctype;
30955682Smarkm    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
31055682Smarkm    memset(&key, 0, sizeof(key));
31155682Smarkm    return 0;
31255682Smarkm}
31355682Smarkm
31455682Smarkmstatic void
31555682SmarkmDES3_random_key(krb5_context context,
31655682Smarkm		krb5_keyblock *key)
31755682Smarkm{
31855682Smarkm    des_cblock *k = key->keyvalue.data;
31955682Smarkm    do {
32055682Smarkm	krb5_generate_random_block(k, 3 * sizeof(des_cblock));
32155682Smarkm	des_set_odd_parity(&k[0]);
32255682Smarkm	des_set_odd_parity(&k[1]);
32355682Smarkm	des_set_odd_parity(&k[2]);
32455682Smarkm    } while(des_is_weak_key(&k[0]) ||
32555682Smarkm	    des_is_weak_key(&k[1]) ||
32655682Smarkm	    des_is_weak_key(&k[2]));
32755682Smarkm}
32855682Smarkm
32955682Smarkmstatic void
33055682SmarkmDES3_schedule(krb5_context context,
33155682Smarkm	      struct key_data *key)
33255682Smarkm{
33355682Smarkm    des_cblock *k = key->key->keyvalue.data;
33455682Smarkm    des_key_schedule *s = key->schedule->data;
33555682Smarkm    des_set_key(&k[0], s[0]);
33655682Smarkm    des_set_key(&k[1], s[1]);
33755682Smarkm    des_set_key(&k[2], s[2]);
33855682Smarkm}
33955682Smarkm
34055682Smarkm/*
34155682Smarkm * A = A xor B. A & B are 8 bytes.
34255682Smarkm */
34355682Smarkm
34455682Smarkmstatic void
34555682Smarkmxor (des_cblock *key, const unsigned char *b)
34655682Smarkm{
34755682Smarkm    unsigned char *a = (unsigned char*)key;
34855682Smarkm    a[0] ^= b[0];
34955682Smarkm    a[1] ^= b[1];
35055682Smarkm    a[2] ^= b[2];
35155682Smarkm    a[3] ^= b[3];
35255682Smarkm    a[4] ^= b[4];
35355682Smarkm    a[5] ^= b[5];
35455682Smarkm    a[6] ^= b[6];
35555682Smarkm    a[7] ^= b[7];
35655682Smarkm}
35755682Smarkm
35855682Smarkmstatic krb5_error_code
35955682SmarkmDES3_string_to_key(krb5_context context,
36055682Smarkm		   krb5_enctype enctype,
36155682Smarkm		   krb5_data password,
36255682Smarkm		   krb5_salt salt,
36355682Smarkm		   krb5_keyblock *key)
36455682Smarkm{
36555682Smarkm    char *str;
36655682Smarkm    size_t len;
36755682Smarkm    unsigned char tmp[24];
36855682Smarkm    des_cblock keys[3];
36955682Smarkm
37055682Smarkm    len = password.length + salt.saltvalue.length;
37155682Smarkm    str = malloc(len);
37278536Sassar    if(len != 0 && str == NULL) {
37378536Sassar	krb5_set_error_string(context, "malloc: out of memory");
37455682Smarkm	return ENOMEM;
37578536Sassar    }
37655682Smarkm    memcpy(str, password.data, password.length);
37755682Smarkm    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
37855682Smarkm    {
37955682Smarkm	des_cblock ivec;
38055682Smarkm	des_key_schedule s[3];
38155682Smarkm	int i;
38255682Smarkm
38355682Smarkm	_krb5_n_fold(str, len, tmp, 24);
38455682Smarkm
38555682Smarkm	for(i = 0; i < 3; i++){
38655682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
38755682Smarkm	    des_set_odd_parity(keys + i);
38855682Smarkm	    if(des_is_weak_key(keys + i))
389102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
39055682Smarkm	    des_set_key(keys + i, s[i]);
39155682Smarkm	}
39255682Smarkm	memset(&ivec, 0, sizeof(ivec));
39390929Snectar	des_ede3_cbc_encrypt(tmp,
39490929Snectar			     tmp, sizeof(tmp),
39555682Smarkm			     s[0], s[1], s[2], &ivec, DES_ENCRYPT);
39655682Smarkm	memset(s, 0, sizeof(s));
39755682Smarkm	memset(&ivec, 0, sizeof(ivec));
39855682Smarkm	for(i = 0; i < 3; i++){
39955682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
40055682Smarkm	    des_set_odd_parity(keys + i);
40155682Smarkm	    if(des_is_weak_key(keys + i))
402102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
40355682Smarkm	}
40455682Smarkm	memset(tmp, 0, sizeof(tmp));
40555682Smarkm    }
40655682Smarkm    key->keytype = enctype;
40755682Smarkm    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
40855682Smarkm    memset(keys, 0, sizeof(keys));
40955682Smarkm    memset(str, 0, len);
41055682Smarkm    free(str);
41155682Smarkm    return 0;
41255682Smarkm}
41355682Smarkm
41455682Smarkmstatic krb5_error_code
41555682SmarkmDES3_string_to_key_derived(krb5_context context,
41655682Smarkm			   krb5_enctype enctype,
41755682Smarkm			   krb5_data password,
41855682Smarkm			   krb5_salt salt,
41955682Smarkm			   krb5_keyblock *key)
42055682Smarkm{
42155682Smarkm    krb5_error_code ret;
42255682Smarkm    size_t len = password.length + salt.saltvalue.length;
42355682Smarkm    char *s;
42455682Smarkm
42555682Smarkm    s = malloc(len);
42678536Sassar    if(len != 0 && s == NULL) {
42778536Sassar	krb5_set_error_string(context, "malloc: out of memory");
42855682Smarkm	return ENOMEM;
42978536Sassar    }
43055682Smarkm    memcpy(s, password.data, password.length);
43155682Smarkm    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
43255682Smarkm    ret = krb5_string_to_key_derived(context,
43355682Smarkm				     s,
43455682Smarkm				     len,
43555682Smarkm				     enctype,
43655682Smarkm				     key);
43755682Smarkm    memset(s, 0, len);
43855682Smarkm    free(s);
43955682Smarkm    return ret;
44055682Smarkm}
44155682Smarkm
44255682Smarkm/*
44355682Smarkm * ARCFOUR
44455682Smarkm */
44555682Smarkm
44655682Smarkmstatic void
44755682SmarkmARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
44855682Smarkm{
44955682Smarkm    krb5_generate_random_block (key->keyvalue.data,
45055682Smarkm				key->keyvalue.length);
45155682Smarkm}
45255682Smarkm
45355682Smarkmstatic void
45455682SmarkmARCFOUR_schedule(krb5_context context, struct key_data *kd)
45555682Smarkm{
45655682Smarkm    RC4_set_key (kd->schedule->data,
45755682Smarkm		 kd->key->keyvalue.length, kd->key->keyvalue.data);
45855682Smarkm}
45955682Smarkm
46055682Smarkmstatic krb5_error_code
46155682SmarkmARCFOUR_string_to_key(krb5_context context,
46255682Smarkm		  krb5_enctype enctype,
46355682Smarkm		  krb5_data password,
46455682Smarkm		  krb5_salt salt,
46555682Smarkm		  krb5_keyblock *key)
46655682Smarkm{
46755682Smarkm    char *s, *p;
46855682Smarkm    size_t len;
46955682Smarkm    int i;
47057416Smarkm    MD4_CTX m;
47155682Smarkm
47272448Sassar    len = 2 * password.length;
47355682Smarkm    s = malloc (len);
47478536Sassar    if (len != 0 && s == NULL) {
47578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
47655682Smarkm	return ENOMEM;
47778536Sassar    }
47855682Smarkm    for (p = s, i = 0; i < password.length; ++i) {
47955682Smarkm	*p++ = ((char *)password.data)[i];
48055682Smarkm	*p++ = 0;
48155682Smarkm    }
48272448Sassar    MD4_Init (&m);
48372448Sassar    MD4_Update (&m, s, len);
48455682Smarkm    key->keytype = enctype;
48555682Smarkm    krb5_data_alloc (&key->keyvalue, 16);
48672448Sassar    MD4_Final (key->keyvalue.data, &m);
48755682Smarkm    memset (s, 0, len);
48855682Smarkm    free (s);
48955682Smarkm    return 0;
49055682Smarkm}
49155682Smarkm
49255682Smarkmextern struct salt_type des_salt[],
49355682Smarkm    des3_salt[], des3_salt_derived[], arcfour_salt[];
49455682Smarkm
49555682Smarkmstruct key_type keytype_null = {
49655682Smarkm    KEYTYPE_NULL,
49755682Smarkm    "null",
49855682Smarkm    0,
49955682Smarkm    0,
50055682Smarkm    0,
50155682Smarkm    NULL,
50255682Smarkm    NULL,
50355682Smarkm    NULL
50455682Smarkm};
50555682Smarkm
50655682Smarkmstruct key_type keytype_des = {
50755682Smarkm    KEYTYPE_DES,
50855682Smarkm    "des",
50955682Smarkm    56,
51055682Smarkm    sizeof(des_cblock),
51155682Smarkm    sizeof(des_key_schedule),
512102647Snectar    krb5_DES_random_key,
513102647Snectar    krb5_DES_schedule,
51455682Smarkm    des_salt
51555682Smarkm};
51655682Smarkm
51755682Smarkmstruct key_type keytype_des3 = {
51855682Smarkm    KEYTYPE_DES3,
51955682Smarkm    "des3",
52055682Smarkm    168,
52155682Smarkm    3 * sizeof(des_cblock),
52255682Smarkm    3 * sizeof(des_key_schedule),
52355682Smarkm    DES3_random_key,
52455682Smarkm    DES3_schedule,
52555682Smarkm    des3_salt
52655682Smarkm};
52755682Smarkm
52855682Smarkmstruct key_type keytype_des3_derived = {
52955682Smarkm    KEYTYPE_DES3,
53055682Smarkm    "des3",
53155682Smarkm    168,
53255682Smarkm    3 * sizeof(des_cblock),
53355682Smarkm    3 * sizeof(des_key_schedule),
53455682Smarkm    DES3_random_key,
53555682Smarkm    DES3_schedule,
53655682Smarkm    des3_salt_derived
53755682Smarkm};
53855682Smarkm
53955682Smarkmstruct key_type keytype_arcfour = {
54055682Smarkm    KEYTYPE_ARCFOUR,
54155682Smarkm    "arcfour",
54255682Smarkm    128,
54355682Smarkm    16,
54455682Smarkm    sizeof(RC4_KEY),
54555682Smarkm    ARCFOUR_random_key,
54655682Smarkm    ARCFOUR_schedule,
54755682Smarkm    arcfour_salt
54855682Smarkm};
54955682Smarkm
55055682Smarkmstruct key_type *keytypes[] = {
55155682Smarkm    &keytype_null,
55255682Smarkm    &keytype_des,
55355682Smarkm    &keytype_des3_derived,
55455682Smarkm    &keytype_des3,
55555682Smarkm    &keytype_arcfour
55655682Smarkm};
55755682Smarkm
55855682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
55955682Smarkm
56055682Smarkmstatic struct key_type *
56155682Smarkm_find_keytype(krb5_keytype type)
56255682Smarkm{
56355682Smarkm    int i;
56455682Smarkm    for(i = 0; i < num_keytypes; i++)
56555682Smarkm	if(keytypes[i]->type == type)
56655682Smarkm	    return keytypes[i];
56755682Smarkm    return NULL;
56855682Smarkm}
56955682Smarkm
57055682Smarkm
57155682Smarkmstruct salt_type des_salt[] = {
57255682Smarkm    {
57355682Smarkm	KRB5_PW_SALT,
57455682Smarkm	"pw-salt",
575102647Snectar	krb5_DES_string_to_key
57655682Smarkm    },
57755682Smarkm    {
57855682Smarkm	KRB5_AFS3_SALT,
57955682Smarkm	"afs3-salt",
58055682Smarkm	DES_AFS3_string_to_key
58155682Smarkm    },
58255682Smarkm    { 0 }
58355682Smarkm};
58455682Smarkm
58555682Smarkmstruct salt_type des3_salt[] = {
58655682Smarkm    {
58755682Smarkm	KRB5_PW_SALT,
58855682Smarkm	"pw-salt",
58955682Smarkm	DES3_string_to_key
59055682Smarkm    },
59155682Smarkm    { 0 }
59255682Smarkm};
59355682Smarkm
59455682Smarkmstruct salt_type des3_salt_derived[] = {
59555682Smarkm    {
59655682Smarkm	KRB5_PW_SALT,
59755682Smarkm	"pw-salt",
59855682Smarkm	DES3_string_to_key_derived
59955682Smarkm    },
60055682Smarkm    { 0 }
60155682Smarkm};
60255682Smarkm
60355682Smarkmstruct salt_type arcfour_salt[] = {
60455682Smarkm    {
60555682Smarkm	KRB5_PW_SALT,
60655682Smarkm	"pw-salt",
60755682Smarkm	ARCFOUR_string_to_key
60855682Smarkm    },
60955682Smarkm    { 0 }
61055682Smarkm};
61155682Smarkm
61255682Smarkmkrb5_error_code
61355682Smarkmkrb5_salttype_to_string (krb5_context context,
61455682Smarkm			 krb5_enctype etype,
61555682Smarkm			 krb5_salttype stype,
61655682Smarkm			 char **string)
61755682Smarkm{
61855682Smarkm    struct encryption_type *e;
61955682Smarkm    struct salt_type *st;
62055682Smarkm
62155682Smarkm    e = _find_enctype (etype);
62278536Sassar    if (e == NULL) {
62378536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
62478536Sassar			      etype);
62555682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
62678536Sassar    }
62755682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
62855682Smarkm	if (st->type == stype) {
62955682Smarkm	    *string = strdup (st->name);
63078536Sassar	    if (*string == NULL) {
63178536Sassar		krb5_set_error_string(context, "malloc: out of memory");
63255682Smarkm		return ENOMEM;
63378536Sassar	    }
63455682Smarkm	    return 0;
63555682Smarkm	}
63655682Smarkm    }
63778536Sassar    krb5_set_error_string(context, "salttype %d not supported", stype);
63855682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
63955682Smarkm}
64055682Smarkm
64155682Smarkmkrb5_error_code
64255682Smarkmkrb5_string_to_salttype (krb5_context context,
64355682Smarkm			 krb5_enctype etype,
64455682Smarkm			 const char *string,
64555682Smarkm			 krb5_salttype *salttype)
64655682Smarkm{
64755682Smarkm    struct encryption_type *e;
64855682Smarkm    struct salt_type *st;
64955682Smarkm
65055682Smarkm    e = _find_enctype (etype);
65178536Sassar    if (e == NULL) {
65278536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
65378536Sassar			      etype);
65455682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
65578536Sassar    }
65655682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
65755682Smarkm	if (strcasecmp (st->name, string) == 0) {
65855682Smarkm	    *salttype = st->type;
65955682Smarkm	    return 0;
66055682Smarkm	}
66155682Smarkm    }
66278536Sassar    krb5_set_error_string(context, "salttype %s not supported", string);
66355682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
66455682Smarkm}
66555682Smarkm
66655682Smarkmkrb5_error_code
66755682Smarkmkrb5_get_pw_salt(krb5_context context,
66855682Smarkm		 krb5_const_principal principal,
66955682Smarkm		 krb5_salt *salt)
67055682Smarkm{
67155682Smarkm    size_t len;
67255682Smarkm    int i;
67355682Smarkm    krb5_error_code ret;
67455682Smarkm    char *p;
67555682Smarkm
67655682Smarkm    salt->salttype = KRB5_PW_SALT;
67755682Smarkm    len = strlen(principal->realm);
67855682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i)
67955682Smarkm	len += strlen(principal->name.name_string.val[i]);
68055682Smarkm    ret = krb5_data_alloc (&salt->saltvalue, len);
68155682Smarkm    if (ret)
68255682Smarkm	return ret;
68355682Smarkm    p = salt->saltvalue.data;
68455682Smarkm    memcpy (p, principal->realm, strlen(principal->realm));
68555682Smarkm    p += strlen(principal->realm);
68655682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i) {
68755682Smarkm	memcpy (p,
68855682Smarkm		principal->name.name_string.val[i],
68955682Smarkm		strlen(principal->name.name_string.val[i]));
69055682Smarkm	p += strlen(principal->name.name_string.val[i]);
69155682Smarkm    }
69255682Smarkm    return 0;
69355682Smarkm}
69455682Smarkm
69555682Smarkmkrb5_error_code
69655682Smarkmkrb5_free_salt(krb5_context context,
69755682Smarkm	       krb5_salt salt)
69855682Smarkm{
69955682Smarkm    krb5_data_free(&salt.saltvalue);
70055682Smarkm    return 0;
70155682Smarkm}
70255682Smarkm
70355682Smarkmkrb5_error_code
70455682Smarkmkrb5_string_to_key_data (krb5_context context,
70555682Smarkm			 krb5_enctype enctype,
70655682Smarkm			 krb5_data password,
70755682Smarkm			 krb5_principal principal,
70855682Smarkm			 krb5_keyblock *key)
70955682Smarkm{
71055682Smarkm    krb5_error_code ret;
71155682Smarkm    krb5_salt salt;
71255682Smarkm
71355682Smarkm    ret = krb5_get_pw_salt(context, principal, &salt);
71455682Smarkm    if(ret)
71555682Smarkm	return ret;
71655682Smarkm    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
71755682Smarkm    krb5_free_salt(context, salt);
71855682Smarkm    return ret;
71955682Smarkm}
72055682Smarkm
72155682Smarkmkrb5_error_code
72255682Smarkmkrb5_string_to_key (krb5_context context,
72355682Smarkm		    krb5_enctype enctype,
72455682Smarkm		    const char *password,
72555682Smarkm		    krb5_principal principal,
72655682Smarkm		    krb5_keyblock *key)
72755682Smarkm{
72855682Smarkm    krb5_data pw;
72955682Smarkm    pw.data = (void*)password;
73055682Smarkm    pw.length = strlen(password);
73155682Smarkm    return krb5_string_to_key_data(context, enctype, pw, principal, key);
73255682Smarkm}
73355682Smarkm
73472448Sassar/*
73572448Sassar * Do a string -> key for encryption type `enctype' operation on
73672448Sassar * `password' (with salt `salt'), returning the resulting key in `key'
73772448Sassar */
73872448Sassar
73955682Smarkmkrb5_error_code
74055682Smarkmkrb5_string_to_key_data_salt (krb5_context context,
74155682Smarkm			      krb5_enctype enctype,
74255682Smarkm			      krb5_data password,
74355682Smarkm			      krb5_salt salt,
74455682Smarkm			      krb5_keyblock *key)
74555682Smarkm{
74655682Smarkm    struct encryption_type *et =_find_enctype(enctype);
74755682Smarkm    struct salt_type *st;
74878536Sassar    if(et == NULL) {
74978536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
75078536Sassar			      enctype);
75155682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
75278536Sassar    }
75355682Smarkm    for(st = et->keytype->string_to_key; st && st->type; st++)
75455682Smarkm	if(st->type == salt.salttype)
75555682Smarkm	    return (*st->string_to_key)(context, enctype, password, salt, key);
75678536Sassar    krb5_set_error_string(context, "salt type %d not supported",
75778536Sassar			  salt.salttype);
75855682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
75955682Smarkm}
76055682Smarkm
76172448Sassar/*
76272448Sassar * Do a string -> key for encryption type `enctype' operation on the
76372448Sassar * string `password' (with salt `salt'), returning the resulting key
76472448Sassar * in `key'
76572448Sassar */
76672448Sassar
76755682Smarkmkrb5_error_code
76855682Smarkmkrb5_string_to_key_salt (krb5_context context,
76955682Smarkm			 krb5_enctype enctype,
77055682Smarkm			 const char *password,
77155682Smarkm			 krb5_salt salt,
77255682Smarkm			 krb5_keyblock *key)
77355682Smarkm{
77455682Smarkm    krb5_data pw;
77555682Smarkm    pw.data = (void*)password;
77655682Smarkm    pw.length = strlen(password);
77755682Smarkm    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
77855682Smarkm}
77955682Smarkm
78055682Smarkmkrb5_error_code
78155682Smarkmkrb5_keytype_to_string(krb5_context context,
78255682Smarkm		       krb5_keytype keytype,
78355682Smarkm		       char **string)
78455682Smarkm{
78555682Smarkm    struct key_type *kt = _find_keytype(keytype);
78678536Sassar    if(kt == NULL) {
78778536Sassar	krb5_set_error_string(context, "key type %d not supported", keytype);
78855682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
78978536Sassar    }
79055682Smarkm    *string = strdup(kt->name);
79178536Sassar    if(*string == NULL) {
79278536Sassar	krb5_set_error_string(context, "malloc: out of memory");
79355682Smarkm	return ENOMEM;
79478536Sassar    }
79555682Smarkm    return 0;
79655682Smarkm}
79755682Smarkm
79855682Smarkmkrb5_error_code
79955682Smarkmkrb5_string_to_keytype(krb5_context context,
80055682Smarkm		       const char *string,
80155682Smarkm		       krb5_keytype *keytype)
80255682Smarkm{
80355682Smarkm    int i;
80455682Smarkm    for(i = 0; i < num_keytypes; i++)
80555682Smarkm	if(strcasecmp(keytypes[i]->name, string) == 0){
80655682Smarkm	    *keytype = keytypes[i]->type;
80755682Smarkm	    return 0;
80855682Smarkm	}
80978536Sassar    krb5_set_error_string(context, "key type %s not supported", string);
81055682Smarkm    return KRB5_PROG_KEYTYPE_NOSUPP;
81155682Smarkm}
81255682Smarkm
81355682Smarkmkrb5_error_code
81455682Smarkmkrb5_generate_random_keyblock(krb5_context context,
81555682Smarkm			      krb5_enctype type,
81655682Smarkm			      krb5_keyblock *key)
81755682Smarkm{
81855682Smarkm    krb5_error_code ret;
81955682Smarkm    struct encryption_type *et = _find_enctype(type);
82078536Sassar    if(et == NULL) {
82178536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
82278536Sassar			      type);
82355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
82478536Sassar    }
82555682Smarkm    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
82655682Smarkm    if(ret)
82755682Smarkm	return ret;
82855682Smarkm    key->keytype = type;
82955682Smarkm    if(et->keytype->random_key)
83055682Smarkm	(*et->keytype->random_key)(context, key);
83155682Smarkm    else
83255682Smarkm	krb5_generate_random_block(key->keyvalue.data,
83355682Smarkm				   key->keyvalue.length);
83455682Smarkm    return 0;
83555682Smarkm}
83655682Smarkm
83755682Smarkmstatic krb5_error_code
83855682Smarkm_key_schedule(krb5_context context,
83955682Smarkm	      struct key_data *key)
84055682Smarkm{
84155682Smarkm    krb5_error_code ret;
84255682Smarkm    struct encryption_type *et = _find_enctype(key->key->keytype);
84355682Smarkm    struct key_type *kt = et->keytype;
84455682Smarkm
84555682Smarkm    if(kt->schedule == NULL)
84655682Smarkm	return 0;
84772448Sassar    if (key->schedule != NULL)
84872448Sassar	return 0;
84955682Smarkm    ALLOC(key->schedule, 1);
85078536Sassar    if(key->schedule == NULL) {
85178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
85255682Smarkm	return ENOMEM;
85378536Sassar    }
85455682Smarkm    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
85555682Smarkm    if(ret) {
85655682Smarkm	free(key->schedule);
85755682Smarkm	key->schedule = NULL;
85855682Smarkm	return ret;
85955682Smarkm    }
86055682Smarkm    (*kt->schedule)(context, key);
86155682Smarkm    return 0;
86255682Smarkm}
86355682Smarkm
86455682Smarkm/************************************************************
86555682Smarkm *                                                          *
86655682Smarkm ************************************************************/
86755682Smarkm
86855682Smarkmstatic void
86955682SmarkmNONE_checksum(krb5_context context,
87055682Smarkm	      struct key_data *key,
87172448Sassar	      const void *data,
87255682Smarkm	      size_t len,
87372448Sassar	      unsigned usage,
87455682Smarkm	      Checksum *C)
87555682Smarkm{
87655682Smarkm}
87755682Smarkm
87855682Smarkmstatic void
87955682SmarkmCRC32_checksum(krb5_context context,
88055682Smarkm	       struct key_data *key,
88172448Sassar	       const void *data,
88255682Smarkm	       size_t len,
88372448Sassar	       unsigned usage,
88455682Smarkm	       Checksum *C)
88555682Smarkm{
88655682Smarkm    u_int32_t crc;
88755682Smarkm    unsigned char *r = C->checksum.data;
88855682Smarkm    _krb5_crc_init_table ();
88955682Smarkm    crc = _krb5_crc_update (data, len, 0);
89055682Smarkm    r[0] = crc & 0xff;
89155682Smarkm    r[1] = (crc >> 8)  & 0xff;
89255682Smarkm    r[2] = (crc >> 16) & 0xff;
89355682Smarkm    r[3] = (crc >> 24) & 0xff;
89455682Smarkm}
89555682Smarkm
89655682Smarkmstatic void
89755682SmarkmRSA_MD4_checksum(krb5_context context,
89855682Smarkm		 struct key_data *key,
89972448Sassar		 const void *data,
90055682Smarkm		 size_t len,
90172448Sassar		 unsigned usage,
90255682Smarkm		 Checksum *C)
90355682Smarkm{
90457416Smarkm    MD4_CTX m;
90557416Smarkm
90672448Sassar    MD4_Init (&m);
90772448Sassar    MD4_Update (&m, data, len);
90872448Sassar    MD4_Final (C->checksum.data, &m);
90955682Smarkm}
91055682Smarkm
91155682Smarkmstatic void
91255682SmarkmRSA_MD4_DES_checksum(krb5_context context,
91355682Smarkm		     struct key_data *key,
91472448Sassar		     const void *data,
91555682Smarkm		     size_t len,
91672448Sassar		     unsigned usage,
91755682Smarkm		     Checksum *cksum)
91855682Smarkm{
91957416Smarkm    MD4_CTX md4;
92055682Smarkm    des_cblock ivec;
92155682Smarkm    unsigned char *p = cksum->checksum.data;
92255682Smarkm
92355682Smarkm    krb5_generate_random_block(p, 8);
92472448Sassar    MD4_Init (&md4);
92572448Sassar    MD4_Update (&md4, p, 8);
92672448Sassar    MD4_Update (&md4, data, len);
92772448Sassar    MD4_Final (p + 8, &md4);
92855682Smarkm    memset (&ivec, 0, sizeof(ivec));
92990929Snectar    des_cbc_encrypt(p,
93090929Snectar		    p,
93155682Smarkm		    24,
93255682Smarkm		    key->schedule->data,
93355682Smarkm		    &ivec,
93455682Smarkm		    DES_ENCRYPT);
93555682Smarkm}
93655682Smarkm
93755682Smarkmstatic krb5_error_code
93855682SmarkmRSA_MD4_DES_verify(krb5_context context,
93955682Smarkm		   struct key_data *key,
94072448Sassar		   const void *data,
94155682Smarkm		   size_t len,
94272448Sassar		   unsigned usage,
94355682Smarkm		   Checksum *C)
94455682Smarkm{
94557416Smarkm    MD4_CTX md4;
94655682Smarkm    unsigned char tmp[24];
94755682Smarkm    unsigned char res[16];
94855682Smarkm    des_cblock ivec;
94955682Smarkm    krb5_error_code ret = 0;
95055682Smarkm
95155682Smarkm    memset(&ivec, 0, sizeof(ivec));
95257416Smarkm    des_cbc_encrypt(C->checksum.data,
95355682Smarkm		    (void*)tmp,
95455682Smarkm		    C->checksum.length,
95555682Smarkm		    key->schedule->data,
95655682Smarkm		    &ivec,
95755682Smarkm		    DES_DECRYPT);
95872448Sassar    MD4_Init (&md4);
95972448Sassar    MD4_Update (&md4, tmp, 8); /* confounder */
96072448Sassar    MD4_Update (&md4, data, len);
96172448Sassar    MD4_Final (res, &md4);
96278536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
96378536Sassar	krb5_clear_error_string (context);
96455682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
96578536Sassar    }
96655682Smarkm    memset(tmp, 0, sizeof(tmp));
96755682Smarkm    memset(res, 0, sizeof(res));
96855682Smarkm    return ret;
96955682Smarkm}
97055682Smarkm
97155682Smarkmstatic void
97255682SmarkmRSA_MD5_checksum(krb5_context context,
97355682Smarkm		 struct key_data *key,
97472448Sassar		 const void *data,
97555682Smarkm		 size_t len,
97672448Sassar		 unsigned usage,
97755682Smarkm		 Checksum *C)
97855682Smarkm{
97957416Smarkm    MD5_CTX m;
98057416Smarkm
98172448Sassar    MD5_Init  (&m);
98272448Sassar    MD5_Update(&m, data, len);
98372448Sassar    MD5_Final (C->checksum.data, &m);
98455682Smarkm}
98555682Smarkm
98655682Smarkmstatic void
98755682SmarkmRSA_MD5_DES_checksum(krb5_context context,
98855682Smarkm		     struct key_data *key,
98972448Sassar		     const void *data,
99055682Smarkm		     size_t len,
99172448Sassar		     unsigned usage,
99255682Smarkm		     Checksum *C)
99355682Smarkm{
99457416Smarkm    MD5_CTX md5;
99555682Smarkm    des_cblock ivec;
99655682Smarkm    unsigned char *p = C->checksum.data;
99755682Smarkm
99855682Smarkm    krb5_generate_random_block(p, 8);
99972448Sassar    MD5_Init (&md5);
100072448Sassar    MD5_Update (&md5, p, 8);
100172448Sassar    MD5_Update (&md5, data, len);
100272448Sassar    MD5_Final (p + 8, &md5);
100355682Smarkm    memset (&ivec, 0, sizeof(ivec));
100490929Snectar    des_cbc_encrypt(p,
100590929Snectar		    p,
100655682Smarkm		    24,
100755682Smarkm		    key->schedule->data,
100855682Smarkm		    &ivec,
100955682Smarkm		    DES_ENCRYPT);
101055682Smarkm}
101155682Smarkm
101255682Smarkmstatic krb5_error_code
101355682SmarkmRSA_MD5_DES_verify(krb5_context context,
101455682Smarkm		   struct key_data *key,
101572448Sassar		   const void *data,
101655682Smarkm		   size_t len,
101772448Sassar		   unsigned usage,
101855682Smarkm		   Checksum *C)
101955682Smarkm{
102057416Smarkm    MD5_CTX md5;
102155682Smarkm    unsigned char tmp[24];
102255682Smarkm    unsigned char res[16];
102355682Smarkm    des_cblock ivec;
102455682Smarkm    des_key_schedule *sched = key->schedule->data;
102555682Smarkm    krb5_error_code ret = 0;
102655682Smarkm
102755682Smarkm    memset(&ivec, 0, sizeof(ivec));
102855682Smarkm    des_cbc_encrypt(C->checksum.data,
102955682Smarkm		    (void*)tmp,
103055682Smarkm		    C->checksum.length,
103155682Smarkm		    sched[0],
103255682Smarkm		    &ivec,
103355682Smarkm		    DES_DECRYPT);
103472448Sassar    MD5_Init (&md5);
103572448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
103672448Sassar    MD5_Update (&md5, data, len);
103772448Sassar    MD5_Final (res, &md5);
103878536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
103978536Sassar	krb5_clear_error_string (context);
104055682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
104178536Sassar    }
104255682Smarkm    memset(tmp, 0, sizeof(tmp));
104355682Smarkm    memset(res, 0, sizeof(res));
104455682Smarkm    return ret;
104555682Smarkm}
104655682Smarkm
104755682Smarkmstatic void
104855682SmarkmRSA_MD5_DES3_checksum(krb5_context context,
104955682Smarkm		      struct key_data *key,
105072448Sassar		      const void *data,
105155682Smarkm		      size_t len,
105272448Sassar		      unsigned usage,
105355682Smarkm		      Checksum *C)
105455682Smarkm{
105557416Smarkm    MD5_CTX md5;
105655682Smarkm    des_cblock ivec;
105755682Smarkm    unsigned char *p = C->checksum.data;
105855682Smarkm    des_key_schedule *sched = key->schedule->data;
105955682Smarkm
106055682Smarkm    krb5_generate_random_block(p, 8);
106172448Sassar    MD5_Init (&md5);
106272448Sassar    MD5_Update (&md5, p, 8);
106372448Sassar    MD5_Update (&md5, data, len);
106472448Sassar    MD5_Final (p + 8, &md5);
106555682Smarkm    memset (&ivec, 0, sizeof(ivec));
106690929Snectar    des_ede3_cbc_encrypt(p,
106790929Snectar			 p,
106855682Smarkm			 24,
106955682Smarkm			 sched[0], sched[1], sched[2],
107055682Smarkm			 &ivec,
107155682Smarkm			 DES_ENCRYPT);
107255682Smarkm}
107355682Smarkm
107455682Smarkmstatic krb5_error_code
107555682SmarkmRSA_MD5_DES3_verify(krb5_context context,
107655682Smarkm		    struct key_data *key,
107772448Sassar		    const void *data,
107855682Smarkm		    size_t len,
107972448Sassar		    unsigned usage,
108055682Smarkm		    Checksum *C)
108155682Smarkm{
108257416Smarkm    MD5_CTX md5;
108355682Smarkm    unsigned char tmp[24];
108455682Smarkm    unsigned char res[16];
108555682Smarkm    des_cblock ivec;
108655682Smarkm    des_key_schedule *sched = key->schedule->data;
108755682Smarkm    krb5_error_code ret = 0;
108855682Smarkm
108955682Smarkm    memset(&ivec, 0, sizeof(ivec));
109055682Smarkm    des_ede3_cbc_encrypt(C->checksum.data,
109155682Smarkm			 (void*)tmp,
109255682Smarkm			 C->checksum.length,
109355682Smarkm			 sched[0], sched[1], sched[2],
109455682Smarkm			 &ivec,
109555682Smarkm			 DES_DECRYPT);
109672448Sassar    MD5_Init (&md5);
109772448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
109872448Sassar    MD5_Update (&md5, data, len);
109972448Sassar    MD5_Final (res, &md5);
110078536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
110178536Sassar	krb5_clear_error_string (context);
110255682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
110378536Sassar    }
110455682Smarkm    memset(tmp, 0, sizeof(tmp));
110555682Smarkm    memset(res, 0, sizeof(res));
110655682Smarkm    return ret;
110755682Smarkm}
110855682Smarkm
110955682Smarkmstatic void
111055682SmarkmSHA1_checksum(krb5_context context,
111155682Smarkm	      struct key_data *key,
111272448Sassar	      const void *data,
111355682Smarkm	      size_t len,
111472448Sassar	      unsigned usage,
111555682Smarkm	      Checksum *C)
111655682Smarkm{
111772448Sassar    SHA_CTX m;
111857416Smarkm
111972448Sassar    SHA1_Init(&m);
112072448Sassar    SHA1_Update(&m, data, len);
112172448Sassar    SHA1_Final(C->checksum.data, &m);
112255682Smarkm}
112355682Smarkm
112455682Smarkm/* HMAC according to RFC2104 */
112555682Smarkmstatic void
112655682Smarkmhmac(krb5_context context,
112755682Smarkm     struct checksum_type *cm,
112872448Sassar     const void *data,
112955682Smarkm     size_t len,
113072448Sassar     unsigned usage,
113155682Smarkm     struct key_data *keyblock,
113255682Smarkm     Checksum *result)
113355682Smarkm{
113455682Smarkm    unsigned char *ipad, *opad;
113555682Smarkm    unsigned char *key;
113655682Smarkm    size_t key_len;
113755682Smarkm    int i;
113855682Smarkm
113955682Smarkm    if(keyblock->key->keyvalue.length > cm->blocksize){
114055682Smarkm	(*cm->checksum)(context,
114155682Smarkm			keyblock,
114255682Smarkm			keyblock->key->keyvalue.data,
114355682Smarkm			keyblock->key->keyvalue.length,
114472448Sassar			usage,
114555682Smarkm			result);
114655682Smarkm	key = result->checksum.data;
114755682Smarkm	key_len = result->checksum.length;
114855682Smarkm    } else {
114955682Smarkm	key = keyblock->key->keyvalue.data;
115055682Smarkm	key_len = keyblock->key->keyvalue.length;
115155682Smarkm    }
115255682Smarkm    ipad = malloc(cm->blocksize + len);
115355682Smarkm    opad = malloc(cm->blocksize + cm->checksumsize);
115455682Smarkm    memset(ipad, 0x36, cm->blocksize);
115555682Smarkm    memset(opad, 0x5c, cm->blocksize);
115655682Smarkm    for(i = 0; i < key_len; i++){
115755682Smarkm	ipad[i] ^= key[i];
115855682Smarkm	opad[i] ^= key[i];
115955682Smarkm    }
116055682Smarkm    memcpy(ipad + cm->blocksize, data, len);
116172448Sassar    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
116272448Sassar		    usage, result);
116355682Smarkm    memcpy(opad + cm->blocksize, result->checksum.data,
116455682Smarkm	   result->checksum.length);
116555682Smarkm    (*cm->checksum)(context, keyblock, opad,
116672448Sassar		    cm->blocksize + cm->checksumsize, usage, result);
116755682Smarkm    memset(ipad, 0, cm->blocksize + len);
116855682Smarkm    free(ipad);
116955682Smarkm    memset(opad, 0, cm->blocksize + cm->checksumsize);
117055682Smarkm    free(opad);
117155682Smarkm}
117255682Smarkm
117355682Smarkmstatic void
117455682SmarkmHMAC_SHA1_DES3_checksum(krb5_context context,
117555682Smarkm			struct key_data *key,
117672448Sassar			const void *data,
117755682Smarkm			size_t len,
117872448Sassar			unsigned usage,
117955682Smarkm			Checksum *result)
118055682Smarkm{
118155682Smarkm    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
118255682Smarkm
118372448Sassar    hmac(context, c, data, len, usage, key, result);
118455682Smarkm}
118555682Smarkm
118672448Sassar/*
118772448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
118872448Sassar */
118972448Sassar
119072448Sassarstatic void
119172448SassarHMAC_MD5_checksum(krb5_context context,
119272448Sassar		  struct key_data *key,
119372448Sassar		  const void *data,
119472448Sassar		  size_t len,
119572448Sassar		  unsigned usage,
119672448Sassar		  Checksum *result)
119772448Sassar{
119872448Sassar    MD5_CTX md5;
119972448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
120072448Sassar    const char signature[] = "signaturekey";
120172448Sassar    Checksum ksign_c;
120272448Sassar    struct key_data ksign;
120372448Sassar    krb5_keyblock kb;
120472448Sassar    unsigned char t[4];
120572448Sassar    unsigned char tmp[16];
120672448Sassar    unsigned char ksign_c_data[16];
120772448Sassar
120872448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
120972448Sassar    ksign_c.checksum.data   = ksign_c_data;
121072448Sassar    hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
121172448Sassar    ksign.key = &kb;
121272448Sassar    kb.keyvalue = ksign_c.checksum;
121372448Sassar    MD5_Init (&md5);
121472448Sassar    t[0] = (usage >>  0) & 0xFF;
121572448Sassar    t[1] = (usage >>  8) & 0xFF;
121672448Sassar    t[2] = (usage >> 16) & 0xFF;
121772448Sassar    t[3] = (usage >> 24) & 0xFF;
121872448Sassar    MD5_Update (&md5, t, 4);
121972448Sassar    MD5_Update (&md5, data, len);
122072448Sassar    MD5_Final (tmp, &md5);
122172448Sassar    hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
122272448Sassar}
122372448Sassar
122472448Sassar/*
122572448Sassar * same as previous but being used while encrypting.
122672448Sassar */
122772448Sassar
122872448Sassarstatic void
122972448SassarHMAC_MD5_checksum_enc(krb5_context context,
123072448Sassar		      struct key_data *key,
123172448Sassar		      const void *data,
123272448Sassar		      size_t len,
123372448Sassar		      unsigned usage,
123472448Sassar		      Checksum *result)
123572448Sassar{
123672448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
123772448Sassar    Checksum ksign_c;
123872448Sassar    struct key_data ksign;
123972448Sassar    krb5_keyblock kb;
124072448Sassar    unsigned char t[4];
124172448Sassar    unsigned char ksign_c_data[16];
124272448Sassar
124372448Sassar    t[0] = (usage >>  0) & 0xFF;
124472448Sassar    t[1] = (usage >>  8) & 0xFF;
124572448Sassar    t[2] = (usage >> 16) & 0xFF;
124672448Sassar    t[3] = (usage >> 24) & 0xFF;
124772448Sassar
124872448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
124972448Sassar    ksign_c.checksum.data   = ksign_c_data;
125072448Sassar    hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
125172448Sassar    ksign.key = &kb;
125272448Sassar    kb.keyvalue = ksign_c.checksum;
125372448Sassar    hmac(context, c, data, len, 0, &ksign, result);
125472448Sassar}
125572448Sassar
125655682Smarkmstruct checksum_type checksum_none = {
125755682Smarkm    CKSUMTYPE_NONE,
125855682Smarkm    "none",
125955682Smarkm    1,
126055682Smarkm    0,
126155682Smarkm    0,
126255682Smarkm    NONE_checksum,
126355682Smarkm    NULL
126455682Smarkm};
126555682Smarkmstruct checksum_type checksum_crc32 = {
126655682Smarkm    CKSUMTYPE_CRC32,
126755682Smarkm    "crc32",
126855682Smarkm    1,
126955682Smarkm    4,
127055682Smarkm    0,
127155682Smarkm    CRC32_checksum,
127255682Smarkm    NULL
127355682Smarkm};
127455682Smarkmstruct checksum_type checksum_rsa_md4 = {
127555682Smarkm    CKSUMTYPE_RSA_MD4,
127655682Smarkm    "rsa-md4",
127755682Smarkm    64,
127855682Smarkm    16,
127955682Smarkm    F_CPROOF,
128055682Smarkm    RSA_MD4_checksum,
128155682Smarkm    NULL
128255682Smarkm};
128355682Smarkmstruct checksum_type checksum_rsa_md4_des = {
128455682Smarkm    CKSUMTYPE_RSA_MD4_DES,
128555682Smarkm    "rsa-md4-des",
128655682Smarkm    64,
128755682Smarkm    24,
128855682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
128955682Smarkm    RSA_MD4_DES_checksum,
129055682Smarkm    RSA_MD4_DES_verify
129155682Smarkm};
129255682Smarkm#if 0
129355682Smarkmstruct checksum_type checksum_des_mac = {
129455682Smarkm    CKSUMTYPE_DES_MAC,
129555682Smarkm    "des-mac",
129655682Smarkm    0,
129755682Smarkm    0,
129855682Smarkm    0,
129972448Sassar    DES_MAC_checksum
130055682Smarkm};
130155682Smarkmstruct checksum_type checksum_des_mac_k = {
130255682Smarkm    CKSUMTYPE_DES_MAC_K,
130355682Smarkm    "des-mac-k",
130455682Smarkm    0,
130555682Smarkm    0,
130655682Smarkm    0,
130772448Sassar    DES_MAC_K_checksum
130855682Smarkm};
130955682Smarkmstruct checksum_type checksum_rsa_md4_des_k = {
131055682Smarkm    CKSUMTYPE_RSA_MD4_DES_K,
131155682Smarkm    "rsa-md4-des-k",
131255682Smarkm    0,
131355682Smarkm    0,
131455682Smarkm    0,
131572448Sassar    RSA_MD4_DES_K_checksum,
131672448Sassar    RSA_MD4_DES_K_verify
131755682Smarkm};
131855682Smarkm#endif
131955682Smarkmstruct checksum_type checksum_rsa_md5 = {
132055682Smarkm    CKSUMTYPE_RSA_MD5,
132155682Smarkm    "rsa-md5",
132255682Smarkm    64,
132355682Smarkm    16,
132455682Smarkm    F_CPROOF,
132555682Smarkm    RSA_MD5_checksum,
132655682Smarkm    NULL
132755682Smarkm};
132855682Smarkmstruct checksum_type checksum_rsa_md5_des = {
132955682Smarkm    CKSUMTYPE_RSA_MD5_DES,
133055682Smarkm    "rsa-md5-des",
133155682Smarkm    64,
133255682Smarkm    24,
133355682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
133455682Smarkm    RSA_MD5_DES_checksum,
133572448Sassar    RSA_MD5_DES_verify
133655682Smarkm};
133755682Smarkmstruct checksum_type checksum_rsa_md5_des3 = {
133855682Smarkm    CKSUMTYPE_RSA_MD5_DES3,
133955682Smarkm    "rsa-md5-des3",
134055682Smarkm    64,
134155682Smarkm    24,
134255682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
134355682Smarkm    RSA_MD5_DES3_checksum,
134472448Sassar    RSA_MD5_DES3_verify
134555682Smarkm};
134655682Smarkmstruct checksum_type checksum_sha1 = {
134755682Smarkm    CKSUMTYPE_SHA1,
134855682Smarkm    "sha1",
134955682Smarkm    64,
135055682Smarkm    20,
135155682Smarkm    F_CPROOF,
135255682Smarkm    SHA1_checksum,
135355682Smarkm    NULL
135455682Smarkm};
135555682Smarkmstruct checksum_type checksum_hmac_sha1_des3 = {
135655682Smarkm    CKSUMTYPE_HMAC_SHA1_DES3,
135755682Smarkm    "hmac-sha1-des3",
135855682Smarkm    64,
135955682Smarkm    20,
136055682Smarkm    F_KEYED | F_CPROOF | F_DERIVED,
136155682Smarkm    HMAC_SHA1_DES3_checksum,
136255682Smarkm    NULL
136355682Smarkm};
136455682Smarkm
136572448Sassarstruct checksum_type checksum_hmac_md5 = {
136672448Sassar    CKSUMTYPE_HMAC_MD5,
136772448Sassar    "hmac-md5",
136872448Sassar    64,
136972448Sassar    16,
137072448Sassar    F_KEYED | F_CPROOF,
137172448Sassar    HMAC_MD5_checksum,
137272448Sassar    NULL
137372448Sassar};
137472448Sassar
137572448Sassarstruct checksum_type checksum_hmac_md5_enc = {
137672448Sassar    CKSUMTYPE_HMAC_MD5_ENC,
137772448Sassar    "hmac-md5-enc",
137872448Sassar    64,
137972448Sassar    16,
138072448Sassar    F_KEYED | F_CPROOF | F_PSEUDO,
138172448Sassar    HMAC_MD5_checksum_enc,
138272448Sassar    NULL
138372448Sassar};
138472448Sassar
138555682Smarkmstruct checksum_type *checksum_types[] = {
138655682Smarkm    &checksum_none,
138755682Smarkm    &checksum_crc32,
138855682Smarkm    &checksum_rsa_md4,
138955682Smarkm    &checksum_rsa_md4_des,
139055682Smarkm#if 0
139155682Smarkm    &checksum_des_mac,
139255682Smarkm    &checksum_des_mac_k,
139355682Smarkm    &checksum_rsa_md4_des_k,
139455682Smarkm#endif
139555682Smarkm    &checksum_rsa_md5,
139655682Smarkm    &checksum_rsa_md5_des,
139755682Smarkm    &checksum_rsa_md5_des3,
139855682Smarkm    &checksum_sha1,
139972448Sassar    &checksum_hmac_sha1_des3,
140072448Sassar    &checksum_hmac_md5,
140172448Sassar    &checksum_hmac_md5_enc
140255682Smarkm};
140355682Smarkm
140455682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
140555682Smarkm
140655682Smarkmstatic struct checksum_type *
140755682Smarkm_find_checksum(krb5_cksumtype type)
140855682Smarkm{
140955682Smarkm    int i;
141055682Smarkm    for(i = 0; i < num_checksums; i++)
141155682Smarkm	if(checksum_types[i]->type == type)
141255682Smarkm	    return checksum_types[i];
141355682Smarkm    return NULL;
141455682Smarkm}
141555682Smarkm
141655682Smarkmstatic krb5_error_code
141755682Smarkmget_checksum_key(krb5_context context,
141855682Smarkm		 krb5_crypto crypto,
141955682Smarkm		 unsigned usage,  /* not krb5_key_usage */
142055682Smarkm		 struct checksum_type *ct,
142155682Smarkm		 struct key_data **key)
142255682Smarkm{
142355682Smarkm    krb5_error_code ret = 0;
142455682Smarkm
142555682Smarkm    if(ct->flags & F_DERIVED)
142655682Smarkm	ret = _get_derived_key(context, crypto, usage, key);
142755682Smarkm    else if(ct->flags & F_VARIANT) {
142855682Smarkm	int i;
142955682Smarkm
143055682Smarkm	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
143178536Sassar	if(*key == NULL) {
143278536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
143355682Smarkm	    return ENOMEM;
143478536Sassar	}
143555682Smarkm	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
143655682Smarkm	if(ret)
143755682Smarkm	    return ret;
143855682Smarkm	for(i = 0; i < (*key)->key->keyvalue.length; i++)
143955682Smarkm	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
144055682Smarkm    } else {
144155682Smarkm	*key = &crypto->key;
144255682Smarkm    }
144355682Smarkm    if(ret == 0)
144455682Smarkm	ret = _key_schedule(context, *key);
144555682Smarkm    return ret;
144655682Smarkm}
144755682Smarkm
144855682Smarkmstatic krb5_error_code
144955682Smarkmdo_checksum (krb5_context context,
145055682Smarkm	     struct checksum_type *ct,
145155682Smarkm	     krb5_crypto crypto,
145255682Smarkm	     unsigned usage,
145355682Smarkm	     void *data,
145455682Smarkm	     size_t len,
145555682Smarkm	     Checksum *result)
145655682Smarkm{
145755682Smarkm    krb5_error_code ret;
145855682Smarkm    struct key_data *dkey;
145955682Smarkm    int keyed_checksum;
146055682Smarkm
146155682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
146278536Sassar    if(keyed_checksum && crypto == NULL) {
146378536Sassar	krb5_clear_error_string (context);
146455682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
146578536Sassar    }
146672448Sassar    if(keyed_checksum) {
146755682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
146872448Sassar	if (ret)
146972448Sassar	    return ret;
147072448Sassar    } else
147155682Smarkm	dkey = NULL;
147255682Smarkm    result->cksumtype = ct->type;
147355682Smarkm    krb5_data_alloc(&result->checksum, ct->checksumsize);
147472448Sassar    (*ct->checksum)(context, dkey, data, len, usage, result);
147555682Smarkm    return 0;
147655682Smarkm}
147755682Smarkm
147855682Smarkmstatic krb5_error_code
147955682Smarkmcreate_checksum(krb5_context context,
148055682Smarkm		krb5_crypto crypto,
148190929Snectar		unsigned usage, /* not krb5_key_usage */
148278536Sassar		krb5_cksumtype type, /* 0 -> pick from crypto */
148355682Smarkm		void *data,
148455682Smarkm		size_t len,
148555682Smarkm		Checksum *result)
148655682Smarkm{
148778536Sassar    struct checksum_type *ct = NULL;
148855682Smarkm
148978536Sassar    if (type) {
149078536Sassar	ct = _find_checksum(type);
149178536Sassar    } else if (crypto) {
149255682Smarkm	ct = crypto->et->keyed_checksum;
149378536Sassar	if (ct == NULL)
149478536Sassar	    ct = crypto->et->checksum;
149578536Sassar    }
149678536Sassar
149778536Sassar    if(ct == NULL) {
149878536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
149978536Sassar			       type);
150055682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
150178536Sassar    }
150255682Smarkm    return do_checksum (context, ct, crypto, usage, data, len, result);
150355682Smarkm}
150455682Smarkm
150555682Smarkmkrb5_error_code
150655682Smarkmkrb5_create_checksum(krb5_context context,
150755682Smarkm		     krb5_crypto crypto,
150878536Sassar		     krb5_key_usage usage,
150978536Sassar		     int type,
151055682Smarkm		     void *data,
151155682Smarkm		     size_t len,
151255682Smarkm		     Checksum *result)
151355682Smarkm{
151455682Smarkm    return create_checksum(context, crypto,
151578536Sassar			   CHECKSUM_USAGE(usage),
151678536Sassar			   type, data, len, result);
151755682Smarkm}
151855682Smarkm
151955682Smarkmstatic krb5_error_code
152055682Smarkmverify_checksum(krb5_context context,
152155682Smarkm		krb5_crypto crypto,
152255682Smarkm		unsigned usage, /* not krb5_key_usage */
152355682Smarkm		void *data,
152455682Smarkm		size_t len,
152555682Smarkm		Checksum *cksum)
152655682Smarkm{
152755682Smarkm    krb5_error_code ret;
152855682Smarkm    struct key_data *dkey;
152955682Smarkm    int keyed_checksum;
153055682Smarkm    Checksum c;
153155682Smarkm    struct checksum_type *ct;
153255682Smarkm
153355682Smarkm    ct = _find_checksum(cksum->cksumtype);
153478536Sassar    if(ct == NULL) {
153578536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
153678536Sassar			       cksum->cksumtype);
153755682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
153878536Sassar    }
153978536Sassar    if(ct->checksumsize != cksum->checksum.length) {
154078536Sassar	krb5_clear_error_string (context);
154155682Smarkm	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
154278536Sassar    }
154355682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
154478536Sassar    if(keyed_checksum && crypto == NULL) {
154578536Sassar	krb5_clear_error_string (context);
154655682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
154778536Sassar    }
154855682Smarkm    if(keyed_checksum)
154955682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
155055682Smarkm    else
155155682Smarkm	dkey = NULL;
155255682Smarkm    if(ct->verify)
155372448Sassar	return (*ct->verify)(context, dkey, data, len, usage, cksum);
155455682Smarkm
155555682Smarkm    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
155655682Smarkm    if (ret)
155755682Smarkm	return ret;
155855682Smarkm
155972448Sassar    (*ct->checksum)(context, dkey, data, len, usage, &c);
156055682Smarkm
156155682Smarkm    if(c.checksum.length != cksum->checksum.length ||
156278536Sassar       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
156378536Sassar	krb5_clear_error_string (context);
156455682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
156578536Sassar    } else {
156655682Smarkm	ret = 0;
156778536Sassar    }
156855682Smarkm    krb5_data_free (&c.checksum);
156955682Smarkm    return ret;
157055682Smarkm}
157155682Smarkm
157255682Smarkmkrb5_error_code
157355682Smarkmkrb5_verify_checksum(krb5_context context,
157455682Smarkm		     krb5_crypto crypto,
157555682Smarkm		     krb5_key_usage usage,
157655682Smarkm		     void *data,
157755682Smarkm		     size_t len,
157855682Smarkm		     Checksum *cksum)
157955682Smarkm{
158055682Smarkm    return verify_checksum(context, crypto,
158155682Smarkm			   CHECKSUM_USAGE(usage), data, len, cksum);
158255682Smarkm}
158355682Smarkm
158455682Smarkmkrb5_error_code
158555682Smarkmkrb5_checksumsize(krb5_context context,
158655682Smarkm		  krb5_cksumtype type,
158755682Smarkm		  size_t *size)
158855682Smarkm{
158955682Smarkm    struct checksum_type *ct = _find_checksum(type);
159078536Sassar    if(ct == NULL) {
159178536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
159278536Sassar			       type);
159355682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
159478536Sassar    }
159555682Smarkm    *size = ct->checksumsize;
159655682Smarkm    return 0;
159755682Smarkm}
159855682Smarkm
159955682Smarkmkrb5_boolean
160055682Smarkmkrb5_checksum_is_keyed(krb5_context context,
160155682Smarkm		       krb5_cksumtype type)
160255682Smarkm{
160355682Smarkm    struct checksum_type *ct = _find_checksum(type);
160478536Sassar    if(ct == NULL) {
160578536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
160678536Sassar			       type);
160755682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
160878536Sassar    }
160955682Smarkm    return ct->flags & F_KEYED;
161055682Smarkm}
161155682Smarkm
161255682Smarkmkrb5_boolean
161355682Smarkmkrb5_checksum_is_collision_proof(krb5_context context,
161455682Smarkm				 krb5_cksumtype type)
161555682Smarkm{
161655682Smarkm    struct checksum_type *ct = _find_checksum(type);
161778536Sassar    if(ct == NULL) {
161878536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
161978536Sassar			       type);
162055682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
162178536Sassar    }
162255682Smarkm    return ct->flags & F_CPROOF;
162355682Smarkm}
162455682Smarkm
162555682Smarkm/************************************************************
162655682Smarkm *                                                          *
162755682Smarkm ************************************************************/
162855682Smarkm
162972448Sassarstatic krb5_error_code
163078536SassarNULL_encrypt(krb5_context context,
163178536Sassar	     struct key_data *key,
163255682Smarkm	     void *data,
163355682Smarkm	     size_t len,
163472448Sassar	     krb5_boolean encrypt,
163572448Sassar	     int usage,
163672448Sassar	     void *ivec)
163755682Smarkm{
163872448Sassar    return 0;
163955682Smarkm}
164055682Smarkm
164172448Sassarstatic krb5_error_code
164278536SassarDES_CBC_encrypt_null_ivec(krb5_context context,
164378536Sassar			  struct key_data *key,
164455682Smarkm			  void *data,
164555682Smarkm			  size_t len,
164672448Sassar			  krb5_boolean encrypt,
164772448Sassar			  int usage,
164872448Sassar			  void *ignore_ivec)
164955682Smarkm{
165055682Smarkm    des_cblock ivec;
165155682Smarkm    des_key_schedule *s = key->schedule->data;
165255682Smarkm    memset(&ivec, 0, sizeof(ivec));
165355682Smarkm    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
165472448Sassar    return 0;
165555682Smarkm}
165655682Smarkm
165772448Sassarstatic krb5_error_code
165878536SassarDES_CBC_encrypt_key_ivec(krb5_context context,
165978536Sassar			 struct key_data *key,
166055682Smarkm			 void *data,
166155682Smarkm			 size_t len,
166272448Sassar			 krb5_boolean encrypt,
166372448Sassar			 int usage,
166472448Sassar			 void *ignore_ivec)
166555682Smarkm{
166655682Smarkm    des_cblock ivec;
166755682Smarkm    des_key_schedule *s = key->schedule->data;
166855682Smarkm    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
166955682Smarkm    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
167072448Sassar    return 0;
167155682Smarkm}
167255682Smarkm
167372448Sassarstatic krb5_error_code
167478536SassarDES3_CBC_encrypt(krb5_context context,
167578536Sassar		 struct key_data *key,
167655682Smarkm		 void *data,
167755682Smarkm		 size_t len,
167872448Sassar		 krb5_boolean encrypt,
167972448Sassar		 int usage,
1680103426Snectar		 void *ivec)
168155682Smarkm{
1682103426Snectar    des_cblock local_ivec;
168355682Smarkm    des_key_schedule *s = key->schedule->data;
1684103426Snectar    if(ivec == NULL) {
1685103426Snectar	ivec = &local_ivec;
1686103426Snectar	memset(local_ivec, 0, sizeof(local_ivec));
1687103426Snectar    }
168872448Sassar    des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt);
168972448Sassar    return 0;
169072448Sassar}
169172448Sassar
169272448Sassarstatic krb5_error_code
169378536SassarDES_CFB64_encrypt_null_ivec(krb5_context context,
169478536Sassar			    struct key_data *key,
169572448Sassar			    void *data,
169672448Sassar			    size_t len,
169772448Sassar			    krb5_boolean encrypt,
169872448Sassar			    int usage,
169972448Sassar			    void *ignore_ivec)
170072448Sassar{
170172448Sassar    des_cblock ivec;
170272448Sassar    int num = 0;
170372448Sassar    des_key_schedule *s = key->schedule->data;
170472448Sassar    memset(&ivec, 0, sizeof(ivec));
170572448Sassar
170672448Sassar    des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
170772448Sassar    return 0;
170872448Sassar}
170972448Sassar
171072448Sassarstatic krb5_error_code
171178536SassarDES_PCBC_encrypt_key_ivec(krb5_context context,
171278536Sassar			  struct key_data *key,
171372448Sassar			  void *data,
171472448Sassar			  size_t len,
171572448Sassar			  krb5_boolean encrypt,
171672448Sassar			  int usage,
171772448Sassar			  void *ignore_ivec)
171872448Sassar{
171972448Sassar    des_cblock ivec;
172072448Sassar    des_key_schedule *s = key->schedule->data;
172172448Sassar    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
172272448Sassar
172372448Sassar    des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
172472448Sassar    return 0;
172572448Sassar}
172672448Sassar
172772448Sassar/*
172872448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
172972448Sassar *
173072448Sassar * warning: not for small children
173172448Sassar */
173272448Sassar
173372448Sassarstatic krb5_error_code
173478536SassarARCFOUR_subencrypt(krb5_context context,
173578536Sassar		   struct key_data *key,
173672448Sassar		   void *data,
173772448Sassar		   size_t len,
173872448Sassar		   int usage,
173972448Sassar		   void *ivec)
174072448Sassar{
174172448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
174272448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
174372448Sassar    struct key_data ke;
174472448Sassar    krb5_keyblock kb;
174572448Sassar    unsigned char t[4];
174672448Sassar    RC4_KEY rc4_key;
174790929Snectar    unsigned char *cdata = data;
174872448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
174972448Sassar
175072448Sassar    t[0] = (usage >>  0) & 0xFF;
175172448Sassar    t[1] = (usage >>  8) & 0xFF;
175272448Sassar    t[2] = (usage >> 16) & 0xFF;
175372448Sassar    t[3] = (usage >> 24) & 0xFF;
175472448Sassar
175572448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
175672448Sassar    k1_c.checksum.data   = k1_c_data;
175772448Sassar
175872448Sassar    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
175972448Sassar
176072448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
176172448Sassar
176272448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
176372448Sassar    k2_c.checksum.data   = k2_c_data;
176472448Sassar
176572448Sassar    ke.key = &kb;
176672448Sassar    kb.keyvalue = k2_c.checksum;
176772448Sassar
176872448Sassar    cksum.checksum.length = 16;
176972448Sassar    cksum.checksum.data   = data;
177072448Sassar
177172448Sassar    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
177272448Sassar
177372448Sassar    ke.key = &kb;
177472448Sassar    kb.keyvalue = k1_c.checksum;
177572448Sassar
177672448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
177772448Sassar    k3_c.checksum.data   = k3_c_data;
177872448Sassar
177972448Sassar    hmac(NULL, c, data, 16, 0, &ke, &k3_c);
178072448Sassar
178172448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
178272448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
178372448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
178472448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
178572448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
178672448Sassar    return 0;
178772448Sassar}
178872448Sassar
178972448Sassarstatic krb5_error_code
179078536SassarARCFOUR_subdecrypt(krb5_context context,
179178536Sassar		   struct key_data *key,
179272448Sassar		   void *data,
179372448Sassar		   size_t len,
179472448Sassar		   int usage,
179572448Sassar		   void *ivec)
179672448Sassar{
179772448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
179872448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
179972448Sassar    struct key_data ke;
180072448Sassar    krb5_keyblock kb;
180172448Sassar    unsigned char t[4];
180272448Sassar    RC4_KEY rc4_key;
180390929Snectar    unsigned char *cdata = data;
180472448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
180572448Sassar    unsigned char cksum_data[16];
180672448Sassar
180772448Sassar    t[0] = (usage >>  0) & 0xFF;
180872448Sassar    t[1] = (usage >>  8) & 0xFF;
180972448Sassar    t[2] = (usage >> 16) & 0xFF;
181072448Sassar    t[3] = (usage >> 24) & 0xFF;
181172448Sassar
181272448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
181372448Sassar    k1_c.checksum.data   = k1_c_data;
181472448Sassar
181572448Sassar    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
181672448Sassar
181772448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
181872448Sassar
181972448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
182072448Sassar    k2_c.checksum.data   = k2_c_data;
182172448Sassar
182272448Sassar    ke.key = &kb;
182372448Sassar    kb.keyvalue = k1_c.checksum;
182472448Sassar
182572448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
182672448Sassar    k3_c.checksum.data   = k3_c_data;
182772448Sassar
182872448Sassar    hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
182972448Sassar
183072448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
183172448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
183272448Sassar
183372448Sassar    ke.key = &kb;
183472448Sassar    kb.keyvalue = k2_c.checksum;
183572448Sassar
183672448Sassar    cksum.checksum.length = 16;
183772448Sassar    cksum.checksum.data   = cksum_data;
183872448Sassar
183972448Sassar    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
184072448Sassar
184172448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
184272448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
184372448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
184472448Sassar
184578536Sassar    if (memcmp (cksum.checksum.data, data, 16) != 0) {
184678536Sassar	krb5_clear_error_string (context);
184772448Sassar	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
184878536Sassar    } else {
184972448Sassar	return 0;
185078536Sassar    }
185172448Sassar}
185272448Sassar
185372448Sassar/*
185472448Sassar * convert the usage numbers used in
185572448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
185672448Sassar * draft-brezak-win2k-krb-rc4-hmac-03.txt
185772448Sassar */
185872448Sassar
1859102647Snectarstatic krb5_error_code
1860102647Snectarusage2arcfour (krb5_context context, int *usage)
186172448Sassar{
1862102647Snectar    switch (*usage) {
186372448Sassar    case KRB5_KU_PA_ENC_TIMESTAMP :
1864102647Snectar	*usage = 1;
1865102647Snectar	return 0;
186672448Sassar    case KRB5_KU_TICKET :
1867102647Snectar	*usage = 8;
186872448Sassar    case KRB5_KU_AS_REP_ENC_PART :
1869102647Snectar	*usage = 8;
1870102647Snectar	return 0;
187172448Sassar    case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
187272448Sassar    case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
187372448Sassar    case KRB5_KU_TGS_REQ_AUTH_CKSUM :
187472448Sassar    case KRB5_KU_TGS_REQ_AUTH :
1875102647Snectar	*usage = 7;
1876102647Snectar	return 0;
187772448Sassar    case KRB5_KU_TGS_REP_ENC_PART_SESSION :
187872448Sassar    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
1879102647Snectar	*usage = 8;
1880102647Snectar	return 0;
188172448Sassar    case KRB5_KU_AP_REQ_AUTH_CKSUM :
188272448Sassar    case KRB5_KU_AP_REQ_AUTH :
188372448Sassar    case KRB5_KU_AP_REQ_ENC_PART :
1884102647Snectar	*usage = 11;
1885102647Snectar	return 0;
188672448Sassar    case KRB5_KU_KRB_PRIV :
1887102647Snectar	*usage = 0;
188872448Sassar	return 0;
188972448Sassar    case KRB5_KU_KRB_CRED :
189072448Sassar    case KRB5_KU_KRB_SAFE_CKSUM :
189172448Sassar    case KRB5_KU_OTHER_ENCRYPTED :
189272448Sassar    case KRB5_KU_OTHER_CKSUM :
189372448Sassar    case KRB5_KU_KRB_ERROR :
189472448Sassar    case KRB5_KU_AD_KDC_ISSUED :
189572448Sassar    case KRB5_KU_MANDATORY_TICKET_EXTENSION :
189672448Sassar    case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
189772448Sassar    case KRB5_KU_USAGE_SEAL :
189872448Sassar    case KRB5_KU_USAGE_SIGN :
189972448Sassar    case KRB5_KU_USAGE_SEQ :
190072448Sassar    default :
1901102647Snectar	krb5_set_error_string(context, "unknown arcfour usage type %d", *usage);
1902102647Snectar	return KRB5_PROG_ETYPE_NOSUPP;
190372448Sassar    }
190472448Sassar}
190572448Sassar
190672448Sassarstatic krb5_error_code
190778536SassarARCFOUR_encrypt(krb5_context context,
190878536Sassar		struct key_data *key,
190955682Smarkm		void *data,
191055682Smarkm		size_t len,
191172448Sassar		krb5_boolean encrypt,
191272448Sassar		int usage,
191372448Sassar		void *ivec)
191455682Smarkm{
1915102647Snectar    krb5_error_code ret;
1916102647Snectar    if((ret = usage2arcfour (context, &usage)) != 0)
1917102647Snectar	return ret;
191855682Smarkm
191972448Sassar    if (encrypt)
192078536Sassar	return ARCFOUR_subencrypt (context, key, data, len, usage, ivec);
192172448Sassar    else
192278536Sassar	return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec);
192355682Smarkm}
192455682Smarkm
192572448Sassar
192655682Smarkm/*
192755682Smarkm * these should currently be in reverse preference order.
192872448Sassar * (only relevant for !F_PSEUDO) */
192955682Smarkm
193078536Sassarstatic struct encryption_type enctype_null = {
193178536Sassar    ETYPE_NULL,
193278536Sassar    "null",
193378536Sassar    1,
193478536Sassar    0,
193578536Sassar    &keytype_null,
193678536Sassar    &checksum_none,
193778536Sassar    NULL,
193878536Sassar    0,
193978536Sassar    NULL_encrypt,
194055682Smarkm};
194178536Sassarstatic struct encryption_type enctype_des_cbc_crc = {
194278536Sassar    ETYPE_DES_CBC_CRC,
194378536Sassar    "des-cbc-crc",
194478536Sassar    8,
194578536Sassar    8,
194678536Sassar    &keytype_des,
194778536Sassar    &checksum_crc32,
194878536Sassar    NULL,
194978536Sassar    0,
195078536Sassar    DES_CBC_encrypt_key_ivec,
195178536Sassar};
195278536Sassarstatic struct encryption_type enctype_des_cbc_md4 = {
195378536Sassar    ETYPE_DES_CBC_MD4,
195478536Sassar    "des-cbc-md4",
195578536Sassar    8,
195678536Sassar    8,
195778536Sassar    &keytype_des,
195878536Sassar    &checksum_rsa_md4,
195978536Sassar    &checksum_rsa_md4_des,
196078536Sassar    0,
196178536Sassar    DES_CBC_encrypt_null_ivec,
196278536Sassar};
196378536Sassarstatic struct encryption_type enctype_des_cbc_md5 = {
196478536Sassar    ETYPE_DES_CBC_MD5,
196578536Sassar    "des-cbc-md5",
196678536Sassar    8,
196778536Sassar    8,
196878536Sassar    &keytype_des,
196978536Sassar    &checksum_rsa_md5,
197078536Sassar    &checksum_rsa_md5_des,
197178536Sassar    0,
197278536Sassar    DES_CBC_encrypt_null_ivec,
197378536Sassar};
197478536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = {
197578536Sassar    ETYPE_ARCFOUR_HMAC_MD5,
197678536Sassar    "arcfour-hmac-md5",
197778536Sassar    1,
197878536Sassar    8,
197978536Sassar    &keytype_arcfour,
198090929Snectar    &checksum_hmac_md5,
198178536Sassar    &checksum_hmac_md5_enc,
198278536Sassar    F_SPECIAL,
198378536Sassar    ARCFOUR_encrypt
198478536Sassar};
198578536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = {
198678536Sassar    ETYPE_DES3_CBC_MD5,
198778536Sassar    "des3-cbc-md5",
198878536Sassar    8,
198978536Sassar    8,
199078536Sassar    &keytype_des3,
199178536Sassar    &checksum_rsa_md5,
199278536Sassar    &checksum_rsa_md5_des3,
199378536Sassar    0,
199478536Sassar    DES3_CBC_encrypt,
199578536Sassar};
199678536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = {
199778536Sassar    ETYPE_DES3_CBC_SHA1,
199878536Sassar    "des3-cbc-sha1",
199978536Sassar    8,
200078536Sassar    8,
200178536Sassar    &keytype_des3_derived,
200278536Sassar    &checksum_sha1,
200378536Sassar    &checksum_hmac_sha1_des3,
200478536Sassar    F_DERIVED,
200578536Sassar    DES3_CBC_encrypt,
200678536Sassar};
200778536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = {
200878536Sassar    ETYPE_OLD_DES3_CBC_SHA1,
200978536Sassar    "old-des3-cbc-sha1",
201078536Sassar    8,
201178536Sassar    8,
201278536Sassar    &keytype_des3,
201378536Sassar    &checksum_sha1,
201478536Sassar    &checksum_hmac_sha1_des3,
201578536Sassar    0,
201678536Sassar    DES3_CBC_encrypt,
201778536Sassar};
201878536Sassarstatic struct encryption_type enctype_des_cbc_none = {
201978536Sassar    ETYPE_DES_CBC_NONE,
202078536Sassar    "des-cbc-none",
202178536Sassar    8,
202278536Sassar    0,
202378536Sassar    &keytype_des,
202478536Sassar    &checksum_none,
202578536Sassar    NULL,
202678536Sassar    F_PSEUDO,
202778536Sassar    DES_CBC_encrypt_null_ivec,
202878536Sassar};
202978536Sassarstatic struct encryption_type enctype_des_cfb64_none = {
203078536Sassar    ETYPE_DES_CFB64_NONE,
203178536Sassar    "des-cfb64-none",
203278536Sassar    1,
203378536Sassar    0,
203478536Sassar    &keytype_des,
203578536Sassar    &checksum_none,
203678536Sassar    NULL,
203778536Sassar    F_PSEUDO,
203878536Sassar    DES_CFB64_encrypt_null_ivec,
203978536Sassar};
204078536Sassarstatic struct encryption_type enctype_des_pcbc_none = {
204178536Sassar    ETYPE_DES_PCBC_NONE,
204278536Sassar    "des-pcbc-none",
204378536Sassar    8,
204478536Sassar    0,
204578536Sassar    &keytype_des,
204678536Sassar    &checksum_none,
204778536Sassar    NULL,
204878536Sassar    F_PSEUDO,
204978536Sassar    DES_PCBC_encrypt_key_ivec,
205078536Sassar};
205178536Sassarstatic struct encryption_type enctype_des3_cbc_none = {
205278536Sassar    ETYPE_DES3_CBC_NONE,
205378536Sassar    "des3-cbc-none",
205478536Sassar    8,
205578536Sassar    0,
205678536Sassar    &keytype_des3_derived,
205778536Sassar    &checksum_none,
205878536Sassar    NULL,
205978536Sassar    F_PSEUDO,
206078536Sassar    DES3_CBC_encrypt,
206178536Sassar};
206255682Smarkm
206378536Sassarstatic struct encryption_type *etypes[] = {
206478536Sassar    &enctype_null,
206578536Sassar    &enctype_des_cbc_crc,
206678536Sassar    &enctype_des_cbc_md4,
206778536Sassar    &enctype_des_cbc_md5,
206878536Sassar    &enctype_arcfour_hmac_md5,
206978536Sassar    &enctype_des3_cbc_md5,
207078536Sassar    &enctype_des3_cbc_sha1,
207178536Sassar    &enctype_old_des3_cbc_sha1,
207278536Sassar    &enctype_des_cbc_none,
207378536Sassar    &enctype_des_cfb64_none,
207478536Sassar    &enctype_des_pcbc_none,
2075103426Snectar    &enctype_des3_cbc_none
207678536Sassar};
207778536Sassar
207855682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
207955682Smarkm
208055682Smarkm
208155682Smarkmstatic struct encryption_type *
208255682Smarkm_find_enctype(krb5_enctype type)
208355682Smarkm{
208455682Smarkm    int i;
208555682Smarkm    for(i = 0; i < num_etypes; i++)
208678536Sassar	if(etypes[i]->type == type)
208778536Sassar	    return etypes[i];
208855682Smarkm    return NULL;
208955682Smarkm}
209055682Smarkm
209155682Smarkm
209255682Smarkmkrb5_error_code
209355682Smarkmkrb5_enctype_to_string(krb5_context context,
209455682Smarkm		       krb5_enctype etype,
209555682Smarkm		       char **string)
209655682Smarkm{
209755682Smarkm    struct encryption_type *e;
209855682Smarkm    e = _find_enctype(etype);
209978536Sassar    if(e == NULL) {
210078536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
210178536Sassar			       etype);
210255682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
210378536Sassar    }
210455682Smarkm    *string = strdup(e->name);
210578536Sassar    if(*string == NULL) {
210678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
210755682Smarkm	return ENOMEM;
210878536Sassar    }
210955682Smarkm    return 0;
211055682Smarkm}
211155682Smarkm
211255682Smarkmkrb5_error_code
211355682Smarkmkrb5_string_to_enctype(krb5_context context,
211455682Smarkm		       const char *string,
211555682Smarkm		       krb5_enctype *etype)
211655682Smarkm{
211755682Smarkm    int i;
211855682Smarkm    for(i = 0; i < num_etypes; i++)
211978536Sassar	if(strcasecmp(etypes[i]->name, string) == 0){
212078536Sassar	    *etype = etypes[i]->type;
212155682Smarkm	    return 0;
212255682Smarkm	}
212378536Sassar    krb5_set_error_string (context, "encryption type %s not supported",
212478536Sassar			   string);
212555682Smarkm    return KRB5_PROG_ETYPE_NOSUPP;
212655682Smarkm}
212755682Smarkm
212855682Smarkmkrb5_error_code
212955682Smarkmkrb5_enctype_to_keytype(krb5_context context,
213055682Smarkm			krb5_enctype etype,
213155682Smarkm			krb5_keytype *keytype)
213255682Smarkm{
213355682Smarkm    struct encryption_type *e = _find_enctype(etype);
213478536Sassar    if(e == NULL) {
213578536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
213678536Sassar			       etype);
213755682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
213878536Sassar    }
213955682Smarkm    *keytype = e->keytype->type; /* XXX */
214055682Smarkm    return 0;
214155682Smarkm}
214255682Smarkm
214355682Smarkm#if 0
214455682Smarkmkrb5_error_code
214555682Smarkmkrb5_keytype_to_enctype(krb5_context context,
214655682Smarkm			krb5_keytype keytype,
214755682Smarkm			krb5_enctype *etype)
214855682Smarkm{
214955682Smarkm    struct key_type *kt = _find_keytype(keytype);
215055682Smarkm    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
215155682Smarkm    if(kt == NULL)
215255682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
215355682Smarkm    *etype = kt->best_etype;
215455682Smarkm    return 0;
215555682Smarkm}
215655682Smarkm#endif
215755682Smarkm
215855682Smarkmkrb5_error_code
215955682Smarkmkrb5_keytype_to_enctypes (krb5_context context,
216055682Smarkm			  krb5_keytype keytype,
216155682Smarkm			  unsigned *len,
216290929Snectar			  krb5_enctype **val)
216355682Smarkm{
216455682Smarkm    int i;
216555682Smarkm    unsigned n = 0;
216690929Snectar    krb5_enctype *ret;
216755682Smarkm
216855682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
216978536Sassar	if (etypes[i]->keytype->type == keytype
217078536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
217155682Smarkm	    ++n;
217255682Smarkm    }
217390929Snectar    ret = malloc(n * sizeof(*ret));
217478536Sassar    if (ret == NULL && n != 0) {
217578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
217655682Smarkm	return ENOMEM;
217778536Sassar    }
217855682Smarkm    n = 0;
217955682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
218078536Sassar	if (etypes[i]->keytype->type == keytype
218178536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
218278536Sassar	    ret[n++] = etypes[i]->type;
218355682Smarkm    }
218455682Smarkm    *len = n;
218555682Smarkm    *val = ret;
218655682Smarkm    return 0;
218755682Smarkm}
218855682Smarkm
218955682Smarkm/*
219055682Smarkm * First take the configured list of etypes for `keytype' if available,
219155682Smarkm * else, do `krb5_keytype_to_enctypes'.
219255682Smarkm */
219355682Smarkm
219455682Smarkmkrb5_error_code
219555682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context,
219655682Smarkm				  krb5_keytype keytype,
219755682Smarkm				  unsigned *len,
219890929Snectar				  krb5_enctype **val)
219955682Smarkm{
220055682Smarkm    int i, n;
220190929Snectar    krb5_enctype *ret;
220255682Smarkm
220355682Smarkm    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
220455682Smarkm	return krb5_keytype_to_enctypes (context, keytype, len, val);
220555682Smarkm
220655682Smarkm    for (n = 0; context->etypes_des[n]; ++n)
220755682Smarkm	;
220855682Smarkm    ret = malloc (n * sizeof(*ret));
220978536Sassar    if (ret == NULL && n != 0) {
221078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
221155682Smarkm	return ENOMEM;
221278536Sassar    }
221355682Smarkm    for (i = 0; i < n; ++i)
221455682Smarkm	ret[i] = context->etypes_des[i];
221555682Smarkm    *len = n;
221655682Smarkm    *val = ret;
221755682Smarkm    return 0;
221855682Smarkm}
221955682Smarkm
222055682Smarkmkrb5_error_code
222155682Smarkmkrb5_enctype_valid(krb5_context context,
222255682Smarkm		 krb5_enctype etype)
222355682Smarkm{
222455682Smarkm    return _find_enctype(etype) != NULL;
222555682Smarkm}
222655682Smarkm
222755682Smarkm/* if two enctypes have compatible keys */
222855682Smarkmkrb5_boolean
222955682Smarkmkrb5_enctypes_compatible_keys(krb5_context context,
223055682Smarkm			      krb5_enctype etype1,
223155682Smarkm			      krb5_enctype etype2)
223255682Smarkm{
223355682Smarkm    struct encryption_type *e1 = _find_enctype(etype1);
223455682Smarkm    struct encryption_type *e2 = _find_enctype(etype2);
223555682Smarkm    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
223655682Smarkm}
223755682Smarkm
223855682Smarkmstatic krb5_boolean
223955682Smarkmderived_crypto(krb5_context context,
224055682Smarkm	       krb5_crypto crypto)
224155682Smarkm{
224255682Smarkm    return (crypto->et->flags & F_DERIVED) != 0;
224355682Smarkm}
224455682Smarkm
224572448Sassarstatic krb5_boolean
224672448Sassarspecial_crypto(krb5_context context,
224772448Sassar	       krb5_crypto crypto)
224872448Sassar{
224972448Sassar    return (crypto->et->flags & F_SPECIAL) != 0;
225072448Sassar}
225155682Smarkm
225255682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize)
225355682Smarkm#define CHECKSUMTYPE(C) ((C)->type)
225455682Smarkm
225555682Smarkmstatic krb5_error_code
225655682Smarkmencrypt_internal_derived(krb5_context context,
225755682Smarkm			 krb5_crypto crypto,
225855682Smarkm			 unsigned usage,
225955682Smarkm			 void *data,
226055682Smarkm			 size_t len,
226172448Sassar			 krb5_data *result,
226272448Sassar			 void *ivec)
226355682Smarkm{
226490929Snectar    size_t sz, block_sz, checksum_sz, total_sz;
226555682Smarkm    Checksum cksum;
226655682Smarkm    unsigned char *p, *q;
226755682Smarkm    krb5_error_code ret;
226855682Smarkm    struct key_data *dkey;
226990929Snectar    const struct encryption_type *et = crypto->et;
227055682Smarkm
227155682Smarkm    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
227255682Smarkm
227390929Snectar    sz = et->confoundersize + len;
227455682Smarkm    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
227590929Snectar    total_sz = block_sz + checksum_sz;
227690929Snectar    p = calloc(1, total_sz);
227790929Snectar    if(p == NULL) {
227890929Snectar	krb5_set_error_string(context, "malloc: out of memory");
227955682Smarkm	return ENOMEM;
228090929Snectar    }
228155682Smarkm
228255682Smarkm    q = p;
228355682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
228455682Smarkm    q += et->confoundersize;
228555682Smarkm    memcpy(q, data, len);
228655682Smarkm
228755682Smarkm    ret = create_checksum(context,
228855682Smarkm			  crypto,
228955682Smarkm			  INTEGRITY_USAGE(usage),
229078536Sassar			  et->keyed_checksum->type,
229155682Smarkm			  p,
229255682Smarkm			  block_sz,
229355682Smarkm			  &cksum);
229472448Sassar    if(ret == 0 && cksum.checksum.length != checksum_sz) {
229572448Sassar	free_Checksum (&cksum);
229678536Sassar	krb5_clear_error_string (context);
229772448Sassar	ret = KRB5_CRYPTO_INTERNAL;
229872448Sassar    }
229990929Snectar    if(ret)
230090929Snectar	goto fail;
230155682Smarkm    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
230272448Sassar    free_Checksum (&cksum);
230355682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
230490929Snectar    if(ret)
230590929Snectar	goto fail;
230655682Smarkm    ret = _key_schedule(context, dkey);
230790929Snectar    if(ret)
230890929Snectar	goto fail;
230955682Smarkm#ifdef CRYPTO_DEBUG
231055682Smarkm    krb5_crypto_debug(context, 1, block_sz, dkey->key);
231155682Smarkm#endif
231290929Snectar    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
231390929Snectar    if (ret)
231490929Snectar	goto fail;
231555682Smarkm    result->data = p;
231690929Snectar    result->length = total_sz;
231755682Smarkm    return 0;
231890929Snectar fail:
231990929Snectar    memset(p, 0, total_sz);
232090929Snectar    free(p);
232190929Snectar    return ret;
232255682Smarkm}
232355682Smarkm
232490929Snectar
232555682Smarkmstatic krb5_error_code
232655682Smarkmencrypt_internal(krb5_context context,
232755682Smarkm		 krb5_crypto crypto,
232855682Smarkm		 void *data,
232955682Smarkm		 size_t len,
233072448Sassar		 krb5_data *result,
233172448Sassar		 void *ivec)
233255682Smarkm{
233355682Smarkm    size_t sz, block_sz, checksum_sz;
233455682Smarkm    Checksum cksum;
233555682Smarkm    unsigned char *p, *q;
233655682Smarkm    krb5_error_code ret;
233790929Snectar    const struct encryption_type *et = crypto->et;
233855682Smarkm
233978536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
234055682Smarkm
234155682Smarkm    sz = et->confoundersize + checksum_sz + len;
234255682Smarkm    block_sz = (sz + et->blocksize - 1) &~ (et->blocksize - 1); /* pad */
234355682Smarkm    p = calloc(1, block_sz);
234478536Sassar    if(p == NULL) {
234578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
234655682Smarkm	return ENOMEM;
234778536Sassar    }
234855682Smarkm
234955682Smarkm    q = p;
235055682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
235155682Smarkm    q += et->confoundersize;
235255682Smarkm    memset(q, 0, checksum_sz);
235355682Smarkm    q += checksum_sz;
235455682Smarkm    memcpy(q, data, len);
235555682Smarkm
235655682Smarkm    ret = create_checksum(context,
235778536Sassar			  crypto,
235855682Smarkm			  0,
235978536Sassar			  et->checksum->type,
236055682Smarkm			  p,
236155682Smarkm			  block_sz,
236255682Smarkm			  &cksum);
236355682Smarkm    if(ret == 0 && cksum.checksum.length != checksum_sz) {
236478536Sassar	krb5_clear_error_string (context);
236590929Snectar	free_Checksum(&cksum);
236655682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
236755682Smarkm    }
236890929Snectar    if(ret)
236990929Snectar	goto fail;
237055682Smarkm    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
237155682Smarkm    free_Checksum(&cksum);
237255682Smarkm    ret = _key_schedule(context, &crypto->key);
237390929Snectar    if(ret)
237490929Snectar	goto fail;
237590929Snectar#ifdef CRYPTO_DEBUG
237690929Snectar    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
237790929Snectar#endif
237890929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
237990929Snectar    if (ret) {
238055682Smarkm	memset(p, 0, block_sz);
238155682Smarkm	free(p);
238255682Smarkm	return ret;
238355682Smarkm    }
238455682Smarkm    result->data = p;
238555682Smarkm    result->length = block_sz;
238655682Smarkm    return 0;
238790929Snectar fail:
238890929Snectar    memset(p, 0, block_sz);
238990929Snectar    free(p);
239090929Snectar    return ret;
239155682Smarkm}
239255682Smarkm
239355682Smarkmstatic krb5_error_code
239472448Sassarencrypt_internal_special(krb5_context context,
239572448Sassar			 krb5_crypto crypto,
239672448Sassar			 int usage,
239772448Sassar			 void *data,
239872448Sassar			 size_t len,
239972448Sassar			 krb5_data *result,
240072448Sassar			 void *ivec)
240172448Sassar{
240272448Sassar    struct encryption_type *et = crypto->et;
240378536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
240472448Sassar    size_t sz = len + cksum_sz + et->confoundersize;
240572448Sassar    char *tmp, *p;
240690929Snectar    krb5_error_code ret;
240772448Sassar
240872448Sassar    tmp = malloc (sz);
240978536Sassar    if (tmp == NULL) {
241078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
241172448Sassar	return ENOMEM;
241278536Sassar    }
241372448Sassar    p = tmp;
241472448Sassar    memset (p, 0, cksum_sz);
241572448Sassar    p += cksum_sz;
241672448Sassar    krb5_generate_random_block(p, et->confoundersize);
241772448Sassar    p += et->confoundersize;
241872448Sassar    memcpy (p, data, len);
241990929Snectar    ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
242090929Snectar    if (ret) {
242190929Snectar	memset(tmp, 0, sz);
242290929Snectar	free(tmp);
242390929Snectar	return ret;
242490929Snectar    }
242572448Sassar    result->data   = tmp;
242672448Sassar    result->length = sz;
242772448Sassar    return 0;
242872448Sassar}
242972448Sassar
243072448Sassarstatic krb5_error_code
243155682Smarkmdecrypt_internal_derived(krb5_context context,
243255682Smarkm			 krb5_crypto crypto,
243355682Smarkm			 unsigned usage,
243455682Smarkm			 void *data,
243555682Smarkm			 size_t len,
243672448Sassar			 krb5_data *result,
243772448Sassar			 void *ivec)
243855682Smarkm{
243955682Smarkm    size_t checksum_sz;
244055682Smarkm    Checksum cksum;
244155682Smarkm    unsigned char *p;
244255682Smarkm    krb5_error_code ret;
244355682Smarkm    struct key_data *dkey;
244455682Smarkm    struct encryption_type *et = crypto->et;
244555682Smarkm    unsigned long l;
244655682Smarkm
244772448Sassar    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
244878536Sassar    if (len < checksum_sz) {
244978536Sassar	krb5_clear_error_string (context);
245078536Sassar	return EINVAL;		/* XXX - better error code? */
245178536Sassar    }
245272448Sassar
245355682Smarkm    p = malloc(len);
245478536Sassar    if(len != 0 && p == NULL) {
245578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
245655682Smarkm	return ENOMEM;
245778536Sassar    }
245855682Smarkm    memcpy(p, data, len);
245955682Smarkm
246055682Smarkm    len -= checksum_sz;
246155682Smarkm
246255682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
246355682Smarkm    if(ret) {
246455682Smarkm	free(p);
246555682Smarkm	return ret;
246655682Smarkm    }
246755682Smarkm    ret = _key_schedule(context, dkey);
246855682Smarkm    if(ret) {
246955682Smarkm	free(p);
247055682Smarkm	return ret;
247155682Smarkm    }
247255682Smarkm#ifdef CRYPTO_DEBUG
247355682Smarkm    krb5_crypto_debug(context, 0, len, dkey->key);
247455682Smarkm#endif
247590929Snectar    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
247690929Snectar    if (ret) {
247790929Snectar	free(p);
247890929Snectar	return ret;
247990929Snectar    }
248055682Smarkm
248155682Smarkm    cksum.checksum.data   = p + len;
248255682Smarkm    cksum.checksum.length = checksum_sz;
248355682Smarkm    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
248455682Smarkm
248555682Smarkm    ret = verify_checksum(context,
248655682Smarkm			  crypto,
248755682Smarkm			  INTEGRITY_USAGE(usage),
248855682Smarkm			  p,
248955682Smarkm			  len,
249055682Smarkm			  &cksum);
249155682Smarkm    if(ret) {
249255682Smarkm	free(p);
249355682Smarkm	return ret;
249455682Smarkm    }
249555682Smarkm    l = len - et->confoundersize;
249655682Smarkm    memmove(p, p + et->confoundersize, l);
249755682Smarkm    result->data = realloc(p, l);
249878536Sassar    if(result->data == NULL) {
249955682Smarkm	free(p);
250078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
250155682Smarkm	return ENOMEM;
250255682Smarkm    }
250355682Smarkm    result->length = l;
250455682Smarkm    return 0;
250555682Smarkm}
250655682Smarkm
250755682Smarkmstatic krb5_error_code
250855682Smarkmdecrypt_internal(krb5_context context,
250955682Smarkm		 krb5_crypto crypto,
251055682Smarkm		 void *data,
251155682Smarkm		 size_t len,
251272448Sassar		 krb5_data *result,
251372448Sassar		 void *ivec)
251455682Smarkm{
251555682Smarkm    krb5_error_code ret;
251655682Smarkm    unsigned char *p;
251755682Smarkm    Checksum cksum;
251855682Smarkm    size_t checksum_sz, l;
251955682Smarkm    struct encryption_type *et = crypto->et;
252055682Smarkm
252178536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
252255682Smarkm    p = malloc(len);
252378536Sassar    if(len != 0 && p == NULL) {
252478536Sassar	krb5_set_error_string(context, "malloc: out of memory");
252555682Smarkm	return ENOMEM;
252678536Sassar    }
252755682Smarkm    memcpy(p, data, len);
252855682Smarkm
252955682Smarkm    ret = _key_schedule(context, &crypto->key);
253055682Smarkm    if(ret) {
253155682Smarkm	free(p);
253255682Smarkm	return ret;
253355682Smarkm    }
253455682Smarkm#ifdef CRYPTO_DEBUG
253555682Smarkm    krb5_crypto_debug(context, 0, len, crypto->key.key);
253655682Smarkm#endif
253790929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
253890929Snectar    if (ret) {
253990929Snectar	free(p);
254090929Snectar	return ret;
254190929Snectar    }
254255682Smarkm    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
254355682Smarkm    if(ret) {
254472448Sassar 	free(p);
254572448Sassar 	return ret;
254655682Smarkm    }
254755682Smarkm    memset(p + et->confoundersize, 0, checksum_sz);
254878536Sassar    cksum.cksumtype = CHECKSUMTYPE(et->checksum);
254955682Smarkm    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
255055682Smarkm    free_Checksum(&cksum);
255155682Smarkm    if(ret) {
255255682Smarkm	free(p);
255355682Smarkm	return ret;
255455682Smarkm    }
255555682Smarkm    l = len - et->confoundersize - checksum_sz;
255655682Smarkm    memmove(p, p + et->confoundersize + checksum_sz, l);
255755682Smarkm    result->data = realloc(p, l);
255855682Smarkm    if(result->data == NULL) {
255955682Smarkm	free(p);
256078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
256155682Smarkm	return ENOMEM;
256255682Smarkm    }
256355682Smarkm    result->length = l;
256455682Smarkm    return 0;
256555682Smarkm}
256655682Smarkm
256772448Sassarstatic krb5_error_code
256872448Sassardecrypt_internal_special(krb5_context context,
256972448Sassar			 krb5_crypto crypto,
257072448Sassar			 int usage,
257172448Sassar			 void *data,
257272448Sassar			 size_t len,
257372448Sassar			 krb5_data *result,
257472448Sassar			 void *ivec)
257572448Sassar{
257672448Sassar    struct encryption_type *et = crypto->et;
257778536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
257872448Sassar    size_t sz = len - cksum_sz - et->confoundersize;
257972448Sassar    char *cdata = (char *)data;
258072448Sassar    char *tmp;
258190929Snectar    krb5_error_code ret;
258272448Sassar
258372448Sassar    tmp = malloc (sz);
258478536Sassar    if (tmp == NULL) {
258578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
258672448Sassar	return ENOMEM;
258778536Sassar    }
258872448Sassar
258990929Snectar    ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
259090929Snectar    if (ret) {
259190929Snectar	free(tmp);
259290929Snectar	return ret;
259390929Snectar    }
259472448Sassar
259572448Sassar    memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
259672448Sassar
259772448Sassar    result->data   = tmp;
259872448Sassar    result->length = sz;
259972448Sassar    return 0;
260072448Sassar}
260172448Sassar
260272448Sassar
260355682Smarkmkrb5_error_code
260472448Sassarkrb5_encrypt_ivec(krb5_context context,
260572448Sassar		  krb5_crypto crypto,
260672448Sassar		  unsigned usage,
260772448Sassar		  void *data,
260872448Sassar		  size_t len,
260972448Sassar		  krb5_data *result,
261072448Sassar		  void *ivec)
261172448Sassar{
261272448Sassar    if(derived_crypto(context, crypto))
261372448Sassar	return encrypt_internal_derived(context, crypto, usage,
261472448Sassar					data, len, result, ivec);
261572448Sassar    else if (special_crypto(context, crypto))
261672448Sassar	return encrypt_internal_special (context, crypto, usage,
261772448Sassar					 data, len, result, ivec);
261872448Sassar    else
261972448Sassar	return encrypt_internal(context, crypto, data, len, result, ivec);
262072448Sassar}
262172448Sassar
262272448Sassarkrb5_error_code
262355682Smarkmkrb5_encrypt(krb5_context context,
262455682Smarkm	     krb5_crypto crypto,
262555682Smarkm	     unsigned usage,
262655682Smarkm	     void *data,
262755682Smarkm	     size_t len,
262855682Smarkm	     krb5_data *result)
262955682Smarkm{
263072448Sassar    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
263155682Smarkm}
263255682Smarkm
263355682Smarkmkrb5_error_code
263455682Smarkmkrb5_encrypt_EncryptedData(krb5_context context,
263555682Smarkm			   krb5_crypto crypto,
263655682Smarkm			   unsigned usage,
263755682Smarkm			   void *data,
263855682Smarkm			   size_t len,
263955682Smarkm			   int kvno,
264055682Smarkm			   EncryptedData *result)
264155682Smarkm{
264255682Smarkm    result->etype = CRYPTO_ETYPE(crypto);
264355682Smarkm    if(kvno){
264455682Smarkm	ALLOC(result->kvno, 1);
264555682Smarkm	*result->kvno = kvno;
264655682Smarkm    }else
264755682Smarkm	result->kvno = NULL;
264855682Smarkm    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
264955682Smarkm}
265055682Smarkm
265155682Smarkmkrb5_error_code
265272448Sassarkrb5_decrypt_ivec(krb5_context context,
265372448Sassar		  krb5_crypto crypto,
265472448Sassar		  unsigned usage,
265572448Sassar		  void *data,
265672448Sassar		  size_t len,
265772448Sassar		  krb5_data *result,
265872448Sassar		  void *ivec)
265972448Sassar{
266072448Sassar    if(derived_crypto(context, crypto))
266172448Sassar	return decrypt_internal_derived(context, crypto, usage,
266272448Sassar					data, len, result, ivec);
266372448Sassar    else if (special_crypto (context, crypto))
266472448Sassar	return decrypt_internal_special(context, crypto, usage,
266572448Sassar					data, len, result, ivec);
266672448Sassar    else
266772448Sassar	return decrypt_internal(context, crypto, data, len, result, ivec);
266872448Sassar}
266972448Sassar
267072448Sassarkrb5_error_code
267155682Smarkmkrb5_decrypt(krb5_context context,
267255682Smarkm	     krb5_crypto crypto,
267355682Smarkm	     unsigned usage,
267455682Smarkm	     void *data,
267555682Smarkm	     size_t len,
267655682Smarkm	     krb5_data *result)
267755682Smarkm{
267872448Sassar    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
267972448Sassar			      NULL);
268055682Smarkm}
268155682Smarkm
268255682Smarkmkrb5_error_code
268355682Smarkmkrb5_decrypt_EncryptedData(krb5_context context,
268455682Smarkm			   krb5_crypto crypto,
268555682Smarkm			   unsigned usage,
268672448Sassar			   const EncryptedData *e,
268755682Smarkm			   krb5_data *result)
268855682Smarkm{
268955682Smarkm    return krb5_decrypt(context, crypto, usage,
269055682Smarkm			e->cipher.data, e->cipher.length, result);
269155682Smarkm}
269255682Smarkm
269355682Smarkm/************************************************************
269455682Smarkm *                                                          *
269555682Smarkm ************************************************************/
269655682Smarkm
269790929Snectar#ifdef HAVE_OPENSSL
269878536Sassar#include <openssl/rand.h>
269978536Sassar
270078536Sassar/* From openssl/crypto/rand/rand_lcl.h */
270178536Sassar#define ENTROPY_NEEDED 20
270278536Sassarstatic int
270378536Sassarseed_something(void)
270478536Sassar{
270578536Sassar    int fd = -1;
270678536Sassar    char buf[1024], seedfile[256];
270778536Sassar
270878536Sassar    /* If there is a seed file, load it. But such a file cannot be trusted,
270978536Sassar       so use 0 for the entropy estimate */
271078536Sassar    if (RAND_file_name(seedfile, sizeof(seedfile))) {
271178536Sassar	fd = open(seedfile, O_RDONLY);
271278536Sassar	if (fd >= 0) {
271378536Sassar	    read(fd, buf, sizeof(buf));
271478536Sassar	    /* Use the full buffer anyway */
271578536Sassar	    RAND_add(buf, sizeof(buf), 0.0);
271678536Sassar	} else
271778536Sassar	    seedfile[0] = '\0';
271878536Sassar    } else
271978536Sassar	seedfile[0] = '\0';
272078536Sassar
272178536Sassar    /* Calling RAND_status() will try to use /dev/urandom if it exists so
272278536Sassar       we do not have to deal with it. */
272378536Sassar    if (RAND_status() != 1) {
272478536Sassar	krb5_context context;
272590929Snectar	const char *p;
272678536Sassar
272778536Sassar	/* Try using egd */
272878536Sassar	if (!krb5_init_context(&context)) {
272978536Sassar	    p = krb5_config_get_string(context, NULL, "libdefaults",
273078536Sassar		"egd_socket", NULL);
273178536Sassar	    if (p != NULL)
273278536Sassar		RAND_egd_bytes(p, ENTROPY_NEEDED);
273378536Sassar	    krb5_free_context(context);
273478536Sassar	}
273578536Sassar    }
273678536Sassar
273778536Sassar    if (RAND_status() == 1)	{
273878536Sassar	/* Update the seed file */
273978536Sassar	if (seedfile[0])
274078536Sassar	    RAND_write_file(seedfile);
274178536Sassar
274278536Sassar	return 0;
274378536Sassar    } else
274478536Sassar	return -1;
274578536Sassar}
274678536Sassar
274755682Smarkmvoid
274855682Smarkmkrb5_generate_random_block(void *buf, size_t len)
274955682Smarkm{
275078536Sassar    static int rng_initialized = 0;
275178536Sassar
275278536Sassar    if (!rng_initialized) {
275378536Sassar	if (seed_something())
275478536Sassar	    krb5_abortx(NULL, "Fatal: could not seed the random number generator");
275578536Sassar
275678536Sassar	rng_initialized = 1;
275778536Sassar    }
275878536Sassar    RAND_bytes(buf, len);
275978536Sassar}
276078536Sassar
276178536Sassar#else
276278536Sassar
276378536Sassarvoid
276478536Sassarkrb5_generate_random_block(void *buf, size_t len)
276578536Sassar{
276655682Smarkm    des_cblock key, out;
276755682Smarkm    static des_cblock counter;
276855682Smarkm    static des_key_schedule schedule;
276955682Smarkm    int i;
277055682Smarkm    static int initialized = 0;
277155682Smarkm
277255682Smarkm    if(!initialized) {
277355682Smarkm	des_new_random_key(&key);
277455682Smarkm	des_set_key(&key, schedule);
277555682Smarkm	memset(&key, 0, sizeof(key));
277655682Smarkm	des_new_random_key(&counter);
277755682Smarkm    }
277855682Smarkm    while(len > 0) {
277955682Smarkm	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
278055682Smarkm	for(i = 7; i >=0; i--)
278155682Smarkm	    if(counter[i]++)
278255682Smarkm		break;
278355682Smarkm	memcpy(buf, out, min(len, sizeof(out)));
278455682Smarkm	len -= min(len, sizeof(out));
278555682Smarkm	buf = (char*)buf + sizeof(out);
278655682Smarkm    }
278755682Smarkm}
278878536Sassar#endif
278955682Smarkm
279055682Smarkmstatic void
279155682SmarkmDES3_postproc(krb5_context context,
279255682Smarkm	      unsigned char *k, size_t len, struct key_data *key)
279355682Smarkm{
279455682Smarkm    unsigned char x[24];
279555682Smarkm    int i, j;
279655682Smarkm
279755682Smarkm    memset(x, 0, sizeof(x));
279855682Smarkm    for (i = 0; i < 3; ++i) {
279955682Smarkm	unsigned char foo;
280055682Smarkm
280155682Smarkm	for (j = 0; j < 7; ++j) {
280255682Smarkm	    unsigned char b = k[7 * i + j];
280355682Smarkm
280455682Smarkm	    x[8 * i + j] = b;
280555682Smarkm	}
280655682Smarkm	foo = 0;
280755682Smarkm	for (j = 6; j >= 0; --j) {
280855682Smarkm	    foo |= k[7 * i + j] & 1;
280955682Smarkm	    foo <<= 1;
281055682Smarkm	}
281155682Smarkm	x[8 * i + 7] = foo;
281255682Smarkm    }
281355682Smarkm    k = key->key->keyvalue.data;
281455682Smarkm    memcpy(k, x, 24);
281555682Smarkm    memset(x, 0, sizeof(x));
281655682Smarkm    if (key->schedule) {
281755682Smarkm	krb5_free_data(context, key->schedule);
281855682Smarkm	key->schedule = NULL;
281955682Smarkm    }
282055682Smarkm    des_set_odd_parity((des_cblock*)k);
282155682Smarkm    des_set_odd_parity((des_cblock*)(k + 8));
282255682Smarkm    des_set_odd_parity((des_cblock*)(k + 16));
282355682Smarkm}
282455682Smarkm
282555682Smarkmstatic krb5_error_code
282655682Smarkmderive_key(krb5_context context,
282755682Smarkm	   struct encryption_type *et,
282855682Smarkm	   struct key_data *key,
282978536Sassar	   const void *constant,
283055682Smarkm	   size_t len)
283155682Smarkm{
283255682Smarkm    unsigned char *k;
283355682Smarkm    unsigned int nblocks = 0, i;
283455682Smarkm    krb5_error_code ret = 0;
283555682Smarkm
283655682Smarkm    struct key_type *kt = et->keytype;
283755682Smarkm    ret = _key_schedule(context, key);
283855682Smarkm    if(ret)
283955682Smarkm	return ret;
284072448Sassar    if(et->blocksize * 8 < kt->bits ||
284155682Smarkm       len != et->blocksize) {
284255682Smarkm	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
284355682Smarkm	k = malloc(nblocks * et->blocksize);
284478536Sassar	if(k == NULL) {
284578536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
284655682Smarkm	    return ENOMEM;
284778536Sassar	}
284855682Smarkm	_krb5_n_fold(constant, len, k, et->blocksize);
284955682Smarkm	for(i = 0; i < nblocks; i++) {
285055682Smarkm	    if(i > 0)
285155682Smarkm		memcpy(k + i * et->blocksize,
285255682Smarkm		       k + (i - 1) * et->blocksize,
285355682Smarkm		       et->blocksize);
285478536Sassar	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
285578536Sassar			   1, 0, NULL);
285655682Smarkm	}
285755682Smarkm    } else {
285872448Sassar	/* this case is probably broken, but won't be run anyway */
285955682Smarkm	void *c = malloc(len);
286055682Smarkm	size_t res_len = (kt->bits + 7) / 8;
286155682Smarkm
286278536Sassar	if(len != 0 && c == NULL) {
286378536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
286455682Smarkm	    return ENOMEM;
286578536Sassar	}
286655682Smarkm	memcpy(c, constant, len);
286778536Sassar	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
286855682Smarkm	k = malloc(res_len);
286978536Sassar	if(res_len != 0 && k == NULL) {
287078536Sassar	    free(c);
287178536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
287255682Smarkm	    return ENOMEM;
287378536Sassar	}
287455682Smarkm	_krb5_n_fold(c, len, k, res_len);
287555682Smarkm	free(c);
287655682Smarkm    }
287755682Smarkm
287855682Smarkm    /* XXX keytype dependent post-processing */
287955682Smarkm    switch(kt->type) {
288055682Smarkm    case KEYTYPE_DES3:
288155682Smarkm	DES3_postproc(context, k, nblocks * et->blocksize, key);
288255682Smarkm	break;
288355682Smarkm    default:
288478536Sassar	krb5_set_error_string(context,
288578536Sassar			      "derive_key() called with unknown keytype (%u)",
288678536Sassar			      kt->type);
288755682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
288855682Smarkm	break;
288955682Smarkm    }
289055682Smarkm    memset(k, 0, nblocks * et->blocksize);
289155682Smarkm    free(k);
289255682Smarkm    return ret;
289355682Smarkm}
289455682Smarkm
289555682Smarkmstatic struct key_data *
289655682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage)
289755682Smarkm{
289855682Smarkm    struct key_usage *d = crypto->key_usage;
289955682Smarkm    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
290055682Smarkm    if(d == NULL)
290155682Smarkm	return NULL;
290255682Smarkm    crypto->key_usage = d;
290355682Smarkm    d += crypto->num_key_usage++;
290455682Smarkm    memset(d, 0, sizeof(*d));
290555682Smarkm    d->usage = usage;
290655682Smarkm    return &d->key;
290755682Smarkm}
290855682Smarkm
290978536Sassarkrb5_error_code
291078536Sassarkrb5_derive_key(krb5_context context,
291178536Sassar		const krb5_keyblock *key,
291278536Sassar		krb5_enctype etype,
291378536Sassar		const void *constant,
291478536Sassar		size_t constant_len,
291578536Sassar		krb5_keyblock **derived_key)
291678536Sassar{
291778536Sassar    krb5_error_code ret;
291878536Sassar    struct encryption_type *et;
291978536Sassar    struct key_data d;
292078536Sassar
292178536Sassar    et = _find_enctype (etype);
292278536Sassar    if (et == NULL) {
292378536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
292478536Sassar			      etype);
292578536Sassar	return KRB5_PROG_ETYPE_NOSUPP;
292678536Sassar    }
292778536Sassar
292878536Sassar    ret = krb5_copy_keyblock(context, key, derived_key);
292978536Sassar    if (ret)
293078536Sassar	return ret;
293178536Sassar
293278536Sassar    d.key = *derived_key;
293378536Sassar    d.schedule = NULL;
293478536Sassar    ret = derive_key(context, et, &d, constant, constant_len);
293578536Sassar    if (ret)
293678536Sassar	return ret;
293778536Sassar    ret = krb5_copy_keyblock(context, d.key, derived_key);
293878536Sassar    return ret;
293978536Sassar}
294078536Sassar
294155682Smarkmstatic krb5_error_code
294255682Smarkm_get_derived_key(krb5_context context,
294355682Smarkm		 krb5_crypto crypto,
294455682Smarkm		 unsigned usage,
294555682Smarkm		 struct key_data **key)
294655682Smarkm{
294755682Smarkm    int i;
294855682Smarkm    struct key_data *d;
294955682Smarkm    unsigned char constant[5];
295055682Smarkm
295155682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
295255682Smarkm	if(crypto->key_usage[i].usage == usage) {
295355682Smarkm	    *key = &crypto->key_usage[i].key;
295455682Smarkm	    return 0;
295555682Smarkm	}
295655682Smarkm    d = _new_derived_key(crypto, usage);
295778536Sassar    if(d == NULL) {
295878536Sassar	krb5_set_error_string(context, "malloc: out of memory");
295955682Smarkm	return ENOMEM;
296078536Sassar    }
296155682Smarkm    krb5_copy_keyblock(context, crypto->key.key, &d->key);
296255682Smarkm    _krb5_put_int(constant, usage, 5);
296355682Smarkm    derive_key(context, crypto->et, d, constant, sizeof(constant));
296455682Smarkm    *key = d;
296555682Smarkm    return 0;
296655682Smarkm}
296755682Smarkm
296855682Smarkm
296955682Smarkmkrb5_error_code
297055682Smarkmkrb5_crypto_init(krb5_context context,
297178536Sassar		 const krb5_keyblock *key,
297255682Smarkm		 krb5_enctype etype,
297355682Smarkm		 krb5_crypto *crypto)
297455682Smarkm{
297555682Smarkm    krb5_error_code ret;
297655682Smarkm    ALLOC(*crypto, 1);
297778536Sassar    if(*crypto == NULL) {
297878536Sassar	krb5_set_error_string(context, "malloc: out of memory");
297955682Smarkm	return ENOMEM;
298078536Sassar    }
298155682Smarkm    if(etype == ETYPE_NULL)
298255682Smarkm	etype = key->keytype;
298355682Smarkm    (*crypto)->et = _find_enctype(etype);
298455682Smarkm    if((*crypto)->et == NULL) {
298555682Smarkm	free(*crypto);
298678536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
298778536Sassar			       etype);
298855682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
298955682Smarkm    }
2990102647Snectar    if((*crypto)->et->keytype->size != key->keyvalue.length) {
2991102647Snectar	free(*crypto);
2992102647Snectar	krb5_set_error_string (context, "encryption key has bad length");
2993102647Snectar	return KRB5_BAD_KEYSIZE;
2994102647Snectar    }
299555682Smarkm    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
299655682Smarkm    if(ret) {
299755682Smarkm	free(*crypto);
299855682Smarkm	return ret;
299955682Smarkm    }
300055682Smarkm    (*crypto)->key.schedule = NULL;
300155682Smarkm    (*crypto)->num_key_usage = 0;
300255682Smarkm    (*crypto)->key_usage = NULL;
300355682Smarkm    return 0;
300455682Smarkm}
300555682Smarkm
300655682Smarkmstatic void
300755682Smarkmfree_key_data(krb5_context context, struct key_data *key)
300855682Smarkm{
300955682Smarkm    krb5_free_keyblock(context, key->key);
301055682Smarkm    if(key->schedule) {
301155682Smarkm	memset(key->schedule->data, 0, key->schedule->length);
301255682Smarkm	krb5_free_data(context, key->schedule);
301355682Smarkm    }
301455682Smarkm}
301555682Smarkm
301655682Smarkmstatic void
301755682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku)
301855682Smarkm{
301955682Smarkm    free_key_data(context, &ku->key);
302055682Smarkm}
302155682Smarkm
302255682Smarkmkrb5_error_code
302355682Smarkmkrb5_crypto_destroy(krb5_context context,
302455682Smarkm		    krb5_crypto crypto)
302555682Smarkm{
302655682Smarkm    int i;
302755682Smarkm
302855682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
302955682Smarkm	free_key_usage(context, &crypto->key_usage[i]);
303055682Smarkm    free(crypto->key_usage);
303155682Smarkm    free_key_data(context, &crypto->key);
303255682Smarkm    free (crypto);
303355682Smarkm    return 0;
303455682Smarkm}
303555682Smarkm
303655682Smarkmkrb5_error_code
3037103426Snectarkrb5_crypto_getblocksize(krb5_context context,
3038103426Snectar			 krb5_crypto crypto,
3039103426Snectar			 size_t *blocksize)
3040103426Snectar{
3041103426Snectar    *blocksize = crypto->et->blocksize;
3042103426Snectar    return 0;
3043103426Snectar}
3044103426Snectar
3045103426Snectarkrb5_error_code
304655682Smarkmkrb5_string_to_key_derived(krb5_context context,
304755682Smarkm			   const void *str,
304855682Smarkm			   size_t len,
304955682Smarkm			   krb5_enctype etype,
305055682Smarkm			   krb5_keyblock *key)
305155682Smarkm{
305255682Smarkm    struct encryption_type *et = _find_enctype(etype);
305355682Smarkm    krb5_error_code ret;
305455682Smarkm    struct key_data kd;
305590929Snectar    size_t keylen = et->keytype->bits / 8;
305655682Smarkm    u_char *tmp;
305755682Smarkm
305878536Sassar    if(et == NULL) {
305978536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
306078536Sassar			       etype);
306155682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
306278536Sassar    }
306355682Smarkm    ALLOC(kd.key, 1);
306490929Snectar    if(kd.key == NULL) {
306590929Snectar	krb5_set_error_string (context, "malloc: out of memory");
306690929Snectar	return ENOMEM;
306790929Snectar    }
306890929Snectar    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
306990929Snectar    if(ret) {
307090929Snectar	free(kd.key);
307190929Snectar	return ret;
307290929Snectar    }
307355682Smarkm    kd.key->keytype = etype;
307490929Snectar    tmp = malloc (keylen);
307590929Snectar    if(tmp == NULL) {
307690929Snectar	krb5_free_keyblock(context, kd.key);
307790929Snectar	krb5_set_error_string (context, "malloc: out of memory");
307890929Snectar	return ENOMEM;
307990929Snectar    }
308090929Snectar    _krb5_n_fold(str, len, tmp, keylen);
308155682Smarkm    kd.schedule = NULL;
308290929Snectar    DES3_postproc (context, tmp, keylen, &kd); /* XXX */
308390929Snectar    memset(tmp, 0, keylen);
308490929Snectar    free(tmp);
308590929Snectar    ret = derive_key(context,
308655682Smarkm		     et,
308755682Smarkm		     &kd,
308855682Smarkm		     "kerberos", /* XXX well known constant */
308955682Smarkm		     strlen("kerberos"));
309055682Smarkm    ret = krb5_copy_keyblock_contents(context, kd.key, key);
309155682Smarkm    free_key_data(context, &kd);
309255682Smarkm    return ret;
309355682Smarkm}
309455682Smarkm
309572448Sassarstatic size_t
309672448Sassarwrapped_length (krb5_context context,
309772448Sassar		krb5_crypto  crypto,
309872448Sassar		size_t       data_len)
309972448Sassar{
310072448Sassar    struct encryption_type *et = crypto->et;
310172448Sassar    size_t blocksize = et->blocksize;
310272448Sassar    size_t res;
310372448Sassar
310478536Sassar    res =  et->confoundersize + et->checksum->checksumsize + data_len;
310572448Sassar    res =  (res + blocksize - 1) / blocksize * blocksize;
310672448Sassar    return res;
310772448Sassar}
310872448Sassar
310972448Sassarstatic size_t
311072448Sassarwrapped_length_dervied (krb5_context context,
311172448Sassar			krb5_crypto  crypto,
311272448Sassar			size_t       data_len)
311372448Sassar{
311472448Sassar    struct encryption_type *et = crypto->et;
311572448Sassar    size_t blocksize = et->blocksize;
311672448Sassar    size_t res;
311772448Sassar
311872448Sassar    res =  et->confoundersize + data_len;
311972448Sassar    res =  (res + blocksize - 1) / blocksize * blocksize;
312078536Sassar    res += et->checksum->checksumsize;
312172448Sassar    return res;
312272448Sassar}
312372448Sassar
312455682Smarkm/*
312555682Smarkm * Return the size of an encrypted packet of length `data_len'
312655682Smarkm */
312755682Smarkm
312855682Smarkmsize_t
312955682Smarkmkrb5_get_wrapped_length (krb5_context context,
313055682Smarkm			 krb5_crypto  crypto,
313155682Smarkm			 size_t       data_len)
313255682Smarkm{
313372448Sassar    if (derived_crypto (context, crypto))
313472448Sassar	return wrapped_length_dervied (context, crypto, data_len);
313572448Sassar    else
313672448Sassar	return wrapped_length (context, crypto, data_len);
313755682Smarkm}
313855682Smarkm
313955682Smarkm#ifdef CRYPTO_DEBUG
314055682Smarkm
314155682Smarkmstatic krb5_error_code
314255682Smarkmkrb5_get_keyid(krb5_context context,
314355682Smarkm	       krb5_keyblock *key,
314455682Smarkm	       u_int32_t *keyid)
314555682Smarkm{
314657416Smarkm    MD5_CTX md5;
314755682Smarkm    unsigned char tmp[16];
314857416Smarkm
314972448Sassar    MD5_Init (&md5);
315072448Sassar    MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
315172448Sassar    MD5_Final (tmp, &md5);
315255682Smarkm    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
315355682Smarkm    return 0;
315455682Smarkm}
315555682Smarkm
315655682Smarkmstatic void
315755682Smarkmkrb5_crypto_debug(krb5_context context,
315855682Smarkm		  int encrypt,
315955682Smarkm		  size_t len,
316055682Smarkm		  krb5_keyblock *key)
316155682Smarkm{
316255682Smarkm    u_int32_t keyid;
316355682Smarkm    char *kt;
316455682Smarkm    krb5_get_keyid(context, key, &keyid);
316555682Smarkm    krb5_enctype_to_string(context, key->keytype, &kt);
316655682Smarkm    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
316755682Smarkm	       encrypt ? "encrypting" : "decrypting",
316855682Smarkm	       (unsigned long)len,
316955682Smarkm	       keyid,
317055682Smarkm	       kt);
317155682Smarkm    free(kt);
317255682Smarkm}
317355682Smarkm
317455682Smarkm#endif /* CRYPTO_DEBUG */
317572448Sassar
317672448Sassar#if 0
317772448Sassarint
317872448Sassarmain()
317972448Sassar{
318072448Sassar#if 0
318172448Sassar    int i;
318272448Sassar    krb5_context context;
318372448Sassar    krb5_crypto crypto;
318472448Sassar    struct key_data *d;
318572448Sassar    krb5_keyblock key;
318672448Sassar    char constant[4];
318772448Sassar    unsigned usage = ENCRYPTION_USAGE(3);
318872448Sassar    krb5_error_code ret;
318972448Sassar
319072448Sassar    ret = krb5_init_context(&context);
319172448Sassar    if (ret)
319272448Sassar	errx (1, "krb5_init_context failed: %d", ret);
319372448Sassar
319472448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
319572448Sassar    key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
319672448Sassar	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
319772448Sassar	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
319872448Sassar    key.keyvalue.length = 24;
319972448Sassar
320072448Sassar    krb5_crypto_init(context, &key, 0, &crypto);
320172448Sassar
320272448Sassar    d = _new_derived_key(crypto, usage);
320372448Sassar    if(d == NULL)
320472448Sassar	return ENOMEM;
320572448Sassar    krb5_copy_keyblock(context, crypto->key.key, &d->key);
320672448Sassar    _krb5_put_int(constant, usage, 4);
320772448Sassar    derive_key(context, crypto->et, d, constant, sizeof(constant));
320872448Sassar    return 0;
320972448Sassar#else
321072448Sassar    int i;
321172448Sassar    krb5_context context;
321272448Sassar    krb5_crypto crypto;
321372448Sassar    struct key_data *d;
321472448Sassar    krb5_keyblock key;
321572448Sassar    krb5_error_code ret;
321672448Sassar    Checksum res;
321772448Sassar
321872448Sassar    char *data = "what do ya want for nothing?";
321972448Sassar
322072448Sassar    ret = krb5_init_context(&context);
322172448Sassar    if (ret)
322272448Sassar	errx (1, "krb5_init_context failed: %d", ret);
322372448Sassar
322472448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
322572448Sassar    key.keyvalue.data = "Jefe";
322672448Sassar    /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
322772448Sassar       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
322872448Sassar    key.keyvalue.length = 4;
322972448Sassar
323072448Sassar    d = calloc(1, sizeof(*d));
323172448Sassar
323272448Sassar    d->key = &key;
323372448Sassar    res.checksum.length = 20;
323472448Sassar    res.checksum.data = malloc(res.checksum.length);
323572448Sassar    HMAC_SHA1_DES3_checksum(context, d, data, 28, &res);
323672448Sassar
323772448Sassar    return 0;
323872448Sassar#endif
323972448Sassar}
324072448Sassar#endif
3241