crypto.c revision 120948
155682Smarkm/*
2120948Snectar * Copyright (c) 1997 - 2003 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"
35120948SnectarRCSID("$Id: crypto.c,v 1.73 2003/04/01 16:51:54 lha Exp $");
3657428Smarkm/* RCSID("$FreeBSD: head/crypto/heimdal/lib/krb5/crypto.c 120948 2003-10-09 19:42:07Z 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,
75120948Snectar				     krb5_salt, krb5_data, 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;
114120948Snectar    size_t padsize;
11555682Smarkm    size_t confoundersize;
11655682Smarkm    struct key_type *keytype;
11778536Sassar    struct checksum_type *checksum;
11855682Smarkm    struct checksum_type *keyed_checksum;
11955682Smarkm    unsigned flags;
12078536Sassar    krb5_error_code (*encrypt)(krb5_context context,
12178536Sassar			       struct key_data *key,
12272448Sassar			       void *data, size_t len,
12372448Sassar			       krb5_boolean encrypt,
12472448Sassar			       int usage,
12572448Sassar			       void *ivec);
12655682Smarkm};
12755682Smarkm
12855682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
12955682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
13055682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
13155682Smarkm
13255682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type);
13355682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type);
13455682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type);
13555682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
13655682Smarkm					unsigned, struct key_data**);
13755682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
138120948Snectarstatic krb5_error_code derive_key(krb5_context context,
139120948Snectar				  struct encryption_type *et,
140120948Snectar				  struct key_data *key,
141120948Snectar				  const void *constant,
142120948Snectar				  size_t len);
143120948Snectarstatic void hmac(krb5_context context,
144120948Snectar		 struct checksum_type *cm,
145120948Snectar		 const void *data,
146120948Snectar		 size_t len,
147120948Snectar		 unsigned usage,
148120948Snectar		 struct key_data *keyblock,
149120948Snectar		 Checksum *result);
150120948Snectarstatic void free_key_data(krb5_context context, struct key_data *key);
15155682Smarkm
15255682Smarkm/************************************************************
15355682Smarkm *                                                          *
15455682Smarkm ************************************************************/
15555682Smarkm
15655682Smarkmstatic void
157102647Snectarkrb5_DES_random_key(krb5_context context,
15855682Smarkm	       krb5_keyblock *key)
15955682Smarkm{
16055682Smarkm    des_cblock *k = key->keyvalue.data;
16155682Smarkm    do {
16255682Smarkm	krb5_generate_random_block(k, sizeof(des_cblock));
16355682Smarkm	des_set_odd_parity(k);
16455682Smarkm    } while(des_is_weak_key(k));
16555682Smarkm}
16655682Smarkm
16755682Smarkmstatic void
168102647Snectarkrb5_DES_schedule(krb5_context context,
16955682Smarkm	     struct key_data *key)
17055682Smarkm{
17155682Smarkm    des_set_key(key->key->keyvalue.data, key->schedule->data);
17255682Smarkm}
17355682Smarkm
17490929Snectarstatic void
17590929SnectarDES_string_to_key_int(unsigned char *data, size_t length, des_cblock *key)
17690929Snectar{
17790929Snectar    des_key_schedule schedule;
17890929Snectar    int i;
17990929Snectar    int reverse = 0;
18090929Snectar    unsigned char *p;
18190929Snectar
18290929Snectar    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
18390929Snectar			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
18490929Snectar    memset(key, 0, 8);
18590929Snectar
18690929Snectar    p = (unsigned char*)key;
18790929Snectar    for (i = 0; i < length; i++) {
18890929Snectar	unsigned char tmp = data[i];
18990929Snectar	if (!reverse)
19090929Snectar	    *p++ ^= (tmp << 1);
19190929Snectar	else
19290929Snectar	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
19390929Snectar	if((i % 8) == 7)
19490929Snectar	    reverse = !reverse;
19590929Snectar    }
19690929Snectar    des_set_odd_parity(key);
19790929Snectar    if(des_is_weak_key(key))
19890929Snectar	(*key)[7] ^= 0xF0;
19990929Snectar    des_set_key(key, schedule);
20090929Snectar    des_cbc_cksum((void*)data, key, length, schedule, key);
20190929Snectar    memset(schedule, 0, sizeof(schedule));
20290929Snectar    des_set_odd_parity(key);
20390929Snectar}
20490929Snectar
20555682Smarkmstatic krb5_error_code
206102647Snectarkrb5_DES_string_to_key(krb5_context context,
20755682Smarkm		  krb5_enctype enctype,
20855682Smarkm		  krb5_data password,
20955682Smarkm		  krb5_salt salt,
210120948Snectar		  krb5_data opaque,
21155682Smarkm		  krb5_keyblock *key)
21255682Smarkm{
21390929Snectar    unsigned char *s;
21455682Smarkm    size_t len;
21555682Smarkm    des_cblock tmp;
21655682Smarkm
21790929Snectar    len = password.length + salt.saltvalue.length;
21855682Smarkm    s = malloc(len);
21990929Snectar    if(len > 0 && s == NULL) {
22078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
22155682Smarkm	return ENOMEM;
22278536Sassar    }
22355682Smarkm    memcpy(s, password.data, password.length);
22455682Smarkm    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
22590929Snectar    DES_string_to_key_int(s, len, &tmp);
22655682Smarkm    key->keytype = enctype;
22755682Smarkm    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
22855682Smarkm    memset(&tmp, 0, sizeof(tmp));
22955682Smarkm    memset(s, 0, len);
23055682Smarkm    free(s);
23155682Smarkm    return 0;
23255682Smarkm}
23355682Smarkm
23455682Smarkm/* This defines the Andrew string_to_key function.  It accepts a password
23555682Smarkm * string as input and converts its via a one-way encryption algorithm to a DES
23655682Smarkm * encryption key.  It is compatible with the original Andrew authentication
23755682Smarkm * service password database.
23855682Smarkm */
23955682Smarkm
24055682Smarkm/*
24155682Smarkm * Short passwords, i.e 8 characters or less.
24255682Smarkm */
24355682Smarkmstatic void
244102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
24555682Smarkm			    krb5_data cell,
24655682Smarkm			    des_cblock *key)
24755682Smarkm{
24855682Smarkm    char  password[8+1];	/* crypt is limited to 8 chars anyway */
24955682Smarkm    int   i;
25055682Smarkm
25155682Smarkm    for(i = 0; i < 8; i++) {
25255682Smarkm	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
25372448Sassar		 ((i < cell.length) ?
25472448Sassar		  tolower(((unsigned char*)cell.data)[i]) : 0);
25555682Smarkm	password[i] = c ? c : 'X';
25655682Smarkm    }
25755682Smarkm    password[8] = '\0';
25855682Smarkm
259120948Snectar    memcpy(key, crypt(password, "p1") + 2, sizeof(des_cblock));
26055682Smarkm
26155682Smarkm    /* parity is inserted into the LSB so left shift each byte up one
26255682Smarkm       bit. This allows ascii characters with a zero MSB to retain as
26355682Smarkm       much significance as possible. */
26455682Smarkm    for (i = 0; i < sizeof(des_cblock); i++)
26555682Smarkm	((unsigned char*)key)[i] <<= 1;
26655682Smarkm    des_set_odd_parity (key);
26755682Smarkm}
26855682Smarkm
26955682Smarkm/*
27055682Smarkm * Long passwords, i.e 9 characters or more.
27155682Smarkm */
27255682Smarkmstatic void
273102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
27455682Smarkm				 krb5_data cell,
27555682Smarkm				 des_cblock *key)
27655682Smarkm{
27755682Smarkm    des_key_schedule schedule;
27855682Smarkm    des_cblock temp_key;
27955682Smarkm    des_cblock ivec;
28055682Smarkm    char password[512];
28155682Smarkm    size_t passlen;
28255682Smarkm
28355682Smarkm    memcpy(password, pw.data, min(pw.length, sizeof(password)));
28472448Sassar    if(pw.length < sizeof(password)) {
28572448Sassar	int len = min(cell.length, sizeof(password) - pw.length);
28672448Sassar	int i;
28772448Sassar
28872448Sassar	memcpy(password + pw.length, cell.data, len);
28972448Sassar	for (i = pw.length; i < pw.length + len; ++i)
29072448Sassar	    password[i] = tolower((unsigned char)password[i]);
29172448Sassar    }
29255682Smarkm    passlen = min(sizeof(password), pw.length + cell.length);
29355682Smarkm    memcpy(&ivec, "kerberos", 8);
29455682Smarkm    memcpy(&temp_key, "kerberos", 8);
29555682Smarkm    des_set_odd_parity (&temp_key);
29655682Smarkm    des_set_key (&temp_key, schedule);
29790929Snectar    des_cbc_cksum (password, &ivec, passlen, schedule, &ivec);
29855682Smarkm
29955682Smarkm    memcpy(&temp_key, &ivec, 8);
30055682Smarkm    des_set_odd_parity (&temp_key);
30155682Smarkm    des_set_key (&temp_key, schedule);
30290929Snectar    des_cbc_cksum (password, key, passlen, schedule, &ivec);
30355682Smarkm    memset(&schedule, 0, sizeof(schedule));
30455682Smarkm    memset(&temp_key, 0, sizeof(temp_key));
30555682Smarkm    memset(&ivec, 0, sizeof(ivec));
30655682Smarkm    memset(password, 0, sizeof(password));
30755682Smarkm
30855682Smarkm    des_set_odd_parity (key);
30955682Smarkm}
31055682Smarkm
31155682Smarkmstatic krb5_error_code
31255682SmarkmDES_AFS3_string_to_key(krb5_context context,
31355682Smarkm		       krb5_enctype enctype,
31455682Smarkm		       krb5_data password,
31555682Smarkm		       krb5_salt salt,
316120948Snectar		       krb5_data opaque,
31755682Smarkm		       krb5_keyblock *key)
31855682Smarkm{
31955682Smarkm    des_cblock tmp;
32055682Smarkm    if(password.length > 8)
321102647Snectar	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
32255682Smarkm    else
323102647Snectar	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
32455682Smarkm    key->keytype = enctype;
32555682Smarkm    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
32655682Smarkm    memset(&key, 0, sizeof(key));
32755682Smarkm    return 0;
32855682Smarkm}
32955682Smarkm
33055682Smarkmstatic void
33155682SmarkmDES3_random_key(krb5_context context,
33255682Smarkm		krb5_keyblock *key)
33355682Smarkm{
33455682Smarkm    des_cblock *k = key->keyvalue.data;
33555682Smarkm    do {
33655682Smarkm	krb5_generate_random_block(k, 3 * sizeof(des_cblock));
33755682Smarkm	des_set_odd_parity(&k[0]);
33855682Smarkm	des_set_odd_parity(&k[1]);
33955682Smarkm	des_set_odd_parity(&k[2]);
34055682Smarkm    } while(des_is_weak_key(&k[0]) ||
34155682Smarkm	    des_is_weak_key(&k[1]) ||
34255682Smarkm	    des_is_weak_key(&k[2]));
34355682Smarkm}
34455682Smarkm
34555682Smarkmstatic void
34655682SmarkmDES3_schedule(krb5_context context,
34755682Smarkm	      struct key_data *key)
34855682Smarkm{
34955682Smarkm    des_cblock *k = key->key->keyvalue.data;
35055682Smarkm    des_key_schedule *s = key->schedule->data;
35155682Smarkm    des_set_key(&k[0], s[0]);
35255682Smarkm    des_set_key(&k[1], s[1]);
35355682Smarkm    des_set_key(&k[2], s[2]);
35455682Smarkm}
35555682Smarkm
35655682Smarkm/*
35755682Smarkm * A = A xor B. A & B are 8 bytes.
35855682Smarkm */
35955682Smarkm
36055682Smarkmstatic void
36155682Smarkmxor (des_cblock *key, const unsigned char *b)
36255682Smarkm{
36355682Smarkm    unsigned char *a = (unsigned char*)key;
36455682Smarkm    a[0] ^= b[0];
36555682Smarkm    a[1] ^= b[1];
36655682Smarkm    a[2] ^= b[2];
36755682Smarkm    a[3] ^= b[3];
36855682Smarkm    a[4] ^= b[4];
36955682Smarkm    a[5] ^= b[5];
37055682Smarkm    a[6] ^= b[6];
37155682Smarkm    a[7] ^= b[7];
37255682Smarkm}
37355682Smarkm
37455682Smarkmstatic krb5_error_code
37555682SmarkmDES3_string_to_key(krb5_context context,
37655682Smarkm		   krb5_enctype enctype,
37755682Smarkm		   krb5_data password,
37855682Smarkm		   krb5_salt salt,
379120948Snectar		   krb5_data opaque,
38055682Smarkm		   krb5_keyblock *key)
38155682Smarkm{
38255682Smarkm    char *str;
38355682Smarkm    size_t len;
38455682Smarkm    unsigned char tmp[24];
38555682Smarkm    des_cblock keys[3];
38655682Smarkm
38755682Smarkm    len = password.length + salt.saltvalue.length;
38855682Smarkm    str = malloc(len);
38978536Sassar    if(len != 0 && str == NULL) {
39078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
39155682Smarkm	return ENOMEM;
39278536Sassar    }
39355682Smarkm    memcpy(str, password.data, password.length);
39455682Smarkm    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
39555682Smarkm    {
39655682Smarkm	des_cblock ivec;
39755682Smarkm	des_key_schedule s[3];
39855682Smarkm	int i;
39955682Smarkm
40055682Smarkm	_krb5_n_fold(str, len, tmp, 24);
40155682Smarkm
40255682Smarkm	for(i = 0; i < 3; i++){
40355682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
40455682Smarkm	    des_set_odd_parity(keys + i);
40555682Smarkm	    if(des_is_weak_key(keys + i))
406102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
40755682Smarkm	    des_set_key(keys + i, s[i]);
40855682Smarkm	}
40955682Smarkm	memset(&ivec, 0, sizeof(ivec));
41090929Snectar	des_ede3_cbc_encrypt(tmp,
41190929Snectar			     tmp, sizeof(tmp),
41255682Smarkm			     s[0], s[1], s[2], &ivec, DES_ENCRYPT);
41355682Smarkm	memset(s, 0, sizeof(s));
41455682Smarkm	memset(&ivec, 0, sizeof(ivec));
41555682Smarkm	for(i = 0; i < 3; i++){
41655682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
41755682Smarkm	    des_set_odd_parity(keys + i);
41855682Smarkm	    if(des_is_weak_key(keys + i))
419102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
42055682Smarkm	}
42155682Smarkm	memset(tmp, 0, sizeof(tmp));
42255682Smarkm    }
42355682Smarkm    key->keytype = enctype;
42455682Smarkm    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
42555682Smarkm    memset(keys, 0, sizeof(keys));
42655682Smarkm    memset(str, 0, len);
42755682Smarkm    free(str);
42855682Smarkm    return 0;
42955682Smarkm}
43055682Smarkm
43155682Smarkmstatic krb5_error_code
43255682SmarkmDES3_string_to_key_derived(krb5_context context,
43355682Smarkm			   krb5_enctype enctype,
43455682Smarkm			   krb5_data password,
43555682Smarkm			   krb5_salt salt,
436120948Snectar			   krb5_data opaque,
43755682Smarkm			   krb5_keyblock *key)
43855682Smarkm{
43955682Smarkm    krb5_error_code ret;
44055682Smarkm    size_t len = password.length + salt.saltvalue.length;
44155682Smarkm    char *s;
44255682Smarkm
44355682Smarkm    s = malloc(len);
44478536Sassar    if(len != 0 && s == NULL) {
44578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
44655682Smarkm	return ENOMEM;
44778536Sassar    }
44855682Smarkm    memcpy(s, password.data, password.length);
44955682Smarkm    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
45055682Smarkm    ret = krb5_string_to_key_derived(context,
45155682Smarkm				     s,
45255682Smarkm				     len,
45355682Smarkm				     enctype,
45455682Smarkm				     key);
45555682Smarkm    memset(s, 0, len);
45655682Smarkm    free(s);
45755682Smarkm    return ret;
45855682Smarkm}
45955682Smarkm
46055682Smarkm/*
46155682Smarkm * ARCFOUR
46255682Smarkm */
46355682Smarkm
46455682Smarkmstatic void
46555682SmarkmARCFOUR_random_key(krb5_context context, krb5_keyblock *key)
46655682Smarkm{
46755682Smarkm    krb5_generate_random_block (key->keyvalue.data,
46855682Smarkm				key->keyvalue.length);
46955682Smarkm}
47055682Smarkm
47155682Smarkmstatic void
47255682SmarkmARCFOUR_schedule(krb5_context context, struct key_data *kd)
47355682Smarkm{
47455682Smarkm    RC4_set_key (kd->schedule->data,
47555682Smarkm		 kd->key->keyvalue.length, kd->key->keyvalue.data);
47655682Smarkm}
47755682Smarkm
47855682Smarkmstatic krb5_error_code
47955682SmarkmARCFOUR_string_to_key(krb5_context context,
48055682Smarkm		  krb5_enctype enctype,
48155682Smarkm		  krb5_data password,
48255682Smarkm		  krb5_salt salt,
483120948Snectar		  krb5_data opaque,
48455682Smarkm		  krb5_keyblock *key)
48555682Smarkm{
48655682Smarkm    char *s, *p;
48755682Smarkm    size_t len;
48855682Smarkm    int i;
48957416Smarkm    MD4_CTX m;
49055682Smarkm
49172448Sassar    len = 2 * password.length;
49255682Smarkm    s = malloc (len);
49378536Sassar    if (len != 0 && s == NULL) {
49478536Sassar	krb5_set_error_string(context, "malloc: out of memory");
49555682Smarkm	return ENOMEM;
49678536Sassar    }
49755682Smarkm    for (p = s, i = 0; i < password.length; ++i) {
49855682Smarkm	*p++ = ((char *)password.data)[i];
49955682Smarkm	*p++ = 0;
50055682Smarkm    }
50172448Sassar    MD4_Init (&m);
50272448Sassar    MD4_Update (&m, s, len);
50355682Smarkm    key->keytype = enctype;
50455682Smarkm    krb5_data_alloc (&key->keyvalue, 16);
50572448Sassar    MD4_Final (key->keyvalue.data, &m);
50655682Smarkm    memset (s, 0, len);
50755682Smarkm    free (s);
50855682Smarkm    return 0;
50955682Smarkm}
51055682Smarkm
511120948Snectar#ifdef ENABLE_AES
512120948Snectar/*
513120948Snectar * AES
514120948Snectar */
515120948Snectar
516120948Snectar/* iter is really 1 based, so iter == 0 will be 1 iteration */
517120948Snectar
518120948Snectarkrb5_error_code
519120948Snectarkrb5_PKCS5_PBKDF2(krb5_context context, krb5_cksumtype cktype,
520120948Snectar		  krb5_data password, krb5_salt salt, u_int32_t iter,
521120948Snectar		  krb5_keytype type, krb5_keyblock *key)
522120948Snectar{
523120948Snectar    struct checksum_type *c = _find_checksum(cktype);
524120948Snectar    struct key_type *kt;
525120948Snectar    size_t datalen, leftofkey;
526120948Snectar    krb5_error_code ret;
527120948Snectar    u_int32_t keypart;
528120948Snectar    struct key_data ksign;
529120948Snectar    krb5_keyblock kb;
530120948Snectar    Checksum result;
531120948Snectar    char *data, *tmpcksum;
532120948Snectar    int i, j;
533120948Snectar    char *p;
534120948Snectar
535120948Snectar    if (c == NULL) {
536120948Snectar	krb5_set_error_string(context, "checksum %d not supported", cktype);
537120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP;
538120948Snectar    }
539120948Snectar
540120948Snectar    kt = _find_keytype(type);
541120948Snectar    if (kt == NULL) {
542120948Snectar	krb5_set_error_string(context, "key type %d not supported", type);
543120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP;
544120948Snectar    }
545120948Snectar
546120948Snectar    key->keytype = type;
547120948Snectar    ret = krb5_data_alloc (&key->keyvalue, kt->bits / 8);
548120948Snectar    if (ret) {
549120948Snectar	krb5_set_error_string(context, "malloc: out of memory");
550120948Snectar	return ret;
551120948Snectar    }
552120948Snectar
553120948Snectar    ret = krb5_data_alloc (&result.checksum, c->checksumsize);
554120948Snectar    if (ret) {
555120948Snectar	krb5_set_error_string(context, "malloc: out of memory");
556120948Snectar	krb5_data_free (&key->keyvalue);
557120948Snectar	return ret;
558120948Snectar    }
559120948Snectar
560120948Snectar    tmpcksum = malloc(c->checksumsize);
561120948Snectar    if (tmpcksum == NULL) {
562120948Snectar	krb5_set_error_string(context, "malloc: out of memory");
563120948Snectar	krb5_data_free (&key->keyvalue);
564120948Snectar	krb5_data_free (&result.checksum);
565120948Snectar	return ENOMEM;
566120948Snectar    }
567120948Snectar
568120948Snectar    datalen = salt.saltvalue.length + 4;
569120948Snectar    data = malloc(datalen);
570120948Snectar    if (data == NULL) {
571120948Snectar	krb5_set_error_string(context, "malloc: out of memory");
572120948Snectar	free(tmpcksum);
573120948Snectar	krb5_data_free (&key->keyvalue);
574120948Snectar	krb5_data_free (&result.checksum);
575120948Snectar	return ENOMEM;
576120948Snectar    }
577120948Snectar
578120948Snectar    kb.keyvalue = password;
579120948Snectar    ksign.key = &kb;
580120948Snectar
581120948Snectar    memcpy(data, salt.saltvalue.data, salt.saltvalue.length);
582120948Snectar
583120948Snectar    keypart = 1;
584120948Snectar    leftofkey = key->keyvalue.length;
585120948Snectar    p = key->keyvalue.data;
586120948Snectar
587120948Snectar    while (leftofkey) {
588120948Snectar	int len;
589120948Snectar
590120948Snectar	if (leftofkey > c->checksumsize)
591120948Snectar	    len = c->checksumsize;
592120948Snectar	else
593120948Snectar	    len = leftofkey;
594120948Snectar
595120948Snectar	_krb5_put_int(data + datalen - 4, keypart, 4);
596120948Snectar
597120948Snectar	hmac(context, c, data, datalen, 0, &ksign, &result);
598120948Snectar	memcpy(p, result.checksum.data, len);
599120948Snectar	memcpy(tmpcksum, result.checksum.data, result.checksum.length);
600120948Snectar	for (i = 0; i < iter; i++) {
601120948Snectar	    hmac(context, c, tmpcksum, result.checksum.length,
602120948Snectar		 0, &ksign, &result);
603120948Snectar	    memcpy(tmpcksum, result.checksum.data, result.checksum.length);
604120948Snectar	    for (j = 0; j < len; j++)
605120948Snectar		p[j] ^= tmpcksum[j];
606120948Snectar	}
607120948Snectar
608120948Snectar	p += len;
609120948Snectar	leftofkey -= len;
610120948Snectar	keypart++;
611120948Snectar    }
612120948Snectar
613120948Snectar    free(data);
614120948Snectar    free(tmpcksum);
615120948Snectar    krb5_data_free (&result.checksum);
616120948Snectar
617120948Snectar    return 0;
618120948Snectar}
619120948Snectar
620120948Snectarstatic krb5_error_code
621120948SnectarAES_string_to_key(krb5_context context,
622120948Snectar		  krb5_enctype enctype,
623120948Snectar		  krb5_data password,
624120948Snectar		  krb5_salt salt,
625120948Snectar		  krb5_data opaque,
626120948Snectar		  krb5_keyblock *key)
627120948Snectar{
628120948Snectar    krb5_error_code ret;
629120948Snectar    u_int32_t iter;
630120948Snectar    struct encryption_type *et;
631120948Snectar    struct key_data kd;
632120948Snectar
633120948Snectar    if (opaque.length == 0)
634120948Snectar	iter = 45056 - 1;
635120948Snectar    else if (opaque.length == 4) {
636120948Snectar	unsigned long v;
637120948Snectar	_krb5_get_int(opaque.data, &v, 4);
638120948Snectar	iter = ((u_int32_t)v) - 1;
639120948Snectar    } else
640120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
641120948Snectar
642120948Snectar
643120948Snectar    et = _find_enctype(enctype);
644120948Snectar    if (et == NULL)
645120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP;
646120948Snectar
647120948Snectar    ret = krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt,
648120948Snectar			    iter, enctype, key);
649120948Snectar    if (ret)
650120948Snectar	return ret;
651120948Snectar
652120948Snectar    ret = krb5_copy_keyblock(context, key, &kd.key);
653120948Snectar    kd.schedule = NULL;
654120948Snectar
655120948Snectar    ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
656120948Snectar
657120948Snectar    if (ret) {
658120948Snectar	krb5_data_free(&key->keyvalue);
659120948Snectar    } else {
660120948Snectar	ret = krb5_copy_keyblock_contents(context, kd.key, key);
661120948Snectar	free_key_data(context, &kd);
662120948Snectar    }
663120948Snectar
664120948Snectar    return ret;
665120948Snectar}
666120948Snectar
667120948Snectarstatic void
668120948SnectarAES_schedule(krb5_context context, struct key_data *kd)
669120948Snectar{
670120948Snectar    AES_KEY *key = kd->schedule->data;
671120948Snectar    int bits = kd->key->keyvalue.length * 8;
672120948Snectar
673120948Snectar    AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key[0]);
674120948Snectar    AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key[1]);
675120948Snectar}
676120948Snectar
677120948Snectar/*
678120948Snectar *
679120948Snectar */
680120948Snectar
681120948Snectarextern struct salt_type AES_salt[];
682120948Snectar
683120948Snectar#endif /* ENABLE_AES */
684120948Snectar
68555682Smarkmextern struct salt_type des_salt[],
68655682Smarkm    des3_salt[], des3_salt_derived[], arcfour_salt[];
68755682Smarkm
68855682Smarkmstruct key_type keytype_null = {
68955682Smarkm    KEYTYPE_NULL,
69055682Smarkm    "null",
69155682Smarkm    0,
69255682Smarkm    0,
69355682Smarkm    0,
69455682Smarkm    NULL,
69555682Smarkm    NULL,
69655682Smarkm    NULL
69755682Smarkm};
69855682Smarkm
69955682Smarkmstruct key_type keytype_des = {
70055682Smarkm    KEYTYPE_DES,
70155682Smarkm    "des",
70255682Smarkm    56,
70355682Smarkm    sizeof(des_cblock),
70455682Smarkm    sizeof(des_key_schedule),
705102647Snectar    krb5_DES_random_key,
706102647Snectar    krb5_DES_schedule,
70755682Smarkm    des_salt
70855682Smarkm};
70955682Smarkm
71055682Smarkmstruct key_type keytype_des3 = {
71155682Smarkm    KEYTYPE_DES3,
71255682Smarkm    "des3",
71355682Smarkm    168,
71455682Smarkm    3 * sizeof(des_cblock),
71555682Smarkm    3 * sizeof(des_key_schedule),
71655682Smarkm    DES3_random_key,
71755682Smarkm    DES3_schedule,
71855682Smarkm    des3_salt
71955682Smarkm};
72055682Smarkm
72155682Smarkmstruct key_type keytype_des3_derived = {
72255682Smarkm    KEYTYPE_DES3,
72355682Smarkm    "des3",
72455682Smarkm    168,
72555682Smarkm    3 * sizeof(des_cblock),
72655682Smarkm    3 * sizeof(des_key_schedule),
72755682Smarkm    DES3_random_key,
72855682Smarkm    DES3_schedule,
72955682Smarkm    des3_salt_derived
73055682Smarkm};
73155682Smarkm
732120948Snectar#ifdef ENABLE_AES
733120948Snectarstruct key_type keytype_aes128 = {
734120948Snectar    KEYTYPE_AES128,
735120948Snectar    "aes-128",
736120948Snectar    128,
737120948Snectar    16,
738120948Snectar    sizeof(AES_KEY) * 2,
739120948Snectar    NULL,
740120948Snectar    AES_schedule,
741120948Snectar    AES_salt
742120948Snectar};
743120948Snectar
744120948Snectarstruct key_type keytype_aes256 = {
745120948Snectar    KEYTYPE_AES256,
746120948Snectar    "aes-256",
747120948Snectar    256,
748120948Snectar    16,
749120948Snectar    sizeof(AES_KEY) * 2,
750120948Snectar    NULL,
751120948Snectar    AES_schedule,
752120948Snectar    AES_salt
753120948Snectar};
754120948Snectar#endif /* ENABLE_AES */
755120948Snectar
75655682Smarkmstruct key_type keytype_arcfour = {
75755682Smarkm    KEYTYPE_ARCFOUR,
75855682Smarkm    "arcfour",
75955682Smarkm    128,
76055682Smarkm    16,
76155682Smarkm    sizeof(RC4_KEY),
76255682Smarkm    ARCFOUR_random_key,
76355682Smarkm    ARCFOUR_schedule,
76455682Smarkm    arcfour_salt
76555682Smarkm};
76655682Smarkm
76755682Smarkmstruct key_type *keytypes[] = {
76855682Smarkm    &keytype_null,
76955682Smarkm    &keytype_des,
77055682Smarkm    &keytype_des3_derived,
77155682Smarkm    &keytype_des3,
772120948Snectar#ifdef ENABLE_AES
773120948Snectar    &keytype_aes128,
774120948Snectar    &keytype_aes256,
775120948Snectar#endif /* ENABLE_AES */
77655682Smarkm    &keytype_arcfour
77755682Smarkm};
77855682Smarkm
77955682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
78055682Smarkm
78155682Smarkmstatic struct key_type *
78255682Smarkm_find_keytype(krb5_keytype type)
78355682Smarkm{
78455682Smarkm    int i;
78555682Smarkm    for(i = 0; i < num_keytypes; i++)
78655682Smarkm	if(keytypes[i]->type == type)
78755682Smarkm	    return keytypes[i];
78855682Smarkm    return NULL;
78955682Smarkm}
79055682Smarkm
79155682Smarkm
79255682Smarkmstruct salt_type des_salt[] = {
79355682Smarkm    {
79455682Smarkm	KRB5_PW_SALT,
79555682Smarkm	"pw-salt",
796102647Snectar	krb5_DES_string_to_key
79755682Smarkm    },
79855682Smarkm    {
79955682Smarkm	KRB5_AFS3_SALT,
80055682Smarkm	"afs3-salt",
80155682Smarkm	DES_AFS3_string_to_key
80255682Smarkm    },
80355682Smarkm    { 0 }
80455682Smarkm};
80555682Smarkm
80655682Smarkmstruct salt_type des3_salt[] = {
80755682Smarkm    {
80855682Smarkm	KRB5_PW_SALT,
80955682Smarkm	"pw-salt",
81055682Smarkm	DES3_string_to_key
81155682Smarkm    },
81255682Smarkm    { 0 }
81355682Smarkm};
81455682Smarkm
81555682Smarkmstruct salt_type des3_salt_derived[] = {
81655682Smarkm    {
81755682Smarkm	KRB5_PW_SALT,
81855682Smarkm	"pw-salt",
81955682Smarkm	DES3_string_to_key_derived
82055682Smarkm    },
82155682Smarkm    { 0 }
82255682Smarkm};
82355682Smarkm
824120948Snectar#ifdef ENABLE_AES
825120948Snectarstruct salt_type AES_salt[] = {
826120948Snectar    {
827120948Snectar	KRB5_PW_SALT,
828120948Snectar	"pw-salt",
829120948Snectar	AES_string_to_key
830120948Snectar    },
831120948Snectar    { 0 }
832120948Snectar};
833120948Snectar#endif /* ENABLE_AES */
834120948Snectar
83555682Smarkmstruct salt_type arcfour_salt[] = {
83655682Smarkm    {
83755682Smarkm	KRB5_PW_SALT,
83855682Smarkm	"pw-salt",
83955682Smarkm	ARCFOUR_string_to_key
84055682Smarkm    },
84155682Smarkm    { 0 }
84255682Smarkm};
84355682Smarkm
84455682Smarkmkrb5_error_code
84555682Smarkmkrb5_salttype_to_string (krb5_context context,
84655682Smarkm			 krb5_enctype etype,
84755682Smarkm			 krb5_salttype stype,
84855682Smarkm			 char **string)
84955682Smarkm{
85055682Smarkm    struct encryption_type *e;
85155682Smarkm    struct salt_type *st;
85255682Smarkm
85355682Smarkm    e = _find_enctype (etype);
85478536Sassar    if (e == NULL) {
85578536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
85678536Sassar			      etype);
85755682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
85878536Sassar    }
85955682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
86055682Smarkm	if (st->type == stype) {
86155682Smarkm	    *string = strdup (st->name);
86278536Sassar	    if (*string == NULL) {
86378536Sassar		krb5_set_error_string(context, "malloc: out of memory");
86455682Smarkm		return ENOMEM;
86578536Sassar	    }
86655682Smarkm	    return 0;
86755682Smarkm	}
86855682Smarkm    }
86978536Sassar    krb5_set_error_string(context, "salttype %d not supported", stype);
87055682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
87155682Smarkm}
87255682Smarkm
87355682Smarkmkrb5_error_code
87455682Smarkmkrb5_string_to_salttype (krb5_context context,
87555682Smarkm			 krb5_enctype etype,
87655682Smarkm			 const char *string,
87755682Smarkm			 krb5_salttype *salttype)
87855682Smarkm{
87955682Smarkm    struct encryption_type *e;
88055682Smarkm    struct salt_type *st;
88155682Smarkm
88255682Smarkm    e = _find_enctype (etype);
88378536Sassar    if (e == NULL) {
88478536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
88578536Sassar			      etype);
88655682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
88778536Sassar    }
88855682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
88955682Smarkm	if (strcasecmp (st->name, string) == 0) {
89055682Smarkm	    *salttype = st->type;
89155682Smarkm	    return 0;
89255682Smarkm	}
89355682Smarkm    }
89478536Sassar    krb5_set_error_string(context, "salttype %s not supported", string);
89555682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
89655682Smarkm}
89755682Smarkm
89855682Smarkmkrb5_error_code
89955682Smarkmkrb5_get_pw_salt(krb5_context context,
90055682Smarkm		 krb5_const_principal principal,
90155682Smarkm		 krb5_salt *salt)
90255682Smarkm{
90355682Smarkm    size_t len;
90455682Smarkm    int i;
90555682Smarkm    krb5_error_code ret;
90655682Smarkm    char *p;
90755682Smarkm
90855682Smarkm    salt->salttype = KRB5_PW_SALT;
90955682Smarkm    len = strlen(principal->realm);
91055682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i)
91155682Smarkm	len += strlen(principal->name.name_string.val[i]);
91255682Smarkm    ret = krb5_data_alloc (&salt->saltvalue, len);
91355682Smarkm    if (ret)
91455682Smarkm	return ret;
91555682Smarkm    p = salt->saltvalue.data;
91655682Smarkm    memcpy (p, principal->realm, strlen(principal->realm));
91755682Smarkm    p += strlen(principal->realm);
91855682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i) {
91955682Smarkm	memcpy (p,
92055682Smarkm		principal->name.name_string.val[i],
92155682Smarkm		strlen(principal->name.name_string.val[i]));
92255682Smarkm	p += strlen(principal->name.name_string.val[i]);
92355682Smarkm    }
92455682Smarkm    return 0;
92555682Smarkm}
92655682Smarkm
92755682Smarkmkrb5_error_code
92855682Smarkmkrb5_free_salt(krb5_context context,
92955682Smarkm	       krb5_salt salt)
93055682Smarkm{
93155682Smarkm    krb5_data_free(&salt.saltvalue);
93255682Smarkm    return 0;
93355682Smarkm}
93455682Smarkm
93555682Smarkmkrb5_error_code
93655682Smarkmkrb5_string_to_key_data (krb5_context context,
93755682Smarkm			 krb5_enctype enctype,
93855682Smarkm			 krb5_data password,
93955682Smarkm			 krb5_principal principal,
94055682Smarkm			 krb5_keyblock *key)
94155682Smarkm{
94255682Smarkm    krb5_error_code ret;
94355682Smarkm    krb5_salt salt;
94455682Smarkm
94555682Smarkm    ret = krb5_get_pw_salt(context, principal, &salt);
94655682Smarkm    if(ret)
94755682Smarkm	return ret;
94855682Smarkm    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
94955682Smarkm    krb5_free_salt(context, salt);
95055682Smarkm    return ret;
95155682Smarkm}
95255682Smarkm
95355682Smarkmkrb5_error_code
95455682Smarkmkrb5_string_to_key (krb5_context context,
95555682Smarkm		    krb5_enctype enctype,
95655682Smarkm		    const char *password,
95755682Smarkm		    krb5_principal principal,
95855682Smarkm		    krb5_keyblock *key)
95955682Smarkm{
96055682Smarkm    krb5_data pw;
96155682Smarkm    pw.data = (void*)password;
96255682Smarkm    pw.length = strlen(password);
96355682Smarkm    return krb5_string_to_key_data(context, enctype, pw, principal, key);
96455682Smarkm}
96555682Smarkm
96655682Smarkmkrb5_error_code
96755682Smarkmkrb5_string_to_key_data_salt (krb5_context context,
96855682Smarkm			      krb5_enctype enctype,
96955682Smarkm			      krb5_data password,
97055682Smarkm			      krb5_salt salt,
97155682Smarkm			      krb5_keyblock *key)
97255682Smarkm{
973120948Snectar    krb5_data opaque;
974120948Snectar    krb5_data_zero(&opaque);
975120948Snectar    return krb5_string_to_key_data_salt_opaque(context, enctype, password,
976120948Snectar					       salt, opaque, key);
977120948Snectar}
978120948Snectar
979120948Snectar/*
980120948Snectar * Do a string -> key for encryption type `enctype' operation on
981120948Snectar * `password' (with salt `salt' and the enctype specific data string
982120948Snectar * `opaque'), returning the resulting key in `key'
983120948Snectar */
984120948Snectar
985120948Snectarkrb5_error_code
986120948Snectarkrb5_string_to_key_data_salt_opaque (krb5_context context,
987120948Snectar				     krb5_enctype enctype,
988120948Snectar				     krb5_data password,
989120948Snectar				     krb5_salt salt,
990120948Snectar				     krb5_data opaque,
991120948Snectar				     krb5_keyblock *key)
992120948Snectar{
99355682Smarkm    struct encryption_type *et =_find_enctype(enctype);
99455682Smarkm    struct salt_type *st;
99578536Sassar    if(et == NULL) {
99678536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
99778536Sassar			      enctype);
99855682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
99978536Sassar    }
100055682Smarkm    for(st = et->keytype->string_to_key; st && st->type; st++)
100155682Smarkm	if(st->type == salt.salttype)
1002120948Snectar	    return (*st->string_to_key)(context, enctype, password,
1003120948Snectar					salt, opaque, key);
100478536Sassar    krb5_set_error_string(context, "salt type %d not supported",
100578536Sassar			  salt.salttype);
100655682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
100755682Smarkm}
100855682Smarkm
100972448Sassar/*
101072448Sassar * Do a string -> key for encryption type `enctype' operation on the
101172448Sassar * string `password' (with salt `salt'), returning the resulting key
101272448Sassar * in `key'
101372448Sassar */
101472448Sassar
101555682Smarkmkrb5_error_code
101655682Smarkmkrb5_string_to_key_salt (krb5_context context,
101755682Smarkm			 krb5_enctype enctype,
101855682Smarkm			 const char *password,
101955682Smarkm			 krb5_salt salt,
102055682Smarkm			 krb5_keyblock *key)
102155682Smarkm{
102255682Smarkm    krb5_data pw;
102355682Smarkm    pw.data = (void*)password;
102455682Smarkm    pw.length = strlen(password);
102555682Smarkm    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
102655682Smarkm}
102755682Smarkm
102855682Smarkmkrb5_error_code
102955682Smarkmkrb5_keytype_to_string(krb5_context context,
103055682Smarkm		       krb5_keytype keytype,
103155682Smarkm		       char **string)
103255682Smarkm{
103355682Smarkm    struct key_type *kt = _find_keytype(keytype);
103478536Sassar    if(kt == NULL) {
103578536Sassar	krb5_set_error_string(context, "key type %d not supported", keytype);
103655682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
103778536Sassar    }
103855682Smarkm    *string = strdup(kt->name);
103978536Sassar    if(*string == NULL) {
104078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
104155682Smarkm	return ENOMEM;
104278536Sassar    }
104355682Smarkm    return 0;
104455682Smarkm}
104555682Smarkm
104655682Smarkmkrb5_error_code
104755682Smarkmkrb5_string_to_keytype(krb5_context context,
104855682Smarkm		       const char *string,
104955682Smarkm		       krb5_keytype *keytype)
105055682Smarkm{
105155682Smarkm    int i;
105255682Smarkm    for(i = 0; i < num_keytypes; i++)
105355682Smarkm	if(strcasecmp(keytypes[i]->name, string) == 0){
105455682Smarkm	    *keytype = keytypes[i]->type;
105555682Smarkm	    return 0;
105655682Smarkm	}
105778536Sassar    krb5_set_error_string(context, "key type %s not supported", string);
105855682Smarkm    return KRB5_PROG_KEYTYPE_NOSUPP;
105955682Smarkm}
106055682Smarkm
106155682Smarkmkrb5_error_code
1062120948Snectarkrb5_enctype_keysize(krb5_context context,
1063120948Snectar		     krb5_enctype type,
1064120948Snectar		     size_t *keysize)
1065120948Snectar{
1066120948Snectar    struct encryption_type *et = _find_enctype(type);
1067120948Snectar    if(et == NULL) {
1068120948Snectar	krb5_set_error_string(context, "encryption type %d not supported",
1069120948Snectar			      type);
1070120948Snectar	return KRB5_PROG_ETYPE_NOSUPP;
1071120948Snectar    }
1072120948Snectar    *keysize = et->keytype->size;
1073120948Snectar    return 0;
1074120948Snectar}
1075120948Snectar
1076120948Snectarkrb5_error_code
107755682Smarkmkrb5_generate_random_keyblock(krb5_context context,
107855682Smarkm			      krb5_enctype type,
107955682Smarkm			      krb5_keyblock *key)
108055682Smarkm{
108155682Smarkm    krb5_error_code ret;
108255682Smarkm    struct encryption_type *et = _find_enctype(type);
108378536Sassar    if(et == NULL) {
108478536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
108578536Sassar			      type);
108655682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
108778536Sassar    }
108855682Smarkm    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
108955682Smarkm    if(ret)
109055682Smarkm	return ret;
109155682Smarkm    key->keytype = type;
109255682Smarkm    if(et->keytype->random_key)
109355682Smarkm	(*et->keytype->random_key)(context, key);
109455682Smarkm    else
109555682Smarkm	krb5_generate_random_block(key->keyvalue.data,
109655682Smarkm				   key->keyvalue.length);
109755682Smarkm    return 0;
109855682Smarkm}
109955682Smarkm
110055682Smarkmstatic krb5_error_code
110155682Smarkm_key_schedule(krb5_context context,
110255682Smarkm	      struct key_data *key)
110355682Smarkm{
110455682Smarkm    krb5_error_code ret;
110555682Smarkm    struct encryption_type *et = _find_enctype(key->key->keytype);
110655682Smarkm    struct key_type *kt = et->keytype;
110755682Smarkm
110855682Smarkm    if(kt->schedule == NULL)
110955682Smarkm	return 0;
111072448Sassar    if (key->schedule != NULL)
111172448Sassar	return 0;
111255682Smarkm    ALLOC(key->schedule, 1);
111378536Sassar    if(key->schedule == NULL) {
111478536Sassar	krb5_set_error_string(context, "malloc: out of memory");
111555682Smarkm	return ENOMEM;
111678536Sassar    }
111755682Smarkm    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
111855682Smarkm    if(ret) {
111955682Smarkm	free(key->schedule);
112055682Smarkm	key->schedule = NULL;
112155682Smarkm	return ret;
112255682Smarkm    }
112355682Smarkm    (*kt->schedule)(context, key);
112455682Smarkm    return 0;
112555682Smarkm}
112655682Smarkm
112755682Smarkm/************************************************************
112855682Smarkm *                                                          *
112955682Smarkm ************************************************************/
113055682Smarkm
113155682Smarkmstatic void
113255682SmarkmNONE_checksum(krb5_context context,
113355682Smarkm	      struct key_data *key,
113472448Sassar	      const void *data,
113555682Smarkm	      size_t len,
113672448Sassar	      unsigned usage,
113755682Smarkm	      Checksum *C)
113855682Smarkm{
113955682Smarkm}
114055682Smarkm
114155682Smarkmstatic void
114255682SmarkmCRC32_checksum(krb5_context context,
114355682Smarkm	       struct key_data *key,
114472448Sassar	       const void *data,
114555682Smarkm	       size_t len,
114672448Sassar	       unsigned usage,
114755682Smarkm	       Checksum *C)
114855682Smarkm{
114955682Smarkm    u_int32_t crc;
115055682Smarkm    unsigned char *r = C->checksum.data;
115155682Smarkm    _krb5_crc_init_table ();
115255682Smarkm    crc = _krb5_crc_update (data, len, 0);
115355682Smarkm    r[0] = crc & 0xff;
115455682Smarkm    r[1] = (crc >> 8)  & 0xff;
115555682Smarkm    r[2] = (crc >> 16) & 0xff;
115655682Smarkm    r[3] = (crc >> 24) & 0xff;
115755682Smarkm}
115855682Smarkm
115955682Smarkmstatic void
116055682SmarkmRSA_MD4_checksum(krb5_context context,
116155682Smarkm		 struct key_data *key,
116272448Sassar		 const void *data,
116355682Smarkm		 size_t len,
116472448Sassar		 unsigned usage,
116555682Smarkm		 Checksum *C)
116655682Smarkm{
116757416Smarkm    MD4_CTX m;
116857416Smarkm
116972448Sassar    MD4_Init (&m);
117072448Sassar    MD4_Update (&m, data, len);
117172448Sassar    MD4_Final (C->checksum.data, &m);
117255682Smarkm}
117355682Smarkm
117455682Smarkmstatic void
117555682SmarkmRSA_MD4_DES_checksum(krb5_context context,
117655682Smarkm		     struct key_data *key,
117772448Sassar		     const void *data,
117855682Smarkm		     size_t len,
117972448Sassar		     unsigned usage,
118055682Smarkm		     Checksum *cksum)
118155682Smarkm{
118257416Smarkm    MD4_CTX md4;
118355682Smarkm    des_cblock ivec;
118455682Smarkm    unsigned char *p = cksum->checksum.data;
118555682Smarkm
118655682Smarkm    krb5_generate_random_block(p, 8);
118772448Sassar    MD4_Init (&md4);
118872448Sassar    MD4_Update (&md4, p, 8);
118972448Sassar    MD4_Update (&md4, data, len);
119072448Sassar    MD4_Final (p + 8, &md4);
119155682Smarkm    memset (&ivec, 0, sizeof(ivec));
119290929Snectar    des_cbc_encrypt(p,
119390929Snectar		    p,
119455682Smarkm		    24,
119555682Smarkm		    key->schedule->data,
119655682Smarkm		    &ivec,
119755682Smarkm		    DES_ENCRYPT);
119855682Smarkm}
119955682Smarkm
120055682Smarkmstatic krb5_error_code
120155682SmarkmRSA_MD4_DES_verify(krb5_context context,
120255682Smarkm		   struct key_data *key,
120372448Sassar		   const void *data,
120455682Smarkm		   size_t len,
120572448Sassar		   unsigned usage,
120655682Smarkm		   Checksum *C)
120755682Smarkm{
120857416Smarkm    MD4_CTX md4;
120955682Smarkm    unsigned char tmp[24];
121055682Smarkm    unsigned char res[16];
121155682Smarkm    des_cblock ivec;
121255682Smarkm    krb5_error_code ret = 0;
121355682Smarkm
121455682Smarkm    memset(&ivec, 0, sizeof(ivec));
121557416Smarkm    des_cbc_encrypt(C->checksum.data,
121655682Smarkm		    (void*)tmp,
121755682Smarkm		    C->checksum.length,
121855682Smarkm		    key->schedule->data,
121955682Smarkm		    &ivec,
122055682Smarkm		    DES_DECRYPT);
122172448Sassar    MD4_Init (&md4);
122272448Sassar    MD4_Update (&md4, tmp, 8); /* confounder */
122372448Sassar    MD4_Update (&md4, data, len);
122472448Sassar    MD4_Final (res, &md4);
122578536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
122678536Sassar	krb5_clear_error_string (context);
122755682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
122878536Sassar    }
122955682Smarkm    memset(tmp, 0, sizeof(tmp));
123055682Smarkm    memset(res, 0, sizeof(res));
123155682Smarkm    return ret;
123255682Smarkm}
123355682Smarkm
123455682Smarkmstatic void
123555682SmarkmRSA_MD5_checksum(krb5_context context,
123655682Smarkm		 struct key_data *key,
123772448Sassar		 const void *data,
123855682Smarkm		 size_t len,
123972448Sassar		 unsigned usage,
124055682Smarkm		 Checksum *C)
124155682Smarkm{
124257416Smarkm    MD5_CTX m;
124357416Smarkm
124472448Sassar    MD5_Init  (&m);
124572448Sassar    MD5_Update(&m, data, len);
124672448Sassar    MD5_Final (C->checksum.data, &m);
124755682Smarkm}
124855682Smarkm
124955682Smarkmstatic void
125055682SmarkmRSA_MD5_DES_checksum(krb5_context context,
125155682Smarkm		     struct key_data *key,
125272448Sassar		     const void *data,
125355682Smarkm		     size_t len,
125472448Sassar		     unsigned usage,
125555682Smarkm		     Checksum *C)
125655682Smarkm{
125757416Smarkm    MD5_CTX md5;
125855682Smarkm    des_cblock ivec;
125955682Smarkm    unsigned char *p = C->checksum.data;
126055682Smarkm
126155682Smarkm    krb5_generate_random_block(p, 8);
126272448Sassar    MD5_Init (&md5);
126372448Sassar    MD5_Update (&md5, p, 8);
126472448Sassar    MD5_Update (&md5, data, len);
126572448Sassar    MD5_Final (p + 8, &md5);
126655682Smarkm    memset (&ivec, 0, sizeof(ivec));
126790929Snectar    des_cbc_encrypt(p,
126890929Snectar		    p,
126955682Smarkm		    24,
127055682Smarkm		    key->schedule->data,
127155682Smarkm		    &ivec,
127255682Smarkm		    DES_ENCRYPT);
127355682Smarkm}
127455682Smarkm
127555682Smarkmstatic krb5_error_code
127655682SmarkmRSA_MD5_DES_verify(krb5_context context,
127755682Smarkm		   struct key_data *key,
127872448Sassar		   const void *data,
127955682Smarkm		   size_t len,
128072448Sassar		   unsigned usage,
128155682Smarkm		   Checksum *C)
128255682Smarkm{
128357416Smarkm    MD5_CTX md5;
128455682Smarkm    unsigned char tmp[24];
128555682Smarkm    unsigned char res[16];
128655682Smarkm    des_cblock ivec;
128755682Smarkm    des_key_schedule *sched = key->schedule->data;
128855682Smarkm    krb5_error_code ret = 0;
128955682Smarkm
129055682Smarkm    memset(&ivec, 0, sizeof(ivec));
129155682Smarkm    des_cbc_encrypt(C->checksum.data,
129255682Smarkm		    (void*)tmp,
129355682Smarkm		    C->checksum.length,
129455682Smarkm		    sched[0],
129555682Smarkm		    &ivec,
129655682Smarkm		    DES_DECRYPT);
129772448Sassar    MD5_Init (&md5);
129872448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
129972448Sassar    MD5_Update (&md5, data, len);
130072448Sassar    MD5_Final (res, &md5);
130178536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
130278536Sassar	krb5_clear_error_string (context);
130355682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
130478536Sassar    }
130555682Smarkm    memset(tmp, 0, sizeof(tmp));
130655682Smarkm    memset(res, 0, sizeof(res));
130755682Smarkm    return ret;
130855682Smarkm}
130955682Smarkm
131055682Smarkmstatic void
131155682SmarkmRSA_MD5_DES3_checksum(krb5_context context,
131255682Smarkm		      struct key_data *key,
131372448Sassar		      const void *data,
131455682Smarkm		      size_t len,
131572448Sassar		      unsigned usage,
131655682Smarkm		      Checksum *C)
131755682Smarkm{
131857416Smarkm    MD5_CTX md5;
131955682Smarkm    des_cblock ivec;
132055682Smarkm    unsigned char *p = C->checksum.data;
132155682Smarkm    des_key_schedule *sched = key->schedule->data;
132255682Smarkm
132355682Smarkm    krb5_generate_random_block(p, 8);
132472448Sassar    MD5_Init (&md5);
132572448Sassar    MD5_Update (&md5, p, 8);
132672448Sassar    MD5_Update (&md5, data, len);
132772448Sassar    MD5_Final (p + 8, &md5);
132855682Smarkm    memset (&ivec, 0, sizeof(ivec));
132990929Snectar    des_ede3_cbc_encrypt(p,
133090929Snectar			 p,
133155682Smarkm			 24,
133255682Smarkm			 sched[0], sched[1], sched[2],
133355682Smarkm			 &ivec,
133455682Smarkm			 DES_ENCRYPT);
133555682Smarkm}
133655682Smarkm
133755682Smarkmstatic krb5_error_code
133855682SmarkmRSA_MD5_DES3_verify(krb5_context context,
133955682Smarkm		    struct key_data *key,
134072448Sassar		    const void *data,
134155682Smarkm		    size_t len,
134272448Sassar		    unsigned usage,
134355682Smarkm		    Checksum *C)
134455682Smarkm{
134557416Smarkm    MD5_CTX md5;
134655682Smarkm    unsigned char tmp[24];
134755682Smarkm    unsigned char res[16];
134855682Smarkm    des_cblock ivec;
134955682Smarkm    des_key_schedule *sched = key->schedule->data;
135055682Smarkm    krb5_error_code ret = 0;
135155682Smarkm
135255682Smarkm    memset(&ivec, 0, sizeof(ivec));
135355682Smarkm    des_ede3_cbc_encrypt(C->checksum.data,
135455682Smarkm			 (void*)tmp,
135555682Smarkm			 C->checksum.length,
135655682Smarkm			 sched[0], sched[1], sched[2],
135755682Smarkm			 &ivec,
135855682Smarkm			 DES_DECRYPT);
135972448Sassar    MD5_Init (&md5);
136072448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
136172448Sassar    MD5_Update (&md5, data, len);
136272448Sassar    MD5_Final (res, &md5);
136378536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
136478536Sassar	krb5_clear_error_string (context);
136555682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
136678536Sassar    }
136755682Smarkm    memset(tmp, 0, sizeof(tmp));
136855682Smarkm    memset(res, 0, sizeof(res));
136955682Smarkm    return ret;
137055682Smarkm}
137155682Smarkm
137255682Smarkmstatic void
137355682SmarkmSHA1_checksum(krb5_context context,
137455682Smarkm	      struct key_data *key,
137572448Sassar	      const void *data,
137655682Smarkm	      size_t len,
137772448Sassar	      unsigned usage,
137855682Smarkm	      Checksum *C)
137955682Smarkm{
138072448Sassar    SHA_CTX m;
138157416Smarkm
138272448Sassar    SHA1_Init(&m);
138372448Sassar    SHA1_Update(&m, data, len);
138472448Sassar    SHA1_Final(C->checksum.data, &m);
138555682Smarkm}
138655682Smarkm
138755682Smarkm/* HMAC according to RFC2104 */
138855682Smarkmstatic void
138955682Smarkmhmac(krb5_context context,
139055682Smarkm     struct checksum_type *cm,
139172448Sassar     const void *data,
139255682Smarkm     size_t len,
139372448Sassar     unsigned usage,
139455682Smarkm     struct key_data *keyblock,
139555682Smarkm     Checksum *result)
139655682Smarkm{
139755682Smarkm    unsigned char *ipad, *opad;
139855682Smarkm    unsigned char *key;
139955682Smarkm    size_t key_len;
140055682Smarkm    int i;
140155682Smarkm
140255682Smarkm    if(keyblock->key->keyvalue.length > cm->blocksize){
140355682Smarkm	(*cm->checksum)(context,
140455682Smarkm			keyblock,
140555682Smarkm			keyblock->key->keyvalue.data,
140655682Smarkm			keyblock->key->keyvalue.length,
140772448Sassar			usage,
140855682Smarkm			result);
140955682Smarkm	key = result->checksum.data;
141055682Smarkm	key_len = result->checksum.length;
141155682Smarkm    } else {
141255682Smarkm	key = keyblock->key->keyvalue.data;
141355682Smarkm	key_len = keyblock->key->keyvalue.length;
141455682Smarkm    }
141555682Smarkm    ipad = malloc(cm->blocksize + len);
141655682Smarkm    opad = malloc(cm->blocksize + cm->checksumsize);
141755682Smarkm    memset(ipad, 0x36, cm->blocksize);
141855682Smarkm    memset(opad, 0x5c, cm->blocksize);
141955682Smarkm    for(i = 0; i < key_len; i++){
142055682Smarkm	ipad[i] ^= key[i];
142155682Smarkm	opad[i] ^= key[i];
142255682Smarkm    }
142355682Smarkm    memcpy(ipad + cm->blocksize, data, len);
142472448Sassar    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
142572448Sassar		    usage, result);
142655682Smarkm    memcpy(opad + cm->blocksize, result->checksum.data,
142755682Smarkm	   result->checksum.length);
142855682Smarkm    (*cm->checksum)(context, keyblock, opad,
142972448Sassar		    cm->blocksize + cm->checksumsize, usage, result);
143055682Smarkm    memset(ipad, 0, cm->blocksize + len);
143155682Smarkm    free(ipad);
143255682Smarkm    memset(opad, 0, cm->blocksize + cm->checksumsize);
143355682Smarkm    free(opad);
143455682Smarkm}
143555682Smarkm
143655682Smarkmstatic void
1437120948SnectarSP_HMAC_SHA1_checksum(krb5_context context,
1438120948Snectar		      struct key_data *key,
1439120948Snectar		      const void *data,
1440120948Snectar		      size_t len,
1441120948Snectar		      unsigned usage,
1442120948Snectar		      Checksum *result)
144355682Smarkm{
144455682Smarkm    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1445120948Snectar    Checksum res;
1446120948Snectar    char sha1_data[20];
144755682Smarkm
1448120948Snectar    res.checksum.data = sha1_data;
1449120948Snectar    res.checksum.length = sizeof(sha1_data);
1450120948Snectar
1451120948Snectar    hmac(context, c, data, len, usage, key, &res);
1452120948Snectar    memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
145355682Smarkm}
145455682Smarkm
145572448Sassar/*
145672448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
145772448Sassar */
145872448Sassar
145972448Sassarstatic void
146072448SassarHMAC_MD5_checksum(krb5_context context,
146172448Sassar		  struct key_data *key,
146272448Sassar		  const void *data,
146372448Sassar		  size_t len,
146472448Sassar		  unsigned usage,
146572448Sassar		  Checksum *result)
146672448Sassar{
146772448Sassar    MD5_CTX md5;
146872448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
146972448Sassar    const char signature[] = "signaturekey";
147072448Sassar    Checksum ksign_c;
147172448Sassar    struct key_data ksign;
147272448Sassar    krb5_keyblock kb;
147372448Sassar    unsigned char t[4];
147472448Sassar    unsigned char tmp[16];
147572448Sassar    unsigned char ksign_c_data[16];
147672448Sassar
147772448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
147872448Sassar    ksign_c.checksum.data   = ksign_c_data;
147972448Sassar    hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
148072448Sassar    ksign.key = &kb;
148172448Sassar    kb.keyvalue = ksign_c.checksum;
148272448Sassar    MD5_Init (&md5);
148372448Sassar    t[0] = (usage >>  0) & 0xFF;
148472448Sassar    t[1] = (usage >>  8) & 0xFF;
148572448Sassar    t[2] = (usage >> 16) & 0xFF;
148672448Sassar    t[3] = (usage >> 24) & 0xFF;
148772448Sassar    MD5_Update (&md5, t, 4);
148872448Sassar    MD5_Update (&md5, data, len);
148972448Sassar    MD5_Final (tmp, &md5);
149072448Sassar    hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
149172448Sassar}
149272448Sassar
149372448Sassar/*
149472448Sassar * same as previous but being used while encrypting.
149572448Sassar */
149672448Sassar
149772448Sassarstatic void
149872448SassarHMAC_MD5_checksum_enc(krb5_context context,
149972448Sassar		      struct key_data *key,
150072448Sassar		      const void *data,
150172448Sassar		      size_t len,
150272448Sassar		      unsigned usage,
150372448Sassar		      Checksum *result)
150472448Sassar{
150572448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
150672448Sassar    Checksum ksign_c;
150772448Sassar    struct key_data ksign;
150872448Sassar    krb5_keyblock kb;
150972448Sassar    unsigned char t[4];
151072448Sassar    unsigned char ksign_c_data[16];
151172448Sassar
151272448Sassar    t[0] = (usage >>  0) & 0xFF;
151372448Sassar    t[1] = (usage >>  8) & 0xFF;
151472448Sassar    t[2] = (usage >> 16) & 0xFF;
151572448Sassar    t[3] = (usage >> 24) & 0xFF;
151672448Sassar
151772448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
151872448Sassar    ksign_c.checksum.data   = ksign_c_data;
151972448Sassar    hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
152072448Sassar    ksign.key = &kb;
152172448Sassar    kb.keyvalue = ksign_c.checksum;
152272448Sassar    hmac(context, c, data, len, 0, &ksign, result);
152372448Sassar}
152472448Sassar
152555682Smarkmstruct checksum_type checksum_none = {
152655682Smarkm    CKSUMTYPE_NONE,
152755682Smarkm    "none",
152855682Smarkm    1,
152955682Smarkm    0,
153055682Smarkm    0,
153155682Smarkm    NONE_checksum,
153255682Smarkm    NULL
153355682Smarkm};
153455682Smarkmstruct checksum_type checksum_crc32 = {
153555682Smarkm    CKSUMTYPE_CRC32,
153655682Smarkm    "crc32",
153755682Smarkm    1,
153855682Smarkm    4,
153955682Smarkm    0,
154055682Smarkm    CRC32_checksum,
154155682Smarkm    NULL
154255682Smarkm};
154355682Smarkmstruct checksum_type checksum_rsa_md4 = {
154455682Smarkm    CKSUMTYPE_RSA_MD4,
154555682Smarkm    "rsa-md4",
154655682Smarkm    64,
154755682Smarkm    16,
154855682Smarkm    F_CPROOF,
154955682Smarkm    RSA_MD4_checksum,
155055682Smarkm    NULL
155155682Smarkm};
155255682Smarkmstruct checksum_type checksum_rsa_md4_des = {
155355682Smarkm    CKSUMTYPE_RSA_MD4_DES,
155455682Smarkm    "rsa-md4-des",
155555682Smarkm    64,
155655682Smarkm    24,
155755682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
155855682Smarkm    RSA_MD4_DES_checksum,
155955682Smarkm    RSA_MD4_DES_verify
156055682Smarkm};
156155682Smarkm#if 0
156255682Smarkmstruct checksum_type checksum_des_mac = {
156355682Smarkm    CKSUMTYPE_DES_MAC,
156455682Smarkm    "des-mac",
156555682Smarkm    0,
156655682Smarkm    0,
156755682Smarkm    0,
156872448Sassar    DES_MAC_checksum
156955682Smarkm};
157055682Smarkmstruct checksum_type checksum_des_mac_k = {
157155682Smarkm    CKSUMTYPE_DES_MAC_K,
157255682Smarkm    "des-mac-k",
157355682Smarkm    0,
157455682Smarkm    0,
157555682Smarkm    0,
157672448Sassar    DES_MAC_K_checksum
157755682Smarkm};
157855682Smarkmstruct checksum_type checksum_rsa_md4_des_k = {
157955682Smarkm    CKSUMTYPE_RSA_MD4_DES_K,
158055682Smarkm    "rsa-md4-des-k",
158155682Smarkm    0,
158255682Smarkm    0,
158355682Smarkm    0,
158472448Sassar    RSA_MD4_DES_K_checksum,
158572448Sassar    RSA_MD4_DES_K_verify
158655682Smarkm};
158755682Smarkm#endif
158855682Smarkmstruct checksum_type checksum_rsa_md5 = {
158955682Smarkm    CKSUMTYPE_RSA_MD5,
159055682Smarkm    "rsa-md5",
159155682Smarkm    64,
159255682Smarkm    16,
159355682Smarkm    F_CPROOF,
159455682Smarkm    RSA_MD5_checksum,
159555682Smarkm    NULL
159655682Smarkm};
159755682Smarkmstruct checksum_type checksum_rsa_md5_des = {
159855682Smarkm    CKSUMTYPE_RSA_MD5_DES,
159955682Smarkm    "rsa-md5-des",
160055682Smarkm    64,
160155682Smarkm    24,
160255682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
160355682Smarkm    RSA_MD5_DES_checksum,
160472448Sassar    RSA_MD5_DES_verify
160555682Smarkm};
160655682Smarkmstruct checksum_type checksum_rsa_md5_des3 = {
160755682Smarkm    CKSUMTYPE_RSA_MD5_DES3,
160855682Smarkm    "rsa-md5-des3",
160955682Smarkm    64,
161055682Smarkm    24,
161155682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
161255682Smarkm    RSA_MD5_DES3_checksum,
161372448Sassar    RSA_MD5_DES3_verify
161455682Smarkm};
161555682Smarkmstruct checksum_type checksum_sha1 = {
161655682Smarkm    CKSUMTYPE_SHA1,
161755682Smarkm    "sha1",
161855682Smarkm    64,
161955682Smarkm    20,
162055682Smarkm    F_CPROOF,
162155682Smarkm    SHA1_checksum,
162255682Smarkm    NULL
162355682Smarkm};
162455682Smarkmstruct checksum_type checksum_hmac_sha1_des3 = {
162555682Smarkm    CKSUMTYPE_HMAC_SHA1_DES3,
162655682Smarkm    "hmac-sha1-des3",
162755682Smarkm    64,
162855682Smarkm    20,
162955682Smarkm    F_KEYED | F_CPROOF | F_DERIVED,
1630120948Snectar    SP_HMAC_SHA1_checksum,
163155682Smarkm    NULL
163255682Smarkm};
163355682Smarkm
1634120948Snectar#ifdef ENABLE_AES
1635120948Snectarstruct checksum_type checksum_hmac_sha1_aes128 = {
1636120948Snectar    CKSUMTYPE_HMAC_SHA1_96_AES_128,
1637120948Snectar    "hmac-sha1-96-aes128",
1638120948Snectar    64,
1639120948Snectar    12,
1640120948Snectar    F_KEYED | F_CPROOF | F_DERIVED,
1641120948Snectar    SP_HMAC_SHA1_checksum,
1642120948Snectar    NULL
1643120948Snectar};
1644120948Snectar
1645120948Snectarstruct checksum_type checksum_hmac_sha1_aes256 = {
1646120948Snectar    CKSUMTYPE_HMAC_SHA1_96_AES_256,
1647120948Snectar    "hmac-sha1-96-aes256",
1648120948Snectar    64,
1649120948Snectar    12,
1650120948Snectar    F_KEYED | F_CPROOF | F_DERIVED,
1651120948Snectar    SP_HMAC_SHA1_checksum,
1652120948Snectar    NULL
1653120948Snectar};
1654120948Snectar#endif /* ENABLE_AES */
1655120948Snectar
165672448Sassarstruct checksum_type checksum_hmac_md5 = {
165772448Sassar    CKSUMTYPE_HMAC_MD5,
165872448Sassar    "hmac-md5",
165972448Sassar    64,
166072448Sassar    16,
166172448Sassar    F_KEYED | F_CPROOF,
166272448Sassar    HMAC_MD5_checksum,
166372448Sassar    NULL
166472448Sassar};
166572448Sassar
166672448Sassarstruct checksum_type checksum_hmac_md5_enc = {
166772448Sassar    CKSUMTYPE_HMAC_MD5_ENC,
166872448Sassar    "hmac-md5-enc",
166972448Sassar    64,
167072448Sassar    16,
167172448Sassar    F_KEYED | F_CPROOF | F_PSEUDO,
167272448Sassar    HMAC_MD5_checksum_enc,
167372448Sassar    NULL
167472448Sassar};
167572448Sassar
167655682Smarkmstruct checksum_type *checksum_types[] = {
167755682Smarkm    &checksum_none,
167855682Smarkm    &checksum_crc32,
167955682Smarkm    &checksum_rsa_md4,
168055682Smarkm    &checksum_rsa_md4_des,
168155682Smarkm#if 0
168255682Smarkm    &checksum_des_mac,
168355682Smarkm    &checksum_des_mac_k,
168455682Smarkm    &checksum_rsa_md4_des_k,
168555682Smarkm#endif
168655682Smarkm    &checksum_rsa_md5,
168755682Smarkm    &checksum_rsa_md5_des,
168855682Smarkm    &checksum_rsa_md5_des3,
168955682Smarkm    &checksum_sha1,
169072448Sassar    &checksum_hmac_sha1_des3,
1691120948Snectar#ifdef ENABLE_AES
1692120948Snectar    &checksum_hmac_sha1_aes128,
1693120948Snectar    &checksum_hmac_sha1_aes256,
1694120948Snectar#endif
169572448Sassar    &checksum_hmac_md5,
169672448Sassar    &checksum_hmac_md5_enc
169755682Smarkm};
169855682Smarkm
169955682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
170055682Smarkm
170155682Smarkmstatic struct checksum_type *
170255682Smarkm_find_checksum(krb5_cksumtype type)
170355682Smarkm{
170455682Smarkm    int i;
170555682Smarkm    for(i = 0; i < num_checksums; i++)
170655682Smarkm	if(checksum_types[i]->type == type)
170755682Smarkm	    return checksum_types[i];
170855682Smarkm    return NULL;
170955682Smarkm}
171055682Smarkm
171155682Smarkmstatic krb5_error_code
171255682Smarkmget_checksum_key(krb5_context context,
171355682Smarkm		 krb5_crypto crypto,
171455682Smarkm		 unsigned usage,  /* not krb5_key_usage */
171555682Smarkm		 struct checksum_type *ct,
171655682Smarkm		 struct key_data **key)
171755682Smarkm{
171855682Smarkm    krb5_error_code ret = 0;
171955682Smarkm
172055682Smarkm    if(ct->flags & F_DERIVED)
172155682Smarkm	ret = _get_derived_key(context, crypto, usage, key);
172255682Smarkm    else if(ct->flags & F_VARIANT) {
172355682Smarkm	int i;
172455682Smarkm
172555682Smarkm	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
172678536Sassar	if(*key == NULL) {
172778536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
172855682Smarkm	    return ENOMEM;
172978536Sassar	}
173055682Smarkm	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
173155682Smarkm	if(ret)
173255682Smarkm	    return ret;
173355682Smarkm	for(i = 0; i < (*key)->key->keyvalue.length; i++)
173455682Smarkm	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
173555682Smarkm    } else {
173655682Smarkm	*key = &crypto->key;
173755682Smarkm    }
173855682Smarkm    if(ret == 0)
173955682Smarkm	ret = _key_schedule(context, *key);
174055682Smarkm    return ret;
174155682Smarkm}
174255682Smarkm
174355682Smarkmstatic krb5_error_code
174455682Smarkmdo_checksum (krb5_context context,
174555682Smarkm	     struct checksum_type *ct,
174655682Smarkm	     krb5_crypto crypto,
174755682Smarkm	     unsigned usage,
174855682Smarkm	     void *data,
174955682Smarkm	     size_t len,
175055682Smarkm	     Checksum *result)
175155682Smarkm{
175255682Smarkm    krb5_error_code ret;
175355682Smarkm    struct key_data *dkey;
175455682Smarkm    int keyed_checksum;
175555682Smarkm
175655682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
175778536Sassar    if(keyed_checksum && crypto == NULL) {
175878536Sassar	krb5_clear_error_string (context);
175955682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
176078536Sassar    }
176172448Sassar    if(keyed_checksum) {
176255682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
176372448Sassar	if (ret)
176472448Sassar	    return ret;
176572448Sassar    } else
176655682Smarkm	dkey = NULL;
176755682Smarkm    result->cksumtype = ct->type;
176855682Smarkm    krb5_data_alloc(&result->checksum, ct->checksumsize);
176972448Sassar    (*ct->checksum)(context, dkey, data, len, usage, result);
177055682Smarkm    return 0;
177155682Smarkm}
177255682Smarkm
177355682Smarkmstatic krb5_error_code
177455682Smarkmcreate_checksum(krb5_context context,
177555682Smarkm		krb5_crypto crypto,
177690929Snectar		unsigned usage, /* not krb5_key_usage */
177778536Sassar		krb5_cksumtype type, /* 0 -> pick from crypto */
177855682Smarkm		void *data,
177955682Smarkm		size_t len,
178055682Smarkm		Checksum *result)
178155682Smarkm{
178278536Sassar    struct checksum_type *ct = NULL;
178355682Smarkm
178478536Sassar    if (type) {
178578536Sassar	ct = _find_checksum(type);
178678536Sassar    } else if (crypto) {
178755682Smarkm	ct = crypto->et->keyed_checksum;
178878536Sassar	if (ct == NULL)
178978536Sassar	    ct = crypto->et->checksum;
179078536Sassar    }
179178536Sassar
179278536Sassar    if(ct == NULL) {
179378536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
179478536Sassar			       type);
179555682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
179678536Sassar    }
179755682Smarkm    return do_checksum (context, ct, crypto, usage, data, len, result);
179855682Smarkm}
179955682Smarkm
180055682Smarkmkrb5_error_code
180155682Smarkmkrb5_create_checksum(krb5_context context,
180255682Smarkm		     krb5_crypto crypto,
180378536Sassar		     krb5_key_usage usage,
180478536Sassar		     int type,
180555682Smarkm		     void *data,
180655682Smarkm		     size_t len,
180755682Smarkm		     Checksum *result)
180855682Smarkm{
180955682Smarkm    return create_checksum(context, crypto,
181078536Sassar			   CHECKSUM_USAGE(usage),
181178536Sassar			   type, data, len, result);
181255682Smarkm}
181355682Smarkm
181455682Smarkmstatic krb5_error_code
181555682Smarkmverify_checksum(krb5_context context,
181655682Smarkm		krb5_crypto crypto,
181755682Smarkm		unsigned usage, /* not krb5_key_usage */
181855682Smarkm		void *data,
181955682Smarkm		size_t len,
182055682Smarkm		Checksum *cksum)
182155682Smarkm{
182255682Smarkm    krb5_error_code ret;
182355682Smarkm    struct key_data *dkey;
182455682Smarkm    int keyed_checksum;
182555682Smarkm    Checksum c;
182655682Smarkm    struct checksum_type *ct;
182755682Smarkm
182855682Smarkm    ct = _find_checksum(cksum->cksumtype);
182978536Sassar    if(ct == NULL) {
183078536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
183178536Sassar			       cksum->cksumtype);
183255682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
183378536Sassar    }
183478536Sassar    if(ct->checksumsize != cksum->checksum.length) {
183578536Sassar	krb5_clear_error_string (context);
183655682Smarkm	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
183778536Sassar    }
183855682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
183978536Sassar    if(keyed_checksum && crypto == NULL) {
184078536Sassar	krb5_clear_error_string (context);
184155682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
184278536Sassar    }
184355682Smarkm    if(keyed_checksum)
184455682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
184555682Smarkm    else
184655682Smarkm	dkey = NULL;
184755682Smarkm    if(ct->verify)
184872448Sassar	return (*ct->verify)(context, dkey, data, len, usage, cksum);
184955682Smarkm
185055682Smarkm    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
185155682Smarkm    if (ret)
185255682Smarkm	return ret;
185355682Smarkm
185472448Sassar    (*ct->checksum)(context, dkey, data, len, usage, &c);
185555682Smarkm
185655682Smarkm    if(c.checksum.length != cksum->checksum.length ||
185778536Sassar       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
185878536Sassar	krb5_clear_error_string (context);
185955682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
186078536Sassar    } else {
186155682Smarkm	ret = 0;
186278536Sassar    }
186355682Smarkm    krb5_data_free (&c.checksum);
186455682Smarkm    return ret;
186555682Smarkm}
186655682Smarkm
186755682Smarkmkrb5_error_code
186855682Smarkmkrb5_verify_checksum(krb5_context context,
186955682Smarkm		     krb5_crypto crypto,
187055682Smarkm		     krb5_key_usage usage,
187155682Smarkm		     void *data,
187255682Smarkm		     size_t len,
187355682Smarkm		     Checksum *cksum)
187455682Smarkm{
187555682Smarkm    return verify_checksum(context, crypto,
187655682Smarkm			   CHECKSUM_USAGE(usage), data, len, cksum);
187755682Smarkm}
187855682Smarkm
187955682Smarkmkrb5_error_code
188055682Smarkmkrb5_checksumsize(krb5_context context,
188155682Smarkm		  krb5_cksumtype type,
188255682Smarkm		  size_t *size)
188355682Smarkm{
188455682Smarkm    struct checksum_type *ct = _find_checksum(type);
188578536Sassar    if(ct == NULL) {
188678536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
188778536Sassar			       type);
188855682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
188978536Sassar    }
189055682Smarkm    *size = ct->checksumsize;
189155682Smarkm    return 0;
189255682Smarkm}
189355682Smarkm
189455682Smarkmkrb5_boolean
189555682Smarkmkrb5_checksum_is_keyed(krb5_context context,
189655682Smarkm		       krb5_cksumtype type)
189755682Smarkm{
189855682Smarkm    struct checksum_type *ct = _find_checksum(type);
189978536Sassar    if(ct == NULL) {
190078536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
190178536Sassar			       type);
190255682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
190378536Sassar    }
190455682Smarkm    return ct->flags & F_KEYED;
190555682Smarkm}
190655682Smarkm
190755682Smarkmkrb5_boolean
190855682Smarkmkrb5_checksum_is_collision_proof(krb5_context context,
190955682Smarkm				 krb5_cksumtype type)
191055682Smarkm{
191155682Smarkm    struct checksum_type *ct = _find_checksum(type);
191278536Sassar    if(ct == NULL) {
191378536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
191478536Sassar			       type);
191555682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
191678536Sassar    }
191755682Smarkm    return ct->flags & F_CPROOF;
191855682Smarkm}
191955682Smarkm
192055682Smarkm/************************************************************
192155682Smarkm *                                                          *
192255682Smarkm ************************************************************/
192355682Smarkm
192472448Sassarstatic krb5_error_code
192578536SassarNULL_encrypt(krb5_context context,
192678536Sassar	     struct key_data *key,
192755682Smarkm	     void *data,
192855682Smarkm	     size_t len,
192972448Sassar	     krb5_boolean encrypt,
193072448Sassar	     int usage,
193172448Sassar	     void *ivec)
193255682Smarkm{
193372448Sassar    return 0;
193455682Smarkm}
193555682Smarkm
193672448Sassarstatic krb5_error_code
193778536SassarDES_CBC_encrypt_null_ivec(krb5_context context,
193878536Sassar			  struct key_data *key,
193955682Smarkm			  void *data,
194055682Smarkm			  size_t len,
194172448Sassar			  krb5_boolean encrypt,
194272448Sassar			  int usage,
194372448Sassar			  void *ignore_ivec)
194455682Smarkm{
194555682Smarkm    des_cblock ivec;
194655682Smarkm    des_key_schedule *s = key->schedule->data;
194755682Smarkm    memset(&ivec, 0, sizeof(ivec));
194855682Smarkm    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
194972448Sassar    return 0;
195055682Smarkm}
195155682Smarkm
195272448Sassarstatic krb5_error_code
195378536SassarDES_CBC_encrypt_key_ivec(krb5_context context,
195478536Sassar			 struct key_data *key,
195555682Smarkm			 void *data,
195655682Smarkm			 size_t len,
195772448Sassar			 krb5_boolean encrypt,
195872448Sassar			 int usage,
195972448Sassar			 void *ignore_ivec)
196055682Smarkm{
196155682Smarkm    des_cblock ivec;
196255682Smarkm    des_key_schedule *s = key->schedule->data;
196355682Smarkm    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
196455682Smarkm    des_cbc_encrypt(data, data, len, *s, &ivec, encrypt);
196572448Sassar    return 0;
196655682Smarkm}
196755682Smarkm
196872448Sassarstatic krb5_error_code
196978536SassarDES3_CBC_encrypt(krb5_context context,
197078536Sassar		 struct key_data *key,
197155682Smarkm		 void *data,
197255682Smarkm		 size_t len,
197372448Sassar		 krb5_boolean encrypt,
197472448Sassar		 int usage,
1975103426Snectar		 void *ivec)
197655682Smarkm{
1977103426Snectar    des_cblock local_ivec;
197855682Smarkm    des_key_schedule *s = key->schedule->data;
1979103426Snectar    if(ivec == NULL) {
1980103426Snectar	ivec = &local_ivec;
1981103426Snectar	memset(local_ivec, 0, sizeof(local_ivec));
1982103426Snectar    }
198372448Sassar    des_ede3_cbc_encrypt(data, data, len, s[0], s[1], s[2], ivec, encrypt);
198472448Sassar    return 0;
198572448Sassar}
198672448Sassar
198772448Sassarstatic krb5_error_code
198878536SassarDES_CFB64_encrypt_null_ivec(krb5_context context,
198978536Sassar			    struct key_data *key,
199072448Sassar			    void *data,
199172448Sassar			    size_t len,
199272448Sassar			    krb5_boolean encrypt,
199372448Sassar			    int usage,
199472448Sassar			    void *ignore_ivec)
199572448Sassar{
199672448Sassar    des_cblock ivec;
199772448Sassar    int num = 0;
199872448Sassar    des_key_schedule *s = key->schedule->data;
199972448Sassar    memset(&ivec, 0, sizeof(ivec));
200072448Sassar
200172448Sassar    des_cfb64_encrypt(data, data, len, *s, &ivec, &num, encrypt);
200272448Sassar    return 0;
200372448Sassar}
200472448Sassar
200572448Sassarstatic krb5_error_code
200678536SassarDES_PCBC_encrypt_key_ivec(krb5_context context,
200778536Sassar			  struct key_data *key,
200872448Sassar			  void *data,
200972448Sassar			  size_t len,
201072448Sassar			  krb5_boolean encrypt,
201172448Sassar			  int usage,
201272448Sassar			  void *ignore_ivec)
201372448Sassar{
201472448Sassar    des_cblock ivec;
201572448Sassar    des_key_schedule *s = key->schedule->data;
201672448Sassar    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
201772448Sassar
201872448Sassar    des_pcbc_encrypt(data, data, len, *s, &ivec, encrypt);
201972448Sassar    return 0;
202072448Sassar}
202172448Sassar
2022120948Snectar#ifdef ENABLE_AES
2023120948Snectar
202472448Sassar/*
2025120948Snectar * AES draft-raeburn-krb-rijndael-krb-02
2026120948Snectar */
2027120948Snectar
2028120948Snectarvoid
2029120948Snectar_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out,
2030120948Snectar		      size_t len, const void *aes_key,
2031120948Snectar		      unsigned char *ivec, const int enc)
2032120948Snectar{
2033120948Snectar    unsigned char tmp[AES_BLOCK_SIZE];
2034120948Snectar    const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */
2035120948Snectar    int i;
2036120948Snectar
2037120948Snectar    /*
2038120948Snectar     * In the framework of kerberos, the length can never be shorter
2039120948Snectar     * then at least one blocksize.
2040120948Snectar     */
2041120948Snectar
2042120948Snectar    if (enc == AES_ENCRYPT) {
2043120948Snectar
2044120948Snectar	while(len > AES_BLOCK_SIZE) {
2045120948Snectar	    for (i = 0; i < AES_BLOCK_SIZE; i++)
2046120948Snectar		tmp[i] = in[i] ^ ivec[i];
2047120948Snectar	    AES_encrypt(tmp, out, key);
2048120948Snectar	    memcpy(ivec, out, AES_BLOCK_SIZE);
2049120948Snectar	    len -= AES_BLOCK_SIZE;
2050120948Snectar	    in += AES_BLOCK_SIZE;
2051120948Snectar	    out += AES_BLOCK_SIZE;
2052120948Snectar	}
2053120948Snectar
2054120948Snectar	for (i = 0; i < len; i++)
2055120948Snectar	    tmp[i] = in[i] ^ ivec[i];
2056120948Snectar	for (; i < AES_BLOCK_SIZE; i++)
2057120948Snectar	    tmp[i] = 0 ^ ivec[i];
2058120948Snectar
2059120948Snectar	AES_encrypt(tmp, out - AES_BLOCK_SIZE, key);
2060120948Snectar
2061120948Snectar	memcpy(out, ivec, len);
2062120948Snectar
2063120948Snectar    } else {
2064120948Snectar	char tmp2[AES_BLOCK_SIZE];
2065120948Snectar	char tmp3[AES_BLOCK_SIZE];
2066120948Snectar
2067120948Snectar	while(len > AES_BLOCK_SIZE * 2) {
2068120948Snectar	    memcpy(tmp, in, AES_BLOCK_SIZE);
2069120948Snectar	    AES_decrypt(in, out, key);
2070120948Snectar	    for (i = 0; i < AES_BLOCK_SIZE; i++)
2071120948Snectar		out[i] ^= ivec[i];
2072120948Snectar	    memcpy(ivec, tmp, AES_BLOCK_SIZE);
2073120948Snectar	    len -= AES_BLOCK_SIZE;
2074120948Snectar	    in += AES_BLOCK_SIZE;
2075120948Snectar	    out += AES_BLOCK_SIZE;
2076120948Snectar	}
2077120948Snectar
2078120948Snectar	len -= AES_BLOCK_SIZE;
2079120948Snectar
2080120948Snectar	AES_decrypt(in, tmp2, key);
2081120948Snectar
2082120948Snectar	memcpy(tmp3, in + AES_BLOCK_SIZE, len);
2083120948Snectar	memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */
2084120948Snectar
2085120948Snectar	for (i = 0; i < len; i++)
2086120948Snectar	    out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i];
2087120948Snectar
2088120948Snectar	AES_decrypt(tmp3, out, key);
2089120948Snectar	for (i = 0; i < AES_BLOCK_SIZE; i++)
2090120948Snectar	    out[i] ^= ivec[i];
2091120948Snectar    }
2092120948Snectar}
2093120948Snectar
2094120948Snectarstatic krb5_error_code
2095120948SnectarAES_CTS_encrypt(krb5_context context,
2096120948Snectar		struct key_data *key,
2097120948Snectar		void *data,
2098120948Snectar		size_t len,
2099120948Snectar		krb5_boolean encrypt,
2100120948Snectar		int usage,
2101120948Snectar		void *ivec)
2102120948Snectar{
2103120948Snectar    AES_KEY *k = key->schedule->data;
2104120948Snectar    char local_ivec[AES_BLOCK_SIZE];
2105120948Snectar
2106120948Snectar    if (encrypt)
2107120948Snectar	k = &k[0];
2108120948Snectar    else
2109120948Snectar	k = &k[1];
2110120948Snectar
2111120948Snectar    if (len < AES_BLOCK_SIZE)
2112120948Snectar	abort();
2113120948Snectar    if (len == AES_BLOCK_SIZE) {
2114120948Snectar	if (encrypt)
2115120948Snectar	    AES_encrypt(data, data, k);
2116120948Snectar	else
2117120948Snectar	    AES_decrypt(data, data, k);
2118120948Snectar    } else {
2119120948Snectar	if(ivec == NULL) {
2120120948Snectar	    memset(local_ivec, 0, sizeof(local_ivec));
2121120948Snectar	    ivec = local_ivec;
2122120948Snectar	}
2123120948Snectar	_krb5_aes_cts_encrypt(data, data, len, k, ivec, encrypt);
2124120948Snectar    }
2125120948Snectar
2126120948Snectar    return 0;
2127120948Snectar}
2128120948Snectar#endif /* ENABLE_AES */
2129120948Snectar
2130120948Snectar/*
213172448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
213272448Sassar *
213372448Sassar * warning: not for small children
213472448Sassar */
213572448Sassar
213672448Sassarstatic krb5_error_code
213778536SassarARCFOUR_subencrypt(krb5_context context,
213878536Sassar		   struct key_data *key,
213972448Sassar		   void *data,
214072448Sassar		   size_t len,
214172448Sassar		   int usage,
214272448Sassar		   void *ivec)
214372448Sassar{
214472448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
214572448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
214672448Sassar    struct key_data ke;
214772448Sassar    krb5_keyblock kb;
214872448Sassar    unsigned char t[4];
214972448Sassar    RC4_KEY rc4_key;
215090929Snectar    unsigned char *cdata = data;
215172448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
215272448Sassar
215372448Sassar    t[0] = (usage >>  0) & 0xFF;
215472448Sassar    t[1] = (usage >>  8) & 0xFF;
215572448Sassar    t[2] = (usage >> 16) & 0xFF;
215672448Sassar    t[3] = (usage >> 24) & 0xFF;
215772448Sassar
215872448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
215972448Sassar    k1_c.checksum.data   = k1_c_data;
216072448Sassar
216172448Sassar    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
216272448Sassar
216372448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
216472448Sassar
216572448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
216672448Sassar    k2_c.checksum.data   = k2_c_data;
216772448Sassar
216872448Sassar    ke.key = &kb;
216972448Sassar    kb.keyvalue = k2_c.checksum;
217072448Sassar
217172448Sassar    cksum.checksum.length = 16;
217272448Sassar    cksum.checksum.data   = data;
217372448Sassar
217472448Sassar    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
217572448Sassar
217672448Sassar    ke.key = &kb;
217772448Sassar    kb.keyvalue = k1_c.checksum;
217872448Sassar
217972448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
218072448Sassar    k3_c.checksum.data   = k3_c_data;
218172448Sassar
218272448Sassar    hmac(NULL, c, data, 16, 0, &ke, &k3_c);
218372448Sassar
218472448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
218572448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
218672448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
218772448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
218872448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
218972448Sassar    return 0;
219072448Sassar}
219172448Sassar
219272448Sassarstatic krb5_error_code
219378536SassarARCFOUR_subdecrypt(krb5_context context,
219478536Sassar		   struct key_data *key,
219572448Sassar		   void *data,
219672448Sassar		   size_t len,
219772448Sassar		   int usage,
219872448Sassar		   void *ivec)
219972448Sassar{
220072448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
220172448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
220272448Sassar    struct key_data ke;
220372448Sassar    krb5_keyblock kb;
220472448Sassar    unsigned char t[4];
220572448Sassar    RC4_KEY rc4_key;
220690929Snectar    unsigned char *cdata = data;
220772448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
220872448Sassar    unsigned char cksum_data[16];
220972448Sassar
221072448Sassar    t[0] = (usage >>  0) & 0xFF;
221172448Sassar    t[1] = (usage >>  8) & 0xFF;
221272448Sassar    t[2] = (usage >> 16) & 0xFF;
221372448Sassar    t[3] = (usage >> 24) & 0xFF;
221472448Sassar
221572448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
221672448Sassar    k1_c.checksum.data   = k1_c_data;
221772448Sassar
221872448Sassar    hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
221972448Sassar
222072448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
222172448Sassar
222272448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
222372448Sassar    k2_c.checksum.data   = k2_c_data;
222472448Sassar
222572448Sassar    ke.key = &kb;
222672448Sassar    kb.keyvalue = k1_c.checksum;
222772448Sassar
222872448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
222972448Sassar    k3_c.checksum.data   = k3_c_data;
223072448Sassar
223172448Sassar    hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
223272448Sassar
223372448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
223472448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
223572448Sassar
223672448Sassar    ke.key = &kb;
223772448Sassar    kb.keyvalue = k2_c.checksum;
223872448Sassar
223972448Sassar    cksum.checksum.length = 16;
224072448Sassar    cksum.checksum.data   = cksum_data;
224172448Sassar
224272448Sassar    hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
224372448Sassar
224472448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
224572448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
224672448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
224772448Sassar
224878536Sassar    if (memcmp (cksum.checksum.data, data, 16) != 0) {
224978536Sassar	krb5_clear_error_string (context);
225072448Sassar	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
225178536Sassar    } else {
225272448Sassar	return 0;
225378536Sassar    }
225472448Sassar}
225572448Sassar
225672448Sassar/*
225772448Sassar * convert the usage numbers used in
225872448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
225972448Sassar * draft-brezak-win2k-krb-rc4-hmac-03.txt
226072448Sassar */
226172448Sassar
2262102647Snectarstatic krb5_error_code
2263102647Snectarusage2arcfour (krb5_context context, int *usage)
226472448Sassar{
2265102647Snectar    switch (*usage) {
226672448Sassar    case KRB5_KU_PA_ENC_TIMESTAMP :
2267102647Snectar	*usage = 1;
2268102647Snectar	return 0;
226972448Sassar    case KRB5_KU_TICKET :
2270120948Snectar	*usage = 2;
2271120948Snectar	return 0;
227272448Sassar    case KRB5_KU_AS_REP_ENC_PART :
2273102647Snectar	*usage = 8;
2274102647Snectar	return 0;
227572448Sassar    case KRB5_KU_TGS_REQ_AUTH_DAT_SESSION :
227672448Sassar    case KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY :
227772448Sassar    case KRB5_KU_TGS_REQ_AUTH_CKSUM :
227872448Sassar    case KRB5_KU_TGS_REQ_AUTH :
2279102647Snectar	*usage = 7;
2280102647Snectar	return 0;
228172448Sassar    case KRB5_KU_TGS_REP_ENC_PART_SESSION :
228272448Sassar    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY :
2283102647Snectar	*usage = 8;
2284102647Snectar	return 0;
228572448Sassar    case KRB5_KU_AP_REQ_AUTH_CKSUM :
228672448Sassar    case KRB5_KU_AP_REQ_AUTH :
228772448Sassar    case KRB5_KU_AP_REQ_ENC_PART :
2288102647Snectar	*usage = 11;
2289102647Snectar	return 0;
229072448Sassar    case KRB5_KU_KRB_PRIV :
2291102647Snectar	*usage = 0;
229272448Sassar	return 0;
229372448Sassar    case KRB5_KU_KRB_CRED :
229472448Sassar    case KRB5_KU_KRB_SAFE_CKSUM :
229572448Sassar    case KRB5_KU_OTHER_ENCRYPTED :
229672448Sassar    case KRB5_KU_OTHER_CKSUM :
229772448Sassar    case KRB5_KU_KRB_ERROR :
229872448Sassar    case KRB5_KU_AD_KDC_ISSUED :
229972448Sassar    case KRB5_KU_MANDATORY_TICKET_EXTENSION :
230072448Sassar    case KRB5_KU_AUTH_DATA_TICKET_EXTENSION :
230172448Sassar    case KRB5_KU_USAGE_SEAL :
230272448Sassar    case KRB5_KU_USAGE_SIGN :
230372448Sassar    case KRB5_KU_USAGE_SEQ :
230472448Sassar    default :
2305102647Snectar	krb5_set_error_string(context, "unknown arcfour usage type %d", *usage);
2306102647Snectar	return KRB5_PROG_ETYPE_NOSUPP;
230772448Sassar    }
230872448Sassar}
230972448Sassar
231072448Sassarstatic krb5_error_code
231178536SassarARCFOUR_encrypt(krb5_context context,
231278536Sassar		struct key_data *key,
231355682Smarkm		void *data,
231455682Smarkm		size_t len,
231572448Sassar		krb5_boolean encrypt,
231672448Sassar		int usage,
231772448Sassar		void *ivec)
231855682Smarkm{
2319102647Snectar    krb5_error_code ret;
2320102647Snectar    if((ret = usage2arcfour (context, &usage)) != 0)
2321102647Snectar	return ret;
232255682Smarkm
232372448Sassar    if (encrypt)
232478536Sassar	return ARCFOUR_subencrypt (context, key, data, len, usage, ivec);
232572448Sassar    else
232678536Sassar	return ARCFOUR_subdecrypt (context, key, data, len, usage, ivec);
232755682Smarkm}
232855682Smarkm
232972448Sassar
233055682Smarkm/*
233155682Smarkm * these should currently be in reverse preference order.
233272448Sassar * (only relevant for !F_PSEUDO) */
233355682Smarkm
233478536Sassarstatic struct encryption_type enctype_null = {
233578536Sassar    ETYPE_NULL,
233678536Sassar    "null",
233778536Sassar    1,
2338120948Snectar    1,
233978536Sassar    0,
234078536Sassar    &keytype_null,
234178536Sassar    &checksum_none,
234278536Sassar    NULL,
234378536Sassar    0,
234478536Sassar    NULL_encrypt,
234555682Smarkm};
234678536Sassarstatic struct encryption_type enctype_des_cbc_crc = {
234778536Sassar    ETYPE_DES_CBC_CRC,
234878536Sassar    "des-cbc-crc",
234978536Sassar    8,
235078536Sassar    8,
2351120948Snectar    8,
235278536Sassar    &keytype_des,
235378536Sassar    &checksum_crc32,
235478536Sassar    NULL,
235578536Sassar    0,
235678536Sassar    DES_CBC_encrypt_key_ivec,
235778536Sassar};
235878536Sassarstatic struct encryption_type enctype_des_cbc_md4 = {
235978536Sassar    ETYPE_DES_CBC_MD4,
236078536Sassar    "des-cbc-md4",
236178536Sassar    8,
236278536Sassar    8,
2363120948Snectar    8,
236478536Sassar    &keytype_des,
236578536Sassar    &checksum_rsa_md4,
236678536Sassar    &checksum_rsa_md4_des,
236778536Sassar    0,
236878536Sassar    DES_CBC_encrypt_null_ivec,
236978536Sassar};
237078536Sassarstatic struct encryption_type enctype_des_cbc_md5 = {
237178536Sassar    ETYPE_DES_CBC_MD5,
237278536Sassar    "des-cbc-md5",
237378536Sassar    8,
237478536Sassar    8,
2375120948Snectar    8,
237678536Sassar    &keytype_des,
237778536Sassar    &checksum_rsa_md5,
237878536Sassar    &checksum_rsa_md5_des,
237978536Sassar    0,
238078536Sassar    DES_CBC_encrypt_null_ivec,
238178536Sassar};
238278536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = {
238378536Sassar    ETYPE_ARCFOUR_HMAC_MD5,
238478536Sassar    "arcfour-hmac-md5",
238578536Sassar    1,
2386120948Snectar    1,
238778536Sassar    8,
238878536Sassar    &keytype_arcfour,
238990929Snectar    &checksum_hmac_md5,
2390120948Snectar    /* &checksum_hmac_md5_enc */ NULL,
239178536Sassar    F_SPECIAL,
239278536Sassar    ARCFOUR_encrypt
239378536Sassar};
239478536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = {
239578536Sassar    ETYPE_DES3_CBC_MD5,
239678536Sassar    "des3-cbc-md5",
239778536Sassar    8,
239878536Sassar    8,
2399120948Snectar    8,
240078536Sassar    &keytype_des3,
240178536Sassar    &checksum_rsa_md5,
240278536Sassar    &checksum_rsa_md5_des3,
240378536Sassar    0,
240478536Sassar    DES3_CBC_encrypt,
240578536Sassar};
240678536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = {
240778536Sassar    ETYPE_DES3_CBC_SHA1,
240878536Sassar    "des3-cbc-sha1",
240978536Sassar    8,
241078536Sassar    8,
2411120948Snectar    8,
241278536Sassar    &keytype_des3_derived,
241378536Sassar    &checksum_sha1,
241478536Sassar    &checksum_hmac_sha1_des3,
241578536Sassar    F_DERIVED,
241678536Sassar    DES3_CBC_encrypt,
241778536Sassar};
241878536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = {
241978536Sassar    ETYPE_OLD_DES3_CBC_SHA1,
242078536Sassar    "old-des3-cbc-sha1",
242178536Sassar    8,
242278536Sassar    8,
2423120948Snectar    8,
242478536Sassar    &keytype_des3,
242578536Sassar    &checksum_sha1,
242678536Sassar    &checksum_hmac_sha1_des3,
242778536Sassar    0,
242878536Sassar    DES3_CBC_encrypt,
242978536Sassar};
2430120948Snectar#ifdef ENABLE_AES
2431120948Snectarstatic struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2432120948Snectar    ETYPE_AES128_CTS_HMAC_SHA1_96,
2433120948Snectar    "aes128-cts-hmac-sha1-96",
2434120948Snectar    16,
2435120948Snectar    1,
2436120948Snectar    16,
2437120948Snectar    &keytype_aes128,
2438120948Snectar    &checksum_sha1,
2439120948Snectar    &checksum_hmac_sha1_aes128,
2440120948Snectar    0,
2441120948Snectar    AES_CTS_encrypt,
2442120948Snectar};
2443120948Snectarstatic struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2444120948Snectar    ETYPE_AES256_CTS_HMAC_SHA1_96,
2445120948Snectar    "aes256-cts-hmac-sha1-96",
2446120948Snectar    16,
2447120948Snectar    1,
2448120948Snectar    16,
2449120948Snectar    &keytype_aes256,
2450120948Snectar    &checksum_sha1,
2451120948Snectar    &checksum_hmac_sha1_aes256,
2452120948Snectar    0,
2453120948Snectar    AES_CTS_encrypt,
2454120948Snectar};
2455120948Snectar#endif /* ENABLE_AES */
245678536Sassarstatic struct encryption_type enctype_des_cbc_none = {
245778536Sassar    ETYPE_DES_CBC_NONE,
245878536Sassar    "des-cbc-none",
245978536Sassar    8,
2460120948Snectar    8,
246178536Sassar    0,
246278536Sassar    &keytype_des,
246378536Sassar    &checksum_none,
246478536Sassar    NULL,
246578536Sassar    F_PSEUDO,
246678536Sassar    DES_CBC_encrypt_null_ivec,
246778536Sassar};
246878536Sassarstatic struct encryption_type enctype_des_cfb64_none = {
246978536Sassar    ETYPE_DES_CFB64_NONE,
247078536Sassar    "des-cfb64-none",
247178536Sassar    1,
2472120948Snectar    1,
247378536Sassar    0,
247478536Sassar    &keytype_des,
247578536Sassar    &checksum_none,
247678536Sassar    NULL,
247778536Sassar    F_PSEUDO,
247878536Sassar    DES_CFB64_encrypt_null_ivec,
247978536Sassar};
248078536Sassarstatic struct encryption_type enctype_des_pcbc_none = {
248178536Sassar    ETYPE_DES_PCBC_NONE,
248278536Sassar    "des-pcbc-none",
248378536Sassar    8,
2484120948Snectar    8,
248578536Sassar    0,
248678536Sassar    &keytype_des,
248778536Sassar    &checksum_none,
248878536Sassar    NULL,
248978536Sassar    F_PSEUDO,
249078536Sassar    DES_PCBC_encrypt_key_ivec,
249178536Sassar};
249278536Sassarstatic struct encryption_type enctype_des3_cbc_none = {
249378536Sassar    ETYPE_DES3_CBC_NONE,
249478536Sassar    "des3-cbc-none",
249578536Sassar    8,
2496120948Snectar    8,
249778536Sassar    0,
249878536Sassar    &keytype_des3_derived,
249978536Sassar    &checksum_none,
250078536Sassar    NULL,
250178536Sassar    F_PSEUDO,
250278536Sassar    DES3_CBC_encrypt,
250378536Sassar};
250455682Smarkm
250578536Sassarstatic struct encryption_type *etypes[] = {
250678536Sassar    &enctype_null,
250778536Sassar    &enctype_des_cbc_crc,
250878536Sassar    &enctype_des_cbc_md4,
250978536Sassar    &enctype_des_cbc_md5,
251078536Sassar    &enctype_arcfour_hmac_md5,
251178536Sassar    &enctype_des3_cbc_md5,
251278536Sassar    &enctype_des3_cbc_sha1,
251378536Sassar    &enctype_old_des3_cbc_sha1,
2514120948Snectar#ifdef ENABLE_AES
2515120948Snectar    &enctype_aes128_cts_hmac_sha1,
2516120948Snectar    &enctype_aes256_cts_hmac_sha1,
2517120948Snectar#endif
251878536Sassar    &enctype_des_cbc_none,
251978536Sassar    &enctype_des_cfb64_none,
252078536Sassar    &enctype_des_pcbc_none,
2521103426Snectar    &enctype_des3_cbc_none
252278536Sassar};
252378536Sassar
252455682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
252555682Smarkm
252655682Smarkm
252755682Smarkmstatic struct encryption_type *
252855682Smarkm_find_enctype(krb5_enctype type)
252955682Smarkm{
253055682Smarkm    int i;
253155682Smarkm    for(i = 0; i < num_etypes; i++)
253278536Sassar	if(etypes[i]->type == type)
253378536Sassar	    return etypes[i];
253455682Smarkm    return NULL;
253555682Smarkm}
253655682Smarkm
253755682Smarkm
253855682Smarkmkrb5_error_code
253955682Smarkmkrb5_enctype_to_string(krb5_context context,
254055682Smarkm		       krb5_enctype etype,
254155682Smarkm		       char **string)
254255682Smarkm{
254355682Smarkm    struct encryption_type *e;
254455682Smarkm    e = _find_enctype(etype);
254578536Sassar    if(e == NULL) {
254678536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
254778536Sassar			       etype);
254855682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
254978536Sassar    }
255055682Smarkm    *string = strdup(e->name);
255178536Sassar    if(*string == NULL) {
255278536Sassar	krb5_set_error_string(context, "malloc: out of memory");
255355682Smarkm	return ENOMEM;
255478536Sassar    }
255555682Smarkm    return 0;
255655682Smarkm}
255755682Smarkm
255855682Smarkmkrb5_error_code
255955682Smarkmkrb5_string_to_enctype(krb5_context context,
256055682Smarkm		       const char *string,
256155682Smarkm		       krb5_enctype *etype)
256255682Smarkm{
256355682Smarkm    int i;
256455682Smarkm    for(i = 0; i < num_etypes; i++)
256578536Sassar	if(strcasecmp(etypes[i]->name, string) == 0){
256678536Sassar	    *etype = etypes[i]->type;
256755682Smarkm	    return 0;
256855682Smarkm	}
256978536Sassar    krb5_set_error_string (context, "encryption type %s not supported",
257078536Sassar			   string);
257155682Smarkm    return KRB5_PROG_ETYPE_NOSUPP;
257255682Smarkm}
257355682Smarkm
257455682Smarkmkrb5_error_code
257555682Smarkmkrb5_enctype_to_keytype(krb5_context context,
257655682Smarkm			krb5_enctype etype,
257755682Smarkm			krb5_keytype *keytype)
257855682Smarkm{
257955682Smarkm    struct encryption_type *e = _find_enctype(etype);
258078536Sassar    if(e == NULL) {
258178536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
258278536Sassar			       etype);
258355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
258478536Sassar    }
258555682Smarkm    *keytype = e->keytype->type; /* XXX */
258655682Smarkm    return 0;
258755682Smarkm}
258855682Smarkm
258955682Smarkm#if 0
259055682Smarkmkrb5_error_code
259155682Smarkmkrb5_keytype_to_enctype(krb5_context context,
259255682Smarkm			krb5_keytype keytype,
259355682Smarkm			krb5_enctype *etype)
259455682Smarkm{
259555682Smarkm    struct key_type *kt = _find_keytype(keytype);
259655682Smarkm    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
259755682Smarkm    if(kt == NULL)
259855682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
259955682Smarkm    *etype = kt->best_etype;
260055682Smarkm    return 0;
260155682Smarkm}
260255682Smarkm#endif
260355682Smarkm
260455682Smarkmkrb5_error_code
260555682Smarkmkrb5_keytype_to_enctypes (krb5_context context,
260655682Smarkm			  krb5_keytype keytype,
260755682Smarkm			  unsigned *len,
260890929Snectar			  krb5_enctype **val)
260955682Smarkm{
261055682Smarkm    int i;
261155682Smarkm    unsigned n = 0;
261290929Snectar    krb5_enctype *ret;
261355682Smarkm
261455682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
261578536Sassar	if (etypes[i]->keytype->type == keytype
261678536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
261755682Smarkm	    ++n;
261855682Smarkm    }
261990929Snectar    ret = malloc(n * sizeof(*ret));
262078536Sassar    if (ret == NULL && n != 0) {
262178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
262255682Smarkm	return ENOMEM;
262378536Sassar    }
262455682Smarkm    n = 0;
262555682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
262678536Sassar	if (etypes[i]->keytype->type == keytype
262778536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
262878536Sassar	    ret[n++] = etypes[i]->type;
262955682Smarkm    }
263055682Smarkm    *len = n;
263155682Smarkm    *val = ret;
263255682Smarkm    return 0;
263355682Smarkm}
263455682Smarkm
263555682Smarkm/*
263655682Smarkm * First take the configured list of etypes for `keytype' if available,
263755682Smarkm * else, do `krb5_keytype_to_enctypes'.
263855682Smarkm */
263955682Smarkm
264055682Smarkmkrb5_error_code
264155682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context,
264255682Smarkm				  krb5_keytype keytype,
264355682Smarkm				  unsigned *len,
264490929Snectar				  krb5_enctype **val)
264555682Smarkm{
264655682Smarkm    int i, n;
264790929Snectar    krb5_enctype *ret;
264855682Smarkm
264955682Smarkm    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
265055682Smarkm	return krb5_keytype_to_enctypes (context, keytype, len, val);
265155682Smarkm
265255682Smarkm    for (n = 0; context->etypes_des[n]; ++n)
265355682Smarkm	;
265455682Smarkm    ret = malloc (n * sizeof(*ret));
265578536Sassar    if (ret == NULL && n != 0) {
265678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
265755682Smarkm	return ENOMEM;
265878536Sassar    }
265955682Smarkm    for (i = 0; i < n; ++i)
266055682Smarkm	ret[i] = context->etypes_des[i];
266155682Smarkm    *len = n;
266255682Smarkm    *val = ret;
266355682Smarkm    return 0;
266455682Smarkm}
266555682Smarkm
266655682Smarkmkrb5_error_code
266755682Smarkmkrb5_enctype_valid(krb5_context context,
266855682Smarkm		 krb5_enctype etype)
266955682Smarkm{
267055682Smarkm    return _find_enctype(etype) != NULL;
267155682Smarkm}
267255682Smarkm
267355682Smarkm/* if two enctypes have compatible keys */
267455682Smarkmkrb5_boolean
267555682Smarkmkrb5_enctypes_compatible_keys(krb5_context context,
267655682Smarkm			      krb5_enctype etype1,
267755682Smarkm			      krb5_enctype etype2)
267855682Smarkm{
267955682Smarkm    struct encryption_type *e1 = _find_enctype(etype1);
268055682Smarkm    struct encryption_type *e2 = _find_enctype(etype2);
268155682Smarkm    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
268255682Smarkm}
268355682Smarkm
268455682Smarkmstatic krb5_boolean
268555682Smarkmderived_crypto(krb5_context context,
268655682Smarkm	       krb5_crypto crypto)
268755682Smarkm{
268855682Smarkm    return (crypto->et->flags & F_DERIVED) != 0;
268955682Smarkm}
269055682Smarkm
269172448Sassarstatic krb5_boolean
269272448Sassarspecial_crypto(krb5_context context,
269372448Sassar	       krb5_crypto crypto)
269472448Sassar{
269572448Sassar    return (crypto->et->flags & F_SPECIAL) != 0;
269672448Sassar}
269755682Smarkm
269855682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize)
269955682Smarkm#define CHECKSUMTYPE(C) ((C)->type)
270055682Smarkm
270155682Smarkmstatic krb5_error_code
270255682Smarkmencrypt_internal_derived(krb5_context context,
270355682Smarkm			 krb5_crypto crypto,
270455682Smarkm			 unsigned usage,
270555682Smarkm			 void *data,
270655682Smarkm			 size_t len,
270772448Sassar			 krb5_data *result,
270872448Sassar			 void *ivec)
270955682Smarkm{
271090929Snectar    size_t sz, block_sz, checksum_sz, total_sz;
271155682Smarkm    Checksum cksum;
271255682Smarkm    unsigned char *p, *q;
271355682Smarkm    krb5_error_code ret;
271455682Smarkm    struct key_data *dkey;
271590929Snectar    const struct encryption_type *et = crypto->et;
271655682Smarkm
271755682Smarkm    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
271855682Smarkm
271990929Snectar    sz = et->confoundersize + len;
2720120948Snectar    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
272190929Snectar    total_sz = block_sz + checksum_sz;
272290929Snectar    p = calloc(1, total_sz);
272390929Snectar    if(p == NULL) {
272490929Snectar	krb5_set_error_string(context, "malloc: out of memory");
272555682Smarkm	return ENOMEM;
272690929Snectar    }
272755682Smarkm
272855682Smarkm    q = p;
272955682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
273055682Smarkm    q += et->confoundersize;
273155682Smarkm    memcpy(q, data, len);
273255682Smarkm
273355682Smarkm    ret = create_checksum(context,
273455682Smarkm			  crypto,
273555682Smarkm			  INTEGRITY_USAGE(usage),
273678536Sassar			  et->keyed_checksum->type,
273755682Smarkm			  p,
273855682Smarkm			  block_sz,
273955682Smarkm			  &cksum);
274072448Sassar    if(ret == 0 && cksum.checksum.length != checksum_sz) {
274172448Sassar	free_Checksum (&cksum);
274278536Sassar	krb5_clear_error_string (context);
274372448Sassar	ret = KRB5_CRYPTO_INTERNAL;
274472448Sassar    }
274590929Snectar    if(ret)
274690929Snectar	goto fail;
274755682Smarkm    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
274872448Sassar    free_Checksum (&cksum);
274955682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
275090929Snectar    if(ret)
275190929Snectar	goto fail;
275255682Smarkm    ret = _key_schedule(context, dkey);
275390929Snectar    if(ret)
275490929Snectar	goto fail;
275555682Smarkm#ifdef CRYPTO_DEBUG
275655682Smarkm    krb5_crypto_debug(context, 1, block_sz, dkey->key);
275755682Smarkm#endif
275890929Snectar    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
275990929Snectar    if (ret)
276090929Snectar	goto fail;
276155682Smarkm    result->data = p;
276290929Snectar    result->length = total_sz;
276355682Smarkm    return 0;
276490929Snectar fail:
276590929Snectar    memset(p, 0, total_sz);
276690929Snectar    free(p);
276790929Snectar    return ret;
276855682Smarkm}
276955682Smarkm
277090929Snectar
277155682Smarkmstatic krb5_error_code
277255682Smarkmencrypt_internal(krb5_context context,
277355682Smarkm		 krb5_crypto crypto,
277455682Smarkm		 void *data,
277555682Smarkm		 size_t len,
277672448Sassar		 krb5_data *result,
277772448Sassar		 void *ivec)
277855682Smarkm{
277955682Smarkm    size_t sz, block_sz, checksum_sz;
278055682Smarkm    Checksum cksum;
278155682Smarkm    unsigned char *p, *q;
278255682Smarkm    krb5_error_code ret;
278390929Snectar    const struct encryption_type *et = crypto->et;
278455682Smarkm
278578536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
278655682Smarkm
278755682Smarkm    sz = et->confoundersize + checksum_sz + len;
2788120948Snectar    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
278955682Smarkm    p = calloc(1, block_sz);
279078536Sassar    if(p == NULL) {
279178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
279255682Smarkm	return ENOMEM;
279378536Sassar    }
279455682Smarkm
279555682Smarkm    q = p;
279655682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
279755682Smarkm    q += et->confoundersize;
279855682Smarkm    memset(q, 0, checksum_sz);
279955682Smarkm    q += checksum_sz;
280055682Smarkm    memcpy(q, data, len);
280155682Smarkm
280255682Smarkm    ret = create_checksum(context,
280378536Sassar			  crypto,
280455682Smarkm			  0,
280578536Sassar			  et->checksum->type,
280655682Smarkm			  p,
280755682Smarkm			  block_sz,
280855682Smarkm			  &cksum);
280955682Smarkm    if(ret == 0 && cksum.checksum.length != checksum_sz) {
281078536Sassar	krb5_clear_error_string (context);
281190929Snectar	free_Checksum(&cksum);
281255682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
281355682Smarkm    }
281490929Snectar    if(ret)
281590929Snectar	goto fail;
281655682Smarkm    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
281755682Smarkm    free_Checksum(&cksum);
281855682Smarkm    ret = _key_schedule(context, &crypto->key);
281990929Snectar    if(ret)
282090929Snectar	goto fail;
282190929Snectar#ifdef CRYPTO_DEBUG
282290929Snectar    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
282390929Snectar#endif
282490929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
282590929Snectar    if (ret) {
282655682Smarkm	memset(p, 0, block_sz);
282755682Smarkm	free(p);
282855682Smarkm	return ret;
282955682Smarkm    }
283055682Smarkm    result->data = p;
283155682Smarkm    result->length = block_sz;
283255682Smarkm    return 0;
283390929Snectar fail:
283490929Snectar    memset(p, 0, block_sz);
283590929Snectar    free(p);
283690929Snectar    return ret;
283755682Smarkm}
283855682Smarkm
283955682Smarkmstatic krb5_error_code
284072448Sassarencrypt_internal_special(krb5_context context,
284172448Sassar			 krb5_crypto crypto,
284272448Sassar			 int usage,
284372448Sassar			 void *data,
284472448Sassar			 size_t len,
284572448Sassar			 krb5_data *result,
284672448Sassar			 void *ivec)
284772448Sassar{
284872448Sassar    struct encryption_type *et = crypto->et;
284978536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
285072448Sassar    size_t sz = len + cksum_sz + et->confoundersize;
285172448Sassar    char *tmp, *p;
285290929Snectar    krb5_error_code ret;
285372448Sassar
285472448Sassar    tmp = malloc (sz);
285578536Sassar    if (tmp == NULL) {
285678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
285772448Sassar	return ENOMEM;
285878536Sassar    }
285972448Sassar    p = tmp;
286072448Sassar    memset (p, 0, cksum_sz);
286172448Sassar    p += cksum_sz;
286272448Sassar    krb5_generate_random_block(p, et->confoundersize);
286372448Sassar    p += et->confoundersize;
286472448Sassar    memcpy (p, data, len);
286590929Snectar    ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
286690929Snectar    if (ret) {
286790929Snectar	memset(tmp, 0, sz);
286890929Snectar	free(tmp);
286990929Snectar	return ret;
287090929Snectar    }
287172448Sassar    result->data   = tmp;
287272448Sassar    result->length = sz;
287372448Sassar    return 0;
287472448Sassar}
287572448Sassar
287672448Sassarstatic krb5_error_code
287755682Smarkmdecrypt_internal_derived(krb5_context context,
287855682Smarkm			 krb5_crypto crypto,
287955682Smarkm			 unsigned usage,
288055682Smarkm			 void *data,
288155682Smarkm			 size_t len,
288272448Sassar			 krb5_data *result,
288372448Sassar			 void *ivec)
288455682Smarkm{
288555682Smarkm    size_t checksum_sz;
288655682Smarkm    Checksum cksum;
288755682Smarkm    unsigned char *p;
288855682Smarkm    krb5_error_code ret;
288955682Smarkm    struct key_data *dkey;
289055682Smarkm    struct encryption_type *et = crypto->et;
289155682Smarkm    unsigned long l;
289255682Smarkm
289372448Sassar    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
289478536Sassar    if (len < checksum_sz) {
289578536Sassar	krb5_clear_error_string (context);
289678536Sassar	return EINVAL;		/* XXX - better error code? */
289778536Sassar    }
289872448Sassar
289955682Smarkm    p = malloc(len);
290078536Sassar    if(len != 0 && p == NULL) {
290178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
290255682Smarkm	return ENOMEM;
290378536Sassar    }
290455682Smarkm    memcpy(p, data, len);
290555682Smarkm
290655682Smarkm    len -= checksum_sz;
290755682Smarkm
290855682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
290955682Smarkm    if(ret) {
291055682Smarkm	free(p);
291155682Smarkm	return ret;
291255682Smarkm    }
291355682Smarkm    ret = _key_schedule(context, dkey);
291455682Smarkm    if(ret) {
291555682Smarkm	free(p);
291655682Smarkm	return ret;
291755682Smarkm    }
291855682Smarkm#ifdef CRYPTO_DEBUG
291955682Smarkm    krb5_crypto_debug(context, 0, len, dkey->key);
292055682Smarkm#endif
292190929Snectar    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
292290929Snectar    if (ret) {
292390929Snectar	free(p);
292490929Snectar	return ret;
292590929Snectar    }
292655682Smarkm
292755682Smarkm    cksum.checksum.data   = p + len;
292855682Smarkm    cksum.checksum.length = checksum_sz;
292955682Smarkm    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
293055682Smarkm
293155682Smarkm    ret = verify_checksum(context,
293255682Smarkm			  crypto,
293355682Smarkm			  INTEGRITY_USAGE(usage),
293455682Smarkm			  p,
293555682Smarkm			  len,
293655682Smarkm			  &cksum);
293755682Smarkm    if(ret) {
293855682Smarkm	free(p);
293955682Smarkm	return ret;
294055682Smarkm    }
294155682Smarkm    l = len - et->confoundersize;
294255682Smarkm    memmove(p, p + et->confoundersize, l);
294355682Smarkm    result->data = realloc(p, l);
294478536Sassar    if(result->data == NULL) {
294555682Smarkm	free(p);
294678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
294755682Smarkm	return ENOMEM;
294855682Smarkm    }
294955682Smarkm    result->length = l;
295055682Smarkm    return 0;
295155682Smarkm}
295255682Smarkm
295355682Smarkmstatic krb5_error_code
295455682Smarkmdecrypt_internal(krb5_context context,
295555682Smarkm		 krb5_crypto crypto,
295655682Smarkm		 void *data,
295755682Smarkm		 size_t len,
295872448Sassar		 krb5_data *result,
295972448Sassar		 void *ivec)
296055682Smarkm{
296155682Smarkm    krb5_error_code ret;
296255682Smarkm    unsigned char *p;
296355682Smarkm    Checksum cksum;
296455682Smarkm    size_t checksum_sz, l;
296555682Smarkm    struct encryption_type *et = crypto->et;
296655682Smarkm
296778536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
296855682Smarkm    p = malloc(len);
296978536Sassar    if(len != 0 && p == NULL) {
297078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
297155682Smarkm	return ENOMEM;
297278536Sassar    }
297355682Smarkm    memcpy(p, data, len);
297455682Smarkm
297555682Smarkm    ret = _key_schedule(context, &crypto->key);
297655682Smarkm    if(ret) {
297755682Smarkm	free(p);
297855682Smarkm	return ret;
297955682Smarkm    }
298055682Smarkm#ifdef CRYPTO_DEBUG
298155682Smarkm    krb5_crypto_debug(context, 0, len, crypto->key.key);
298255682Smarkm#endif
298390929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
298490929Snectar    if (ret) {
298590929Snectar	free(p);
298690929Snectar	return ret;
298790929Snectar    }
298855682Smarkm    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
298955682Smarkm    if(ret) {
299072448Sassar 	free(p);
299172448Sassar 	return ret;
299255682Smarkm    }
299355682Smarkm    memset(p + et->confoundersize, 0, checksum_sz);
299478536Sassar    cksum.cksumtype = CHECKSUMTYPE(et->checksum);
299555682Smarkm    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
299655682Smarkm    free_Checksum(&cksum);
299755682Smarkm    if(ret) {
299855682Smarkm	free(p);
299955682Smarkm	return ret;
300055682Smarkm    }
300155682Smarkm    l = len - et->confoundersize - checksum_sz;
300255682Smarkm    memmove(p, p + et->confoundersize + checksum_sz, l);
300355682Smarkm    result->data = realloc(p, l);
300455682Smarkm    if(result->data == NULL) {
300555682Smarkm	free(p);
300678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
300755682Smarkm	return ENOMEM;
300855682Smarkm    }
300955682Smarkm    result->length = l;
301055682Smarkm    return 0;
301155682Smarkm}
301255682Smarkm
301372448Sassarstatic krb5_error_code
301472448Sassardecrypt_internal_special(krb5_context context,
301572448Sassar			 krb5_crypto crypto,
301672448Sassar			 int usage,
301772448Sassar			 void *data,
301872448Sassar			 size_t len,
301972448Sassar			 krb5_data *result,
302072448Sassar			 void *ivec)
302172448Sassar{
302272448Sassar    struct encryption_type *et = crypto->et;
302378536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
302472448Sassar    size_t sz = len - cksum_sz - et->confoundersize;
302572448Sassar    char *cdata = (char *)data;
302672448Sassar    char *tmp;
302790929Snectar    krb5_error_code ret;
302872448Sassar
302972448Sassar    tmp = malloc (sz);
303078536Sassar    if (tmp == NULL) {
303178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
303272448Sassar	return ENOMEM;
303378536Sassar    }
303472448Sassar
303590929Snectar    ret = (*et->encrypt)(context, &crypto->key, data, len, FALSE, usage, ivec);
303690929Snectar    if (ret) {
303790929Snectar	free(tmp);
303890929Snectar	return ret;
303990929Snectar    }
304072448Sassar
304172448Sassar    memcpy (tmp, cdata + cksum_sz + et->confoundersize, sz);
304272448Sassar
304372448Sassar    result->data   = tmp;
304472448Sassar    result->length = sz;
304572448Sassar    return 0;
304672448Sassar}
304772448Sassar
304872448Sassar
304955682Smarkmkrb5_error_code
305072448Sassarkrb5_encrypt_ivec(krb5_context context,
305172448Sassar		  krb5_crypto crypto,
305272448Sassar		  unsigned usage,
305372448Sassar		  void *data,
305472448Sassar		  size_t len,
305572448Sassar		  krb5_data *result,
305672448Sassar		  void *ivec)
305772448Sassar{
305872448Sassar    if(derived_crypto(context, crypto))
305972448Sassar	return encrypt_internal_derived(context, crypto, usage,
306072448Sassar					data, len, result, ivec);
306172448Sassar    else if (special_crypto(context, crypto))
306272448Sassar	return encrypt_internal_special (context, crypto, usage,
306372448Sassar					 data, len, result, ivec);
306472448Sassar    else
306572448Sassar	return encrypt_internal(context, crypto, data, len, result, ivec);
306672448Sassar}
306772448Sassar
306872448Sassarkrb5_error_code
306955682Smarkmkrb5_encrypt(krb5_context context,
307055682Smarkm	     krb5_crypto crypto,
307155682Smarkm	     unsigned usage,
307255682Smarkm	     void *data,
307355682Smarkm	     size_t len,
307455682Smarkm	     krb5_data *result)
307555682Smarkm{
307672448Sassar    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
307755682Smarkm}
307855682Smarkm
307955682Smarkmkrb5_error_code
308055682Smarkmkrb5_encrypt_EncryptedData(krb5_context context,
308155682Smarkm			   krb5_crypto crypto,
308255682Smarkm			   unsigned usage,
308355682Smarkm			   void *data,
308455682Smarkm			   size_t len,
308555682Smarkm			   int kvno,
308655682Smarkm			   EncryptedData *result)
308755682Smarkm{
308855682Smarkm    result->etype = CRYPTO_ETYPE(crypto);
308955682Smarkm    if(kvno){
309055682Smarkm	ALLOC(result->kvno, 1);
309155682Smarkm	*result->kvno = kvno;
309255682Smarkm    }else
309355682Smarkm	result->kvno = NULL;
309455682Smarkm    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
309555682Smarkm}
309655682Smarkm
309755682Smarkmkrb5_error_code
309872448Sassarkrb5_decrypt_ivec(krb5_context context,
309972448Sassar		  krb5_crypto crypto,
310072448Sassar		  unsigned usage,
310172448Sassar		  void *data,
310272448Sassar		  size_t len,
310372448Sassar		  krb5_data *result,
310472448Sassar		  void *ivec)
310572448Sassar{
310672448Sassar    if(derived_crypto(context, crypto))
310772448Sassar	return decrypt_internal_derived(context, crypto, usage,
310872448Sassar					data, len, result, ivec);
310972448Sassar    else if (special_crypto (context, crypto))
311072448Sassar	return decrypt_internal_special(context, crypto, usage,
311172448Sassar					data, len, result, ivec);
311272448Sassar    else
311372448Sassar	return decrypt_internal(context, crypto, data, len, result, ivec);
311472448Sassar}
311572448Sassar
311672448Sassarkrb5_error_code
311755682Smarkmkrb5_decrypt(krb5_context context,
311855682Smarkm	     krb5_crypto crypto,
311955682Smarkm	     unsigned usage,
312055682Smarkm	     void *data,
312155682Smarkm	     size_t len,
312255682Smarkm	     krb5_data *result)
312355682Smarkm{
312472448Sassar    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
312572448Sassar			      NULL);
312655682Smarkm}
312755682Smarkm
312855682Smarkmkrb5_error_code
312955682Smarkmkrb5_decrypt_EncryptedData(krb5_context context,
313055682Smarkm			   krb5_crypto crypto,
313155682Smarkm			   unsigned usage,
313272448Sassar			   const EncryptedData *e,
313355682Smarkm			   krb5_data *result)
313455682Smarkm{
313555682Smarkm    return krb5_decrypt(context, crypto, usage,
313655682Smarkm			e->cipher.data, e->cipher.length, result);
313755682Smarkm}
313855682Smarkm
313955682Smarkm/************************************************************
314055682Smarkm *                                                          *
314155682Smarkm ************************************************************/
314255682Smarkm
314390929Snectar#ifdef HAVE_OPENSSL
314478536Sassar#include <openssl/rand.h>
314578536Sassar
314678536Sassar/* From openssl/crypto/rand/rand_lcl.h */
314778536Sassar#define ENTROPY_NEEDED 20
314878536Sassarstatic int
314978536Sassarseed_something(void)
315078536Sassar{
315178536Sassar    int fd = -1;
315278536Sassar    char buf[1024], seedfile[256];
315378536Sassar
315478536Sassar    /* If there is a seed file, load it. But such a file cannot be trusted,
315578536Sassar       so use 0 for the entropy estimate */
315678536Sassar    if (RAND_file_name(seedfile, sizeof(seedfile))) {
315778536Sassar	fd = open(seedfile, O_RDONLY);
315878536Sassar	if (fd >= 0) {
315978536Sassar	    read(fd, buf, sizeof(buf));
316078536Sassar	    /* Use the full buffer anyway */
316178536Sassar	    RAND_add(buf, sizeof(buf), 0.0);
316278536Sassar	} else
316378536Sassar	    seedfile[0] = '\0';
316478536Sassar    } else
316578536Sassar	seedfile[0] = '\0';
316678536Sassar
316778536Sassar    /* Calling RAND_status() will try to use /dev/urandom if it exists so
316878536Sassar       we do not have to deal with it. */
316978536Sassar    if (RAND_status() != 1) {
317078536Sassar	krb5_context context;
317190929Snectar	const char *p;
317278536Sassar
317378536Sassar	/* Try using egd */
317478536Sassar	if (!krb5_init_context(&context)) {
317578536Sassar	    p = krb5_config_get_string(context, NULL, "libdefaults",
317678536Sassar		"egd_socket", NULL);
317778536Sassar	    if (p != NULL)
317878536Sassar		RAND_egd_bytes(p, ENTROPY_NEEDED);
317978536Sassar	    krb5_free_context(context);
318078536Sassar	}
318178536Sassar    }
318278536Sassar
318378536Sassar    if (RAND_status() == 1)	{
318478536Sassar	/* Update the seed file */
318578536Sassar	if (seedfile[0])
318678536Sassar	    RAND_write_file(seedfile);
318778536Sassar
318878536Sassar	return 0;
318978536Sassar    } else
319078536Sassar	return -1;
319178536Sassar}
319278536Sassar
319355682Smarkmvoid
319455682Smarkmkrb5_generate_random_block(void *buf, size_t len)
319555682Smarkm{
319678536Sassar    static int rng_initialized = 0;
319778536Sassar
319878536Sassar    if (!rng_initialized) {
319978536Sassar	if (seed_something())
320078536Sassar	    krb5_abortx(NULL, "Fatal: could not seed the random number generator");
320178536Sassar
320278536Sassar	rng_initialized = 1;
320378536Sassar    }
320478536Sassar    RAND_bytes(buf, len);
320578536Sassar}
320678536Sassar
320778536Sassar#else
320878536Sassar
320978536Sassarvoid
321078536Sassarkrb5_generate_random_block(void *buf, size_t len)
321178536Sassar{
321255682Smarkm    des_cblock key, out;
321355682Smarkm    static des_cblock counter;
321455682Smarkm    static des_key_schedule schedule;
321555682Smarkm    int i;
321655682Smarkm    static int initialized = 0;
321755682Smarkm
321855682Smarkm    if(!initialized) {
321955682Smarkm	des_new_random_key(&key);
322055682Smarkm	des_set_key(&key, schedule);
322155682Smarkm	memset(&key, 0, sizeof(key));
322255682Smarkm	des_new_random_key(&counter);
322355682Smarkm    }
322455682Smarkm    while(len > 0) {
322555682Smarkm	des_ecb_encrypt(&counter, &out, schedule, DES_ENCRYPT);
322655682Smarkm	for(i = 7; i >=0; i--)
322755682Smarkm	    if(counter[i]++)
322855682Smarkm		break;
322955682Smarkm	memcpy(buf, out, min(len, sizeof(out)));
323055682Smarkm	len -= min(len, sizeof(out));
323155682Smarkm	buf = (char*)buf + sizeof(out);
323255682Smarkm    }
323355682Smarkm}
323478536Sassar#endif
323555682Smarkm
323655682Smarkmstatic void
323755682SmarkmDES3_postproc(krb5_context context,
323855682Smarkm	      unsigned char *k, size_t len, struct key_data *key)
323955682Smarkm{
324055682Smarkm    unsigned char x[24];
324155682Smarkm    int i, j;
324255682Smarkm
324355682Smarkm    memset(x, 0, sizeof(x));
324455682Smarkm    for (i = 0; i < 3; ++i) {
324555682Smarkm	unsigned char foo;
324655682Smarkm
324755682Smarkm	for (j = 0; j < 7; ++j) {
324855682Smarkm	    unsigned char b = k[7 * i + j];
324955682Smarkm
325055682Smarkm	    x[8 * i + j] = b;
325155682Smarkm	}
325255682Smarkm	foo = 0;
325355682Smarkm	for (j = 6; j >= 0; --j) {
325455682Smarkm	    foo |= k[7 * i + j] & 1;
325555682Smarkm	    foo <<= 1;
325655682Smarkm	}
325755682Smarkm	x[8 * i + 7] = foo;
325855682Smarkm    }
325955682Smarkm    k = key->key->keyvalue.data;
326055682Smarkm    memcpy(k, x, 24);
326155682Smarkm    memset(x, 0, sizeof(x));
326255682Smarkm    if (key->schedule) {
326355682Smarkm	krb5_free_data(context, key->schedule);
326455682Smarkm	key->schedule = NULL;
326555682Smarkm    }
326655682Smarkm    des_set_odd_parity((des_cblock*)k);
326755682Smarkm    des_set_odd_parity((des_cblock*)(k + 8));
326855682Smarkm    des_set_odd_parity((des_cblock*)(k + 16));
326955682Smarkm}
327055682Smarkm
327155682Smarkmstatic krb5_error_code
327255682Smarkmderive_key(krb5_context context,
327355682Smarkm	   struct encryption_type *et,
327455682Smarkm	   struct key_data *key,
327578536Sassar	   const void *constant,
327655682Smarkm	   size_t len)
327755682Smarkm{
327855682Smarkm    unsigned char *k;
327955682Smarkm    unsigned int nblocks = 0, i;
328055682Smarkm    krb5_error_code ret = 0;
328155682Smarkm
328255682Smarkm    struct key_type *kt = et->keytype;
328355682Smarkm    ret = _key_schedule(context, key);
328455682Smarkm    if(ret)
328555682Smarkm	return ret;
328672448Sassar    if(et->blocksize * 8 < kt->bits ||
328755682Smarkm       len != et->blocksize) {
328855682Smarkm	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
328955682Smarkm	k = malloc(nblocks * et->blocksize);
329078536Sassar	if(k == NULL) {
329178536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
329255682Smarkm	    return ENOMEM;
329378536Sassar	}
329455682Smarkm	_krb5_n_fold(constant, len, k, et->blocksize);
329555682Smarkm	for(i = 0; i < nblocks; i++) {
329655682Smarkm	    if(i > 0)
329755682Smarkm		memcpy(k + i * et->blocksize,
329855682Smarkm		       k + (i - 1) * et->blocksize,
329955682Smarkm		       et->blocksize);
330078536Sassar	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
330178536Sassar			   1, 0, NULL);
330255682Smarkm	}
330355682Smarkm    } else {
330472448Sassar	/* this case is probably broken, but won't be run anyway */
330555682Smarkm	void *c = malloc(len);
330655682Smarkm	size_t res_len = (kt->bits + 7) / 8;
330755682Smarkm
330878536Sassar	if(len != 0 && c == NULL) {
330978536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
331055682Smarkm	    return ENOMEM;
331178536Sassar	}
331255682Smarkm	memcpy(c, constant, len);
331378536Sassar	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
331455682Smarkm	k = malloc(res_len);
331578536Sassar	if(res_len != 0 && k == NULL) {
331678536Sassar	    free(c);
331778536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
331855682Smarkm	    return ENOMEM;
331978536Sassar	}
332055682Smarkm	_krb5_n_fold(c, len, k, res_len);
332155682Smarkm	free(c);
332255682Smarkm    }
332355682Smarkm
332455682Smarkm    /* XXX keytype dependent post-processing */
332555682Smarkm    switch(kt->type) {
332655682Smarkm    case KEYTYPE_DES3:
332755682Smarkm	DES3_postproc(context, k, nblocks * et->blocksize, key);
332855682Smarkm	break;
3329120948Snectar#ifdef ENABLE_AES
3330120948Snectar    case KEYTYPE_AES128:
3331120948Snectar    case KEYTYPE_AES256:
3332120948Snectar	memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3333120948Snectar	break;
3334120948Snectar#endif /* ENABLE_AES */
333555682Smarkm    default:
333678536Sassar	krb5_set_error_string(context,
333778536Sassar			      "derive_key() called with unknown keytype (%u)",
333878536Sassar			      kt->type);
333955682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
334055682Smarkm	break;
334155682Smarkm    }
334255682Smarkm    memset(k, 0, nblocks * et->blocksize);
334355682Smarkm    free(k);
334455682Smarkm    return ret;
334555682Smarkm}
334655682Smarkm
334755682Smarkmstatic struct key_data *
334855682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage)
334955682Smarkm{
335055682Smarkm    struct key_usage *d = crypto->key_usage;
335155682Smarkm    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
335255682Smarkm    if(d == NULL)
335355682Smarkm	return NULL;
335455682Smarkm    crypto->key_usage = d;
335555682Smarkm    d += crypto->num_key_usage++;
335655682Smarkm    memset(d, 0, sizeof(*d));
335755682Smarkm    d->usage = usage;
335855682Smarkm    return &d->key;
335955682Smarkm}
336055682Smarkm
336178536Sassarkrb5_error_code
336278536Sassarkrb5_derive_key(krb5_context context,
336378536Sassar		const krb5_keyblock *key,
336478536Sassar		krb5_enctype etype,
336578536Sassar		const void *constant,
336678536Sassar		size_t constant_len,
336778536Sassar		krb5_keyblock **derived_key)
336878536Sassar{
336978536Sassar    krb5_error_code ret;
337078536Sassar    struct encryption_type *et;
337178536Sassar    struct key_data d;
337278536Sassar
337378536Sassar    et = _find_enctype (etype);
337478536Sassar    if (et == NULL) {
337578536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
337678536Sassar			      etype);
337778536Sassar	return KRB5_PROG_ETYPE_NOSUPP;
337878536Sassar    }
337978536Sassar
338078536Sassar    ret = krb5_copy_keyblock(context, key, derived_key);
338178536Sassar    if (ret)
338278536Sassar	return ret;
338378536Sassar
338478536Sassar    d.key = *derived_key;
338578536Sassar    d.schedule = NULL;
338678536Sassar    ret = derive_key(context, et, &d, constant, constant_len);
338778536Sassar    if (ret)
338878536Sassar	return ret;
338978536Sassar    ret = krb5_copy_keyblock(context, d.key, derived_key);
339078536Sassar    return ret;
339178536Sassar}
339278536Sassar
339355682Smarkmstatic krb5_error_code
339455682Smarkm_get_derived_key(krb5_context context,
339555682Smarkm		 krb5_crypto crypto,
339655682Smarkm		 unsigned usage,
339755682Smarkm		 struct key_data **key)
339855682Smarkm{
339955682Smarkm    int i;
340055682Smarkm    struct key_data *d;
340155682Smarkm    unsigned char constant[5];
340255682Smarkm
340355682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
340455682Smarkm	if(crypto->key_usage[i].usage == usage) {
340555682Smarkm	    *key = &crypto->key_usage[i].key;
340655682Smarkm	    return 0;
340755682Smarkm	}
340855682Smarkm    d = _new_derived_key(crypto, usage);
340978536Sassar    if(d == NULL) {
341078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
341155682Smarkm	return ENOMEM;
341278536Sassar    }
341355682Smarkm    krb5_copy_keyblock(context, crypto->key.key, &d->key);
341455682Smarkm    _krb5_put_int(constant, usage, 5);
341555682Smarkm    derive_key(context, crypto->et, d, constant, sizeof(constant));
341655682Smarkm    *key = d;
341755682Smarkm    return 0;
341855682Smarkm}
341955682Smarkm
342055682Smarkm
342155682Smarkmkrb5_error_code
342255682Smarkmkrb5_crypto_init(krb5_context context,
342378536Sassar		 const krb5_keyblock *key,
342455682Smarkm		 krb5_enctype etype,
342555682Smarkm		 krb5_crypto *crypto)
342655682Smarkm{
342755682Smarkm    krb5_error_code ret;
342855682Smarkm    ALLOC(*crypto, 1);
342978536Sassar    if(*crypto == NULL) {
343078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
343155682Smarkm	return ENOMEM;
343278536Sassar    }
343355682Smarkm    if(etype == ETYPE_NULL)
343455682Smarkm	etype = key->keytype;
343555682Smarkm    (*crypto)->et = _find_enctype(etype);
343655682Smarkm    if((*crypto)->et == NULL) {
343755682Smarkm	free(*crypto);
343878536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
343978536Sassar			       etype);
344055682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
344155682Smarkm    }
3442102647Snectar    if((*crypto)->et->keytype->size != key->keyvalue.length) {
3443102647Snectar	free(*crypto);
3444102647Snectar	krb5_set_error_string (context, "encryption key has bad length");
3445102647Snectar	return KRB5_BAD_KEYSIZE;
3446102647Snectar    }
344755682Smarkm    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
344855682Smarkm    if(ret) {
344955682Smarkm	free(*crypto);
345055682Smarkm	return ret;
345155682Smarkm    }
345255682Smarkm    (*crypto)->key.schedule = NULL;
345355682Smarkm    (*crypto)->num_key_usage = 0;
345455682Smarkm    (*crypto)->key_usage = NULL;
345555682Smarkm    return 0;
345655682Smarkm}
345755682Smarkm
345855682Smarkmstatic void
345955682Smarkmfree_key_data(krb5_context context, struct key_data *key)
346055682Smarkm{
346155682Smarkm    krb5_free_keyblock(context, key->key);
346255682Smarkm    if(key->schedule) {
346355682Smarkm	memset(key->schedule->data, 0, key->schedule->length);
346455682Smarkm	krb5_free_data(context, key->schedule);
346555682Smarkm    }
346655682Smarkm}
346755682Smarkm
346855682Smarkmstatic void
346955682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku)
347055682Smarkm{
347155682Smarkm    free_key_data(context, &ku->key);
347255682Smarkm}
347355682Smarkm
347455682Smarkmkrb5_error_code
347555682Smarkmkrb5_crypto_destroy(krb5_context context,
347655682Smarkm		    krb5_crypto crypto)
347755682Smarkm{
347855682Smarkm    int i;
347955682Smarkm
348055682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
348155682Smarkm	free_key_usage(context, &crypto->key_usage[i]);
348255682Smarkm    free(crypto->key_usage);
348355682Smarkm    free_key_data(context, &crypto->key);
348455682Smarkm    free (crypto);
348555682Smarkm    return 0;
348655682Smarkm}
348755682Smarkm
348855682Smarkmkrb5_error_code
3489103426Snectarkrb5_crypto_getblocksize(krb5_context context,
3490103426Snectar			 krb5_crypto crypto,
3491103426Snectar			 size_t *blocksize)
3492103426Snectar{
3493103426Snectar    *blocksize = crypto->et->blocksize;
3494103426Snectar    return 0;
3495103426Snectar}
3496103426Snectar
3497103426Snectarkrb5_error_code
349855682Smarkmkrb5_string_to_key_derived(krb5_context context,
349955682Smarkm			   const void *str,
350055682Smarkm			   size_t len,
350155682Smarkm			   krb5_enctype etype,
350255682Smarkm			   krb5_keyblock *key)
350355682Smarkm{
350455682Smarkm    struct encryption_type *et = _find_enctype(etype);
350555682Smarkm    krb5_error_code ret;
350655682Smarkm    struct key_data kd;
350790929Snectar    size_t keylen = et->keytype->bits / 8;
350855682Smarkm    u_char *tmp;
350955682Smarkm
351078536Sassar    if(et == NULL) {
351178536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
351278536Sassar			       etype);
351355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
351478536Sassar    }
351555682Smarkm    ALLOC(kd.key, 1);
351690929Snectar    if(kd.key == NULL) {
351790929Snectar	krb5_set_error_string (context, "malloc: out of memory");
351890929Snectar	return ENOMEM;
351990929Snectar    }
352090929Snectar    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
352190929Snectar    if(ret) {
352290929Snectar	free(kd.key);
352390929Snectar	return ret;
352490929Snectar    }
352555682Smarkm    kd.key->keytype = etype;
352690929Snectar    tmp = malloc (keylen);
352790929Snectar    if(tmp == NULL) {
352890929Snectar	krb5_free_keyblock(context, kd.key);
352990929Snectar	krb5_set_error_string (context, "malloc: out of memory");
353090929Snectar	return ENOMEM;
353190929Snectar    }
353290929Snectar    _krb5_n_fold(str, len, tmp, keylen);
353355682Smarkm    kd.schedule = NULL;
353490929Snectar    DES3_postproc (context, tmp, keylen, &kd); /* XXX */
353590929Snectar    memset(tmp, 0, keylen);
353690929Snectar    free(tmp);
353790929Snectar    ret = derive_key(context,
353855682Smarkm		     et,
353955682Smarkm		     &kd,
354055682Smarkm		     "kerberos", /* XXX well known constant */
354155682Smarkm		     strlen("kerberos"));
354255682Smarkm    ret = krb5_copy_keyblock_contents(context, kd.key, key);
354355682Smarkm    free_key_data(context, &kd);
354455682Smarkm    return ret;
354555682Smarkm}
354655682Smarkm
354772448Sassarstatic size_t
354872448Sassarwrapped_length (krb5_context context,
354972448Sassar		krb5_crypto  crypto,
355072448Sassar		size_t       data_len)
355172448Sassar{
355272448Sassar    struct encryption_type *et = crypto->et;
3553120948Snectar    size_t padsize = et->padsize;
355472448Sassar    size_t res;
355572448Sassar
355678536Sassar    res =  et->confoundersize + et->checksum->checksumsize + data_len;
3557120948Snectar    res =  (res + padsize - 1) / padsize * padsize;
355872448Sassar    return res;
355972448Sassar}
356072448Sassar
356172448Sassarstatic size_t
356272448Sassarwrapped_length_dervied (krb5_context context,
356372448Sassar			krb5_crypto  crypto,
356472448Sassar			size_t       data_len)
356572448Sassar{
356672448Sassar    struct encryption_type *et = crypto->et;
3567120948Snectar    size_t padsize = et->padsize;
356872448Sassar    size_t res;
356972448Sassar
357072448Sassar    res =  et->confoundersize + data_len;
3571120948Snectar    res =  (res + padsize - 1) / padsize * padsize;
357278536Sassar    res += et->checksum->checksumsize;
357372448Sassar    return res;
357472448Sassar}
357572448Sassar
357655682Smarkm/*
357755682Smarkm * Return the size of an encrypted packet of length `data_len'
357855682Smarkm */
357955682Smarkm
358055682Smarkmsize_t
358155682Smarkmkrb5_get_wrapped_length (krb5_context context,
358255682Smarkm			 krb5_crypto  crypto,
358355682Smarkm			 size_t       data_len)
358455682Smarkm{
358572448Sassar    if (derived_crypto (context, crypto))
358672448Sassar	return wrapped_length_dervied (context, crypto, data_len);
358772448Sassar    else
358872448Sassar	return wrapped_length (context, crypto, data_len);
358955682Smarkm}
359055682Smarkm
359155682Smarkm#ifdef CRYPTO_DEBUG
359255682Smarkm
359355682Smarkmstatic krb5_error_code
359455682Smarkmkrb5_get_keyid(krb5_context context,
359555682Smarkm	       krb5_keyblock *key,
359655682Smarkm	       u_int32_t *keyid)
359755682Smarkm{
359857416Smarkm    MD5_CTX md5;
359955682Smarkm    unsigned char tmp[16];
360057416Smarkm
360172448Sassar    MD5_Init (&md5);
360272448Sassar    MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
360372448Sassar    MD5_Final (tmp, &md5);
360455682Smarkm    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
360555682Smarkm    return 0;
360655682Smarkm}
360755682Smarkm
360855682Smarkmstatic void
360955682Smarkmkrb5_crypto_debug(krb5_context context,
361055682Smarkm		  int encrypt,
361155682Smarkm		  size_t len,
361255682Smarkm		  krb5_keyblock *key)
361355682Smarkm{
361455682Smarkm    u_int32_t keyid;
361555682Smarkm    char *kt;
361655682Smarkm    krb5_get_keyid(context, key, &keyid);
361755682Smarkm    krb5_enctype_to_string(context, key->keytype, &kt);
361855682Smarkm    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
361955682Smarkm	       encrypt ? "encrypting" : "decrypting",
362055682Smarkm	       (unsigned long)len,
362155682Smarkm	       keyid,
362255682Smarkm	       kt);
362355682Smarkm    free(kt);
362455682Smarkm}
362555682Smarkm
362655682Smarkm#endif /* CRYPTO_DEBUG */
362772448Sassar
362872448Sassar#if 0
362972448Sassarint
363072448Sassarmain()
363172448Sassar{
363272448Sassar#if 0
363372448Sassar    int i;
363472448Sassar    krb5_context context;
363572448Sassar    krb5_crypto crypto;
363672448Sassar    struct key_data *d;
363772448Sassar    krb5_keyblock key;
363872448Sassar    char constant[4];
363972448Sassar    unsigned usage = ENCRYPTION_USAGE(3);
364072448Sassar    krb5_error_code ret;
364172448Sassar
364272448Sassar    ret = krb5_init_context(&context);
364372448Sassar    if (ret)
364472448Sassar	errx (1, "krb5_init_context failed: %d", ret);
364572448Sassar
364672448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
364772448Sassar    key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
364872448Sassar	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
364972448Sassar	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
365072448Sassar    key.keyvalue.length = 24;
365172448Sassar
365272448Sassar    krb5_crypto_init(context, &key, 0, &crypto);
365372448Sassar
365472448Sassar    d = _new_derived_key(crypto, usage);
365572448Sassar    if(d == NULL)
365672448Sassar	return ENOMEM;
365772448Sassar    krb5_copy_keyblock(context, crypto->key.key, &d->key);
365872448Sassar    _krb5_put_int(constant, usage, 4);
365972448Sassar    derive_key(context, crypto->et, d, constant, sizeof(constant));
366072448Sassar    return 0;
366172448Sassar#else
366272448Sassar    int i;
366372448Sassar    krb5_context context;
366472448Sassar    krb5_crypto crypto;
366572448Sassar    struct key_data *d;
366672448Sassar    krb5_keyblock key;
366772448Sassar    krb5_error_code ret;
366872448Sassar    Checksum res;
366972448Sassar
367072448Sassar    char *data = "what do ya want for nothing?";
367172448Sassar
367272448Sassar    ret = krb5_init_context(&context);
367372448Sassar    if (ret)
367472448Sassar	errx (1, "krb5_init_context failed: %d", ret);
367572448Sassar
367672448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
367772448Sassar    key.keyvalue.data = "Jefe";
367872448Sassar    /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
367972448Sassar       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
368072448Sassar    key.keyvalue.length = 4;
368172448Sassar
368272448Sassar    d = calloc(1, sizeof(*d));
368372448Sassar
368472448Sassar    d->key = &key;
368572448Sassar    res.checksum.length = 20;
368672448Sassar    res.checksum.data = malloc(res.checksum.length);
3687120948Snectar    SP_HMAC_SHA1_checksum(context, d, data, 28, &res);
368872448Sassar
368972448Sassar    return 0;
369072448Sassar#endif
369172448Sassar}
369272448Sassar#endif
3693