155682Smarkm/*
2178828Sdfr * Copyright (c) 1997 - 2005 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"
35178828SdfrRCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $");
3657428Smarkm/* RCSID("$FreeBSD$"); */
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 */
70178828Sdfr#define F_DISABLED	64	/* enctype/checksum disabled */
7155682Smarkm
7255682Smarkmstruct salt_type {
7355682Smarkm    krb5_salttype type;
7455682Smarkm    const char *name;
7555682Smarkm    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data,
76120948Snectar				     krb5_salt, krb5_data, krb5_keyblock*);
7755682Smarkm};
7855682Smarkm
7955682Smarkmstruct key_type {
8055682Smarkm    krb5_keytype type; /* XXX */
8155682Smarkm    const char *name;
8255682Smarkm    size_t bits;
8355682Smarkm    size_t size;
8455682Smarkm    size_t schedule_size;
8555682Smarkm#if 0
8655682Smarkm    krb5_enctype best_etype;
8755682Smarkm#endif
8855682Smarkm    void (*random_key)(krb5_context, krb5_keyblock*);
8955682Smarkm    void (*schedule)(krb5_context, struct key_data *);
9055682Smarkm    struct salt_type *string_to_key;
91178828Sdfr    void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
9255682Smarkm};
9355682Smarkm
9455682Smarkmstruct checksum_type {
9555682Smarkm    krb5_cksumtype type;
9655682Smarkm    const char *name;
9755682Smarkm    size_t blocksize;
9855682Smarkm    size_t checksumsize;
9955682Smarkm    unsigned flags;
10072448Sassar    void (*checksum)(krb5_context context,
10172448Sassar		     struct key_data *key,
10272448Sassar		     const void *buf, size_t len,
10372448Sassar		     unsigned usage,
10472448Sassar		     Checksum *csum);
10572448Sassar    krb5_error_code (*verify)(krb5_context context,
10672448Sassar			      struct key_data *key,
10772448Sassar			      const void *buf, size_t len,
10872448Sassar			      unsigned usage,
10972448Sassar			      Checksum *csum);
11055682Smarkm};
11155682Smarkm
11255682Smarkmstruct encryption_type {
11355682Smarkm    krb5_enctype type;
11455682Smarkm    const char *name;
115178828Sdfr    heim_oid *oid;
11655682Smarkm    size_t blocksize;
117120948Snectar    size_t padsize;
11855682Smarkm    size_t confoundersize;
11955682Smarkm    struct key_type *keytype;
12078536Sassar    struct checksum_type *checksum;
12155682Smarkm    struct checksum_type *keyed_checksum;
12255682Smarkm    unsigned flags;
12378536Sassar    krb5_error_code (*encrypt)(krb5_context context,
12478536Sassar			       struct key_data *key,
12572448Sassar			       void *data, size_t len,
126178828Sdfr			       krb5_boolean encryptp,
12772448Sassar			       int usage,
12872448Sassar			       void *ivec);
129178828Sdfr    size_t prf_length;
130178828Sdfr    krb5_error_code (*prf)(krb5_context,
131178828Sdfr			   krb5_crypto, const krb5_data *, krb5_data *);
13255682Smarkm};
13355682Smarkm
13455682Smarkm#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
13555682Smarkm#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
13655682Smarkm#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
13755682Smarkm
13855682Smarkmstatic struct checksum_type *_find_checksum(krb5_cksumtype type);
13955682Smarkmstatic struct encryption_type *_find_enctype(krb5_enctype type);
14055682Smarkmstatic struct key_type *_find_keytype(krb5_keytype type);
14155682Smarkmstatic krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
14255682Smarkm					unsigned, struct key_data**);
14355682Smarkmstatic struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
144120948Snectarstatic krb5_error_code derive_key(krb5_context context,
145120948Snectar				  struct encryption_type *et,
146120948Snectar				  struct key_data *key,
147120948Snectar				  const void *constant,
148120948Snectar				  size_t len);
149127811Snectarstatic krb5_error_code hmac(krb5_context context,
150127811Snectar			    struct checksum_type *cm,
151127811Snectar			    const void *data,
152127811Snectar			    size_t len,
153127811Snectar			    unsigned usage,
154127811Snectar			    struct key_data *keyblock,
155127811Snectar			    Checksum *result);
156120948Snectarstatic void free_key_data(krb5_context context, struct key_data *key);
157178828Sdfrstatic krb5_error_code usage2arcfour (krb5_context, unsigned *);
158178828Sdfrstatic void xor (DES_cblock *, const unsigned char *);
15955682Smarkm
16055682Smarkm/************************************************************
16155682Smarkm *                                                          *
16255682Smarkm ************************************************************/
16355682Smarkm
164178828Sdfrstatic HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
165178828Sdfr
166178828Sdfr
16755682Smarkmstatic void
168102647Snectarkrb5_DES_random_key(krb5_context context,
16955682Smarkm	       krb5_keyblock *key)
17055682Smarkm{
171178828Sdfr    DES_cblock *k = key->keyvalue.data;
17255682Smarkm    do {
173178828Sdfr	krb5_generate_random_block(k, sizeof(DES_cblock));
174178828Sdfr	DES_set_odd_parity(k);
175178828Sdfr    } while(DES_is_weak_key(k));
17655682Smarkm}
17755682Smarkm
17855682Smarkmstatic void
179102647Snectarkrb5_DES_schedule(krb5_context context,
180178828Sdfr		  struct key_data *key)
18155682Smarkm{
182178828Sdfr    DES_set_key(key->key->keyvalue.data, key->schedule->data);
18355682Smarkm}
18455682Smarkm
185178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY
18690929Snectar
18755682Smarkm/* This defines the Andrew string_to_key function.  It accepts a password
188178828Sdfr * string as input and converts it via a one-way encryption algorithm to a DES
18955682Smarkm * encryption key.  It is compatible with the original Andrew authentication
19055682Smarkm * service password database.
19155682Smarkm */
19255682Smarkm
19355682Smarkm/*
19455682Smarkm * Short passwords, i.e 8 characters or less.
19555682Smarkm */
19655682Smarkmstatic void
197102647Snectarkrb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
19855682Smarkm			    krb5_data cell,
199178828Sdfr			    DES_cblock *key)
20055682Smarkm{
20155682Smarkm    char  password[8+1];	/* crypt is limited to 8 chars anyway */
20255682Smarkm    int   i;
20355682Smarkm
20455682Smarkm    for(i = 0; i < 8; i++) {
20555682Smarkm	char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
20672448Sassar		 ((i < cell.length) ?
20772448Sassar		  tolower(((unsigned char*)cell.data)[i]) : 0);
20855682Smarkm	password[i] = c ? c : 'X';
20955682Smarkm    }
21055682Smarkm    password[8] = '\0';
21155682Smarkm
212178828Sdfr    memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
21355682Smarkm
21455682Smarkm    /* parity is inserted into the LSB so left shift each byte up one
21555682Smarkm       bit. This allows ascii characters with a zero MSB to retain as
21655682Smarkm       much significance as possible. */
217178828Sdfr    for (i = 0; i < sizeof(DES_cblock); i++)
21855682Smarkm	((unsigned char*)key)[i] <<= 1;
219178828Sdfr    DES_set_odd_parity (key);
22055682Smarkm}
22155682Smarkm
22255682Smarkm/*
22355682Smarkm * Long passwords, i.e 9 characters or more.
22455682Smarkm */
22555682Smarkmstatic void
226102647Snectarkrb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
22755682Smarkm				 krb5_data cell,
228178828Sdfr				 DES_cblock *key)
22955682Smarkm{
230178828Sdfr    DES_key_schedule schedule;
231178828Sdfr    DES_cblock temp_key;
232178828Sdfr    DES_cblock ivec;
23355682Smarkm    char password[512];
23455682Smarkm    size_t passlen;
23555682Smarkm
23655682Smarkm    memcpy(password, pw.data, min(pw.length, sizeof(password)));
23772448Sassar    if(pw.length < sizeof(password)) {
23872448Sassar	int len = min(cell.length, sizeof(password) - pw.length);
23972448Sassar	int i;
24072448Sassar
24172448Sassar	memcpy(password + pw.length, cell.data, len);
24272448Sassar	for (i = pw.length; i < pw.length + len; ++i)
24372448Sassar	    password[i] = tolower((unsigned char)password[i]);
24472448Sassar    }
24555682Smarkm    passlen = min(sizeof(password), pw.length + cell.length);
24655682Smarkm    memcpy(&ivec, "kerberos", 8);
24755682Smarkm    memcpy(&temp_key, "kerberos", 8);
248178828Sdfr    DES_set_odd_parity (&temp_key);
249178828Sdfr    DES_set_key (&temp_key, &schedule);
250178828Sdfr    DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
25155682Smarkm
25255682Smarkm    memcpy(&temp_key, &ivec, 8);
253178828Sdfr    DES_set_odd_parity (&temp_key);
254178828Sdfr    DES_set_key (&temp_key, &schedule);
255178828Sdfr    DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
25655682Smarkm    memset(&schedule, 0, sizeof(schedule));
25755682Smarkm    memset(&temp_key, 0, sizeof(temp_key));
25855682Smarkm    memset(&ivec, 0, sizeof(ivec));
25955682Smarkm    memset(password, 0, sizeof(password));
26055682Smarkm
261178828Sdfr    DES_set_odd_parity (key);
26255682Smarkm}
26355682Smarkm
26455682Smarkmstatic krb5_error_code
26555682SmarkmDES_AFS3_string_to_key(krb5_context context,
26655682Smarkm		       krb5_enctype enctype,
26755682Smarkm		       krb5_data password,
26855682Smarkm		       krb5_salt salt,
269120948Snectar		       krb5_data opaque,
27055682Smarkm		       krb5_keyblock *key)
27155682Smarkm{
272178828Sdfr    DES_cblock tmp;
27355682Smarkm    if(password.length > 8)
274102647Snectar	krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
27555682Smarkm    else
276102647Snectar	krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
27755682Smarkm    key->keytype = enctype;
27855682Smarkm    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
27955682Smarkm    memset(&key, 0, sizeof(key));
28055682Smarkm    return 0;
28155682Smarkm}
282178828Sdfr#endif /* ENABLE_AFS_STRING_TO_KEY */
28355682Smarkm
28455682Smarkmstatic void
285178828SdfrDES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
286178828Sdfr{
287178828Sdfr    DES_key_schedule schedule;
288178828Sdfr    int i;
289178828Sdfr    int reverse = 0;
290178828Sdfr    unsigned char *p;
291178828Sdfr
292178828Sdfr    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
293178828Sdfr			     0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
294178828Sdfr    memset(key, 0, 8);
295178828Sdfr
296178828Sdfr    p = (unsigned char*)key;
297178828Sdfr    for (i = 0; i < length; i++) {
298178828Sdfr	unsigned char tmp = data[i];
299178828Sdfr	if (!reverse)
300178828Sdfr	    *p++ ^= (tmp << 1);
301178828Sdfr	else
302178828Sdfr	    *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
303178828Sdfr	if((i % 8) == 7)
304178828Sdfr	    reverse = !reverse;
305178828Sdfr    }
306178828Sdfr    DES_set_odd_parity(key);
307178828Sdfr    if(DES_is_weak_key(key))
308178828Sdfr	(*key)[7] ^= 0xF0;
309178828Sdfr    DES_set_key(key, &schedule);
310178828Sdfr    DES_cbc_cksum((void*)data, key, length, &schedule, key);
311178828Sdfr    memset(&schedule, 0, sizeof(schedule));
312178828Sdfr    DES_set_odd_parity(key);
313178828Sdfr    if(DES_is_weak_key(key))
314178828Sdfr	(*key)[7] ^= 0xF0;
315178828Sdfr}
316178828Sdfr
317178828Sdfrstatic krb5_error_code
318178828Sdfrkrb5_DES_string_to_key(krb5_context context,
319178828Sdfr		  krb5_enctype enctype,
320178828Sdfr		  krb5_data password,
321178828Sdfr		  krb5_salt salt,
322178828Sdfr		  krb5_data opaque,
323178828Sdfr		  krb5_keyblock *key)
324178828Sdfr{
325178828Sdfr    unsigned char *s;
326178828Sdfr    size_t len;
327178828Sdfr    DES_cblock tmp;
328178828Sdfr
329178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY
330178828Sdfr    if (opaque.length == 1) {
331178828Sdfr	unsigned long v;
332178828Sdfr	_krb5_get_int(opaque.data, &v, 1);
333178828Sdfr	if (v == 1)
334178828Sdfr	    return DES_AFS3_string_to_key(context, enctype, password,
335178828Sdfr					  salt, opaque, key);
336178828Sdfr    }
337178828Sdfr#endif
338178828Sdfr
339178828Sdfr    len = password.length + salt.saltvalue.length;
340178828Sdfr    s = malloc(len);
341178828Sdfr    if(len > 0 && s == NULL) {
342178828Sdfr	krb5_set_error_string(context, "malloc: out of memory");
343178828Sdfr	return ENOMEM;
344178828Sdfr    }
345178828Sdfr    memcpy(s, password.data, password.length);
346178828Sdfr    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
347178828Sdfr    DES_string_to_key_int(s, len, &tmp);
348178828Sdfr    key->keytype = enctype;
349178828Sdfr    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
350178828Sdfr    memset(&tmp, 0, sizeof(tmp));
351178828Sdfr    memset(s, 0, len);
352178828Sdfr    free(s);
353178828Sdfr    return 0;
354178828Sdfr}
355178828Sdfr
356178828Sdfrstatic void
357178828Sdfrkrb5_DES_random_to_key(krb5_context context,
358178828Sdfr		       krb5_keyblock *key,
359178828Sdfr		       const void *data,
360178828Sdfr		       size_t size)
361178828Sdfr{
362178828Sdfr    DES_cblock *k = key->keyvalue.data;
363178828Sdfr    memcpy(k, data, key->keyvalue.length);
364178828Sdfr    DES_set_odd_parity(k);
365178828Sdfr    if(DES_is_weak_key(k))
366178828Sdfr	xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
367178828Sdfr}
368178828Sdfr
369178828Sdfr/*
370178828Sdfr *
371178828Sdfr */
372178828Sdfr
373178828Sdfrstatic void
37455682SmarkmDES3_random_key(krb5_context context,
37555682Smarkm		krb5_keyblock *key)
37655682Smarkm{
377178828Sdfr    DES_cblock *k = key->keyvalue.data;
37855682Smarkm    do {
379178828Sdfr	krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
380178828Sdfr	DES_set_odd_parity(&k[0]);
381178828Sdfr	DES_set_odd_parity(&k[1]);
382178828Sdfr	DES_set_odd_parity(&k[2]);
383178828Sdfr    } while(DES_is_weak_key(&k[0]) ||
384178828Sdfr	    DES_is_weak_key(&k[1]) ||
385178828Sdfr	    DES_is_weak_key(&k[2]));
38655682Smarkm}
38755682Smarkm
38855682Smarkmstatic void
38955682SmarkmDES3_schedule(krb5_context context,
39055682Smarkm	      struct key_data *key)
39155682Smarkm{
392178828Sdfr    DES_cblock *k = key->key->keyvalue.data;
393178828Sdfr    DES_key_schedule *s = key->schedule->data;
394178828Sdfr    DES_set_key(&k[0], &s[0]);
395178828Sdfr    DES_set_key(&k[1], &s[1]);
396178828Sdfr    DES_set_key(&k[2], &s[2]);
39755682Smarkm}
39855682Smarkm
39955682Smarkm/*
40055682Smarkm * A = A xor B. A & B are 8 bytes.
40155682Smarkm */
40255682Smarkm
40355682Smarkmstatic void
404178828Sdfrxor (DES_cblock *key, const unsigned char *b)
40555682Smarkm{
40655682Smarkm    unsigned char *a = (unsigned char*)key;
40755682Smarkm    a[0] ^= b[0];
40855682Smarkm    a[1] ^= b[1];
40955682Smarkm    a[2] ^= b[2];
41055682Smarkm    a[3] ^= b[3];
41155682Smarkm    a[4] ^= b[4];
41255682Smarkm    a[5] ^= b[5];
41355682Smarkm    a[6] ^= b[6];
41455682Smarkm    a[7] ^= b[7];
41555682Smarkm}
41655682Smarkm
41755682Smarkmstatic krb5_error_code
41855682SmarkmDES3_string_to_key(krb5_context context,
41955682Smarkm		   krb5_enctype enctype,
42055682Smarkm		   krb5_data password,
42155682Smarkm		   krb5_salt salt,
422120948Snectar		   krb5_data opaque,
42355682Smarkm		   krb5_keyblock *key)
42455682Smarkm{
42555682Smarkm    char *str;
42655682Smarkm    size_t len;
42755682Smarkm    unsigned char tmp[24];
428178828Sdfr    DES_cblock keys[3];
429178828Sdfr    krb5_error_code ret;
43055682Smarkm
43155682Smarkm    len = password.length + salt.saltvalue.length;
43255682Smarkm    str = malloc(len);
43378536Sassar    if(len != 0 && str == NULL) {
43478536Sassar	krb5_set_error_string(context, "malloc: out of memory");
43555682Smarkm	return ENOMEM;
43678536Sassar    }
43755682Smarkm    memcpy(str, password.data, password.length);
43855682Smarkm    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
43955682Smarkm    {
440178828Sdfr	DES_cblock ivec;
441178828Sdfr	DES_key_schedule s[3];
44255682Smarkm	int i;
44355682Smarkm
444178828Sdfr	ret = _krb5_n_fold(str, len, tmp, 24);
445178828Sdfr	if (ret) {
446178828Sdfr	    memset(str, 0, len);
447178828Sdfr	    free(str);
448178828Sdfr	    krb5_set_error_string(context, "out of memory");
449178828Sdfr	    return ret;
450178828Sdfr	}
45155682Smarkm
45255682Smarkm	for(i = 0; i < 3; i++){
45355682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
454178828Sdfr	    DES_set_odd_parity(keys + i);
455178828Sdfr	    if(DES_is_weak_key(keys + i))
456102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
457178828Sdfr	    DES_set_key(keys + i, &s[i]);
45855682Smarkm	}
45955682Smarkm	memset(&ivec, 0, sizeof(ivec));
460178828Sdfr	DES_ede3_cbc_encrypt(tmp,
46190929Snectar			     tmp, sizeof(tmp),
462178828Sdfr			     &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
46355682Smarkm	memset(s, 0, sizeof(s));
46455682Smarkm	memset(&ivec, 0, sizeof(ivec));
46555682Smarkm	for(i = 0; i < 3; i++){
46655682Smarkm	    memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
467178828Sdfr	    DES_set_odd_parity(keys + i);
468178828Sdfr	    if(DES_is_weak_key(keys + i))
469102647Snectar		xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
47055682Smarkm	}
47155682Smarkm	memset(tmp, 0, sizeof(tmp));
47255682Smarkm    }
47355682Smarkm    key->keytype = enctype;
47455682Smarkm    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
47555682Smarkm    memset(keys, 0, sizeof(keys));
47655682Smarkm    memset(str, 0, len);
47755682Smarkm    free(str);
47855682Smarkm    return 0;
47955682Smarkm}
48055682Smarkm
48155682Smarkmstatic krb5_error_code
48255682SmarkmDES3_string_to_key_derived(krb5_context context,
48355682Smarkm			   krb5_enctype enctype,
48455682Smarkm			   krb5_data password,
48555682Smarkm			   krb5_salt salt,
486120948Snectar			   krb5_data opaque,
48755682Smarkm			   krb5_keyblock *key)
48855682Smarkm{
48955682Smarkm    krb5_error_code ret;
49055682Smarkm    size_t len = password.length + salt.saltvalue.length;
49155682Smarkm    char *s;
49255682Smarkm
49355682Smarkm    s = malloc(len);
49478536Sassar    if(len != 0 && s == NULL) {
49578536Sassar	krb5_set_error_string(context, "malloc: out of memory");
49655682Smarkm	return ENOMEM;
49778536Sassar    }
49855682Smarkm    memcpy(s, password.data, password.length);
49955682Smarkm    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
50055682Smarkm    ret = krb5_string_to_key_derived(context,
50155682Smarkm				     s,
50255682Smarkm				     len,
50355682Smarkm				     enctype,
50455682Smarkm				     key);
50555682Smarkm    memset(s, 0, len);
50655682Smarkm    free(s);
50755682Smarkm    return ret;
50855682Smarkm}
50955682Smarkm
510178828Sdfrstatic void
511178828SdfrDES3_random_to_key(krb5_context context,
512178828Sdfr		   krb5_keyblock *key,
513178828Sdfr		   const void *data,
514178828Sdfr		   size_t size)
515178828Sdfr{
516178828Sdfr    unsigned char *x = key->keyvalue.data;
517178828Sdfr    const u_char *q = data;
518178828Sdfr    DES_cblock *k;
519178828Sdfr    int i, j;
520178828Sdfr
521178828Sdfr    memset(x, 0, sizeof(x));
522178828Sdfr    for (i = 0; i < 3; ++i) {
523178828Sdfr	unsigned char foo;
524178828Sdfr	for (j = 0; j < 7; ++j) {
525178828Sdfr	    unsigned char b = q[7 * i + j];
526178828Sdfr
527178828Sdfr	    x[8 * i + j] = b;
528178828Sdfr	}
529178828Sdfr	foo = 0;
530178828Sdfr	for (j = 6; j >= 0; --j) {
531178828Sdfr	    foo |= q[7 * i + j] & 1;
532178828Sdfr	    foo <<= 1;
533178828Sdfr	}
534178828Sdfr	x[8 * i + 7] = foo;
535178828Sdfr    }
536178828Sdfr    k = key->keyvalue.data;
537178828Sdfr    for (i = 0; i < 3; i++) {
538178828Sdfr	DES_set_odd_parity(&k[i]);
539178828Sdfr	if(DES_is_weak_key(&k[i]))
540178828Sdfr	    xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
541178828Sdfr    }
542178828Sdfr}
543178828Sdfr
54455682Smarkm/*
54555682Smarkm * ARCFOUR
54655682Smarkm */
54755682Smarkm
54855682Smarkmstatic void
549178828SdfrARCFOUR_schedule(krb5_context context,
550178828Sdfr		 struct key_data *kd)
55155682Smarkm{
55255682Smarkm    RC4_set_key (kd->schedule->data,
55355682Smarkm		 kd->key->keyvalue.length, kd->key->keyvalue.data);
55455682Smarkm}
55555682Smarkm
55655682Smarkmstatic krb5_error_code
55755682SmarkmARCFOUR_string_to_key(krb5_context context,
55855682Smarkm		  krb5_enctype enctype,
55955682Smarkm		  krb5_data password,
56055682Smarkm		  krb5_salt salt,
561120948Snectar		  krb5_data opaque,
56255682Smarkm		  krb5_keyblock *key)
56355682Smarkm{
56455682Smarkm    char *s, *p;
56555682Smarkm    size_t len;
56655682Smarkm    int i;
56757416Smarkm    MD4_CTX m;
568178828Sdfr    krb5_error_code ret;
56955682Smarkm
57072448Sassar    len = 2 * password.length;
57155682Smarkm    s = malloc (len);
57278536Sassar    if (len != 0 && s == NULL) {
57378536Sassar	krb5_set_error_string(context, "malloc: out of memory");
574178828Sdfr	ret = ENOMEM;
575178828Sdfr	goto out;
57678536Sassar    }
57755682Smarkm    for (p = s, i = 0; i < password.length; ++i) {
57855682Smarkm	*p++ = ((char *)password.data)[i];
57955682Smarkm	*p++ = 0;
58055682Smarkm    }
58172448Sassar    MD4_Init (&m);
58272448Sassar    MD4_Update (&m, s, len);
58355682Smarkm    key->keytype = enctype;
584178828Sdfr    ret = krb5_data_alloc (&key->keyvalue, 16);
585178828Sdfr    if (ret) {
586178828Sdfr	krb5_set_error_string(context, "malloc: out of memory");
587178828Sdfr	goto out;
588178828Sdfr    }
58972448Sassar    MD4_Final (key->keyvalue.data, &m);
59055682Smarkm    memset (s, 0, len);
591178828Sdfr    ret = 0;
592178828Sdfrout:
59355682Smarkm    free (s);
594178828Sdfr    return ret;
59555682Smarkm}
59655682Smarkm
597120948Snectar/*
598120948Snectar * AES
599120948Snectar */
600120948Snectar
601178828Sdfrint _krb5_AES_string_to_default_iterator = 4096;
602120948Snectar
603120948Snectarstatic krb5_error_code
604120948SnectarAES_string_to_key(krb5_context context,
605120948Snectar		  krb5_enctype enctype,
606120948Snectar		  krb5_data password,
607120948Snectar		  krb5_salt salt,
608120948Snectar		  krb5_data opaque,
609120948Snectar		  krb5_keyblock *key)
610120948Snectar{
611120948Snectar    krb5_error_code ret;
612178828Sdfr    uint32_t iter;
613120948Snectar    struct encryption_type *et;
614120948Snectar    struct key_data kd;
615120948Snectar
616120948Snectar    if (opaque.length == 0)
617178828Sdfr	iter = _krb5_AES_string_to_default_iterator;
618120948Snectar    else if (opaque.length == 4) {
619120948Snectar	unsigned long v;
620120948Snectar	_krb5_get_int(opaque.data, &v, 4);
621178828Sdfr	iter = ((uint32_t)v);
622120948Snectar    } else
623120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
624120948Snectar
625120948Snectar    et = _find_enctype(enctype);
626120948Snectar    if (et == NULL)
627120948Snectar	return KRB5_PROG_KEYTYPE_NOSUPP;
628120948Snectar
629178828Sdfr    kd.schedule = NULL;
630178828Sdfr    ALLOC(kd.key, 1);
631178828Sdfr    if(kd.key == NULL) {
632178828Sdfr	krb5_set_error_string (context, "malloc: out of memory");
633178828Sdfr	return ENOMEM;
634178828Sdfr    }
635178828Sdfr    kd.key->keytype = enctype;
636178828Sdfr    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
637178828Sdfr    if (ret) {
638178828Sdfr	krb5_set_error_string(context, "Failed to allocate pkcs5 key");
639120948Snectar	return ret;
640178828Sdfr    }
641120948Snectar
642178828Sdfr    ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
643178828Sdfr				 salt.saltvalue.data, salt.saltvalue.length,
644178828Sdfr				 iter,
645178828Sdfr				 et->keytype->size, kd.key->keyvalue.data);
646178828Sdfr    if (ret != 1) {
647178828Sdfr	free_key_data(context, &kd);
648178828Sdfr	krb5_set_error_string(context, "Error calculating s2k");
649178828Sdfr	return KRB5_PROG_KEYTYPE_NOSUPP;
650178828Sdfr    }
651120948Snectar
652120948Snectar    ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
653178828Sdfr    if (ret == 0)
654120948Snectar	ret = krb5_copy_keyblock_contents(context, kd.key, key);
655178828Sdfr    free_key_data(context, &kd);
656120948Snectar
657120948Snectar    return ret;
658120948Snectar}
659120948Snectar
660178828Sdfrstruct krb5_aes_schedule {
661178828Sdfr    AES_KEY ekey;
662178828Sdfr    AES_KEY dkey;
663178828Sdfr};
664178828Sdfr
665120948Snectarstatic void
666178828SdfrAES_schedule(krb5_context context,
667178828Sdfr	     struct key_data *kd)
668120948Snectar{
669178828Sdfr    struct krb5_aes_schedule *key = kd->schedule->data;
670120948Snectar    int bits = kd->key->keyvalue.length * 8;
671178828Sdfr
672178828Sdfr    memset(key, 0, sizeof(*key));
673178828Sdfr    AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey);
674178828Sdfr    AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey);
675120948Snectar}
676120948Snectar
677120948Snectar/*
678120948Snectar *
679120948Snectar */
680120948Snectar
681178828Sdfrstatic struct salt_type des_salt[] = {
682178828Sdfr    {
683178828Sdfr	KRB5_PW_SALT,
684178828Sdfr	"pw-salt",
685178828Sdfr	krb5_DES_string_to_key
686178828Sdfr    },
687178828Sdfr#ifdef ENABLE_AFS_STRING_TO_KEY
688178828Sdfr    {
689178828Sdfr	KRB5_AFS3_SALT,
690178828Sdfr	"afs3-salt",
691178828Sdfr	DES_AFS3_string_to_key
692178828Sdfr    },
693178828Sdfr#endif
694178828Sdfr    { 0 }
695178828Sdfr};
696120948Snectar
697178828Sdfrstatic struct salt_type des3_salt[] = {
698178828Sdfr    {
699178828Sdfr	KRB5_PW_SALT,
700178828Sdfr	"pw-salt",
701178828Sdfr	DES3_string_to_key
702178828Sdfr    },
703178828Sdfr    { 0 }
704178828Sdfr};
705120948Snectar
706178828Sdfrstatic struct salt_type des3_salt_derived[] = {
707178828Sdfr    {
708178828Sdfr	KRB5_PW_SALT,
709178828Sdfr	"pw-salt",
710178828Sdfr	DES3_string_to_key_derived
711178828Sdfr    },
712178828Sdfr    { 0 }
713178828Sdfr};
71455682Smarkm
715178828Sdfrstatic struct salt_type AES_salt[] = {
716178828Sdfr    {
717178828Sdfr	KRB5_PW_SALT,
718178828Sdfr	"pw-salt",
719178828Sdfr	AES_string_to_key
720178828Sdfr    },
721178828Sdfr    { 0 }
722178828Sdfr};
723178828Sdfr
724178828Sdfrstatic struct salt_type arcfour_salt[] = {
725178828Sdfr    {
726178828Sdfr	KRB5_PW_SALT,
727178828Sdfr	"pw-salt",
728178828Sdfr	ARCFOUR_string_to_key
729178828Sdfr    },
730178828Sdfr    { 0 }
731178828Sdfr};
732178828Sdfr
733178828Sdfr/*
734178828Sdfr *
735178828Sdfr */
736178828Sdfr
737178828Sdfrstatic struct key_type keytype_null = {
73855682Smarkm    KEYTYPE_NULL,
73955682Smarkm    "null",
74055682Smarkm    0,
74155682Smarkm    0,
74255682Smarkm    0,
74355682Smarkm    NULL,
74455682Smarkm    NULL,
74555682Smarkm    NULL
74655682Smarkm};
74755682Smarkm
748178828Sdfrstatic struct key_type keytype_des = {
74955682Smarkm    KEYTYPE_DES,
75055682Smarkm    "des",
75155682Smarkm    56,
752178828Sdfr    sizeof(DES_cblock),
753178828Sdfr    sizeof(DES_key_schedule),
754102647Snectar    krb5_DES_random_key,
755102647Snectar    krb5_DES_schedule,
756178828Sdfr    des_salt,
757178828Sdfr    krb5_DES_random_to_key
75855682Smarkm};
75955682Smarkm
760178828Sdfrstatic struct key_type keytype_des3 = {
76155682Smarkm    KEYTYPE_DES3,
76255682Smarkm    "des3",
76355682Smarkm    168,
764178828Sdfr    3 * sizeof(DES_cblock),
765178828Sdfr    3 * sizeof(DES_key_schedule),
76655682Smarkm    DES3_random_key,
76755682Smarkm    DES3_schedule,
768178828Sdfr    des3_salt,
769178828Sdfr    DES3_random_to_key
77055682Smarkm};
77155682Smarkm
772178828Sdfrstatic struct key_type keytype_des3_derived = {
77355682Smarkm    KEYTYPE_DES3,
77455682Smarkm    "des3",
77555682Smarkm    168,
776178828Sdfr    3 * sizeof(DES_cblock),
777178828Sdfr    3 * sizeof(DES_key_schedule),
77855682Smarkm    DES3_random_key,
77955682Smarkm    DES3_schedule,
780178828Sdfr    des3_salt_derived,
781178828Sdfr    DES3_random_to_key
78255682Smarkm};
78355682Smarkm
784178828Sdfrstatic struct key_type keytype_aes128 = {
785120948Snectar    KEYTYPE_AES128,
786120948Snectar    "aes-128",
787120948Snectar    128,
788120948Snectar    16,
789178828Sdfr    sizeof(struct krb5_aes_schedule),
790120948Snectar    NULL,
791120948Snectar    AES_schedule,
792120948Snectar    AES_salt
793120948Snectar};
794120948Snectar
795178828Sdfrstatic struct key_type keytype_aes256 = {
796120948Snectar    KEYTYPE_AES256,
797120948Snectar    "aes-256",
798120948Snectar    256,
799178828Sdfr    32,
800178828Sdfr    sizeof(struct krb5_aes_schedule),
801120948Snectar    NULL,
802120948Snectar    AES_schedule,
803120948Snectar    AES_salt
804120948Snectar};
805120948Snectar
806178828Sdfrstatic struct key_type keytype_arcfour = {
80755682Smarkm    KEYTYPE_ARCFOUR,
80855682Smarkm    "arcfour",
80955682Smarkm    128,
81055682Smarkm    16,
81155682Smarkm    sizeof(RC4_KEY),
812178828Sdfr    NULL,
81355682Smarkm    ARCFOUR_schedule,
81455682Smarkm    arcfour_salt
81555682Smarkm};
81655682Smarkm
817178828Sdfrstatic struct key_type *keytypes[] = {
81855682Smarkm    &keytype_null,
81955682Smarkm    &keytype_des,
82055682Smarkm    &keytype_des3_derived,
82155682Smarkm    &keytype_des3,
822120948Snectar    &keytype_aes128,
823120948Snectar    &keytype_aes256,
82455682Smarkm    &keytype_arcfour
82555682Smarkm};
82655682Smarkm
82755682Smarkmstatic int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
82855682Smarkm
82955682Smarkmstatic struct key_type *
83055682Smarkm_find_keytype(krb5_keytype type)
83155682Smarkm{
83255682Smarkm    int i;
83355682Smarkm    for(i = 0; i < num_keytypes; i++)
83455682Smarkm	if(keytypes[i]->type == type)
83555682Smarkm	    return keytypes[i];
83655682Smarkm    return NULL;
83755682Smarkm}
83855682Smarkm
83955682Smarkm
840178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
84155682Smarkmkrb5_salttype_to_string (krb5_context context,
84255682Smarkm			 krb5_enctype etype,
84355682Smarkm			 krb5_salttype stype,
84455682Smarkm			 char **string)
84555682Smarkm{
84655682Smarkm    struct encryption_type *e;
84755682Smarkm    struct salt_type *st;
84855682Smarkm
84955682Smarkm    e = _find_enctype (etype);
85078536Sassar    if (e == NULL) {
85178536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
85278536Sassar			      etype);
85355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
85478536Sassar    }
85555682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
85655682Smarkm	if (st->type == stype) {
85755682Smarkm	    *string = strdup (st->name);
85878536Sassar	    if (*string == NULL) {
85978536Sassar		krb5_set_error_string(context, "malloc: out of memory");
86055682Smarkm		return ENOMEM;
86178536Sassar	    }
86255682Smarkm	    return 0;
86355682Smarkm	}
86455682Smarkm    }
86578536Sassar    krb5_set_error_string(context, "salttype %d not supported", stype);
86655682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
86755682Smarkm}
86855682Smarkm
869178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
87055682Smarkmkrb5_string_to_salttype (krb5_context context,
87155682Smarkm			 krb5_enctype etype,
87255682Smarkm			 const char *string,
87355682Smarkm			 krb5_salttype *salttype)
87455682Smarkm{
87555682Smarkm    struct encryption_type *e;
87655682Smarkm    struct salt_type *st;
87755682Smarkm
87855682Smarkm    e = _find_enctype (etype);
87978536Sassar    if (e == NULL) {
88078536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
88178536Sassar			      etype);
88255682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
88378536Sassar    }
88455682Smarkm    for (st = e->keytype->string_to_key; st && st->type; st++) {
88555682Smarkm	if (strcasecmp (st->name, string) == 0) {
88655682Smarkm	    *salttype = st->type;
88755682Smarkm	    return 0;
88855682Smarkm	}
88955682Smarkm    }
89078536Sassar    krb5_set_error_string(context, "salttype %s not supported", string);
89155682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
89255682Smarkm}
89355682Smarkm
894178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
89555682Smarkmkrb5_get_pw_salt(krb5_context context,
89655682Smarkm		 krb5_const_principal principal,
89755682Smarkm		 krb5_salt *salt)
89855682Smarkm{
89955682Smarkm    size_t len;
90055682Smarkm    int i;
90155682Smarkm    krb5_error_code ret;
90255682Smarkm    char *p;
90355682Smarkm
90455682Smarkm    salt->salttype = KRB5_PW_SALT;
90555682Smarkm    len = strlen(principal->realm);
90655682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i)
90755682Smarkm	len += strlen(principal->name.name_string.val[i]);
90855682Smarkm    ret = krb5_data_alloc (&salt->saltvalue, len);
90955682Smarkm    if (ret)
91055682Smarkm	return ret;
91155682Smarkm    p = salt->saltvalue.data;
91255682Smarkm    memcpy (p, principal->realm, strlen(principal->realm));
91355682Smarkm    p += strlen(principal->realm);
91455682Smarkm    for (i = 0; i < principal->name.name_string.len; ++i) {
91555682Smarkm	memcpy (p,
91655682Smarkm		principal->name.name_string.val[i],
91755682Smarkm		strlen(principal->name.name_string.val[i]));
91855682Smarkm	p += strlen(principal->name.name_string.val[i]);
91955682Smarkm    }
92055682Smarkm    return 0;
92155682Smarkm}
92255682Smarkm
923178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
92455682Smarkmkrb5_free_salt(krb5_context context,
92555682Smarkm	       krb5_salt salt)
92655682Smarkm{
92755682Smarkm    krb5_data_free(&salt.saltvalue);
92855682Smarkm    return 0;
92955682Smarkm}
93055682Smarkm
931178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
93255682Smarkmkrb5_string_to_key_data (krb5_context context,
93355682Smarkm			 krb5_enctype enctype,
93455682Smarkm			 krb5_data password,
93555682Smarkm			 krb5_principal principal,
93655682Smarkm			 krb5_keyblock *key)
93755682Smarkm{
93855682Smarkm    krb5_error_code ret;
93955682Smarkm    krb5_salt salt;
94055682Smarkm
94155682Smarkm    ret = krb5_get_pw_salt(context, principal, &salt);
94255682Smarkm    if(ret)
94355682Smarkm	return ret;
94455682Smarkm    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
94555682Smarkm    krb5_free_salt(context, salt);
94655682Smarkm    return ret;
94755682Smarkm}
94855682Smarkm
949178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
95055682Smarkmkrb5_string_to_key (krb5_context context,
95155682Smarkm		    krb5_enctype enctype,
95255682Smarkm		    const char *password,
95355682Smarkm		    krb5_principal principal,
95455682Smarkm		    krb5_keyblock *key)
95555682Smarkm{
95655682Smarkm    krb5_data pw;
957178828Sdfr    pw.data = rk_UNCONST(password);
95855682Smarkm    pw.length = strlen(password);
95955682Smarkm    return krb5_string_to_key_data(context, enctype, pw, principal, key);
96055682Smarkm}
96155682Smarkm
962178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
96355682Smarkmkrb5_string_to_key_data_salt (krb5_context context,
96455682Smarkm			      krb5_enctype enctype,
96555682Smarkm			      krb5_data password,
96655682Smarkm			      krb5_salt salt,
96755682Smarkm			      krb5_keyblock *key)
96855682Smarkm{
969120948Snectar    krb5_data opaque;
970120948Snectar    krb5_data_zero(&opaque);
971120948Snectar    return krb5_string_to_key_data_salt_opaque(context, enctype, password,
972120948Snectar					       salt, opaque, key);
973120948Snectar}
974120948Snectar
975120948Snectar/*
976120948Snectar * Do a string -> key for encryption type `enctype' operation on
977120948Snectar * `password' (with salt `salt' and the enctype specific data string
978120948Snectar * `opaque'), returning the resulting key in `key'
979120948Snectar */
980120948Snectar
981178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
982120948Snectarkrb5_string_to_key_data_salt_opaque (krb5_context context,
983120948Snectar				     krb5_enctype enctype,
984120948Snectar				     krb5_data password,
985120948Snectar				     krb5_salt salt,
986120948Snectar				     krb5_data opaque,
987120948Snectar				     krb5_keyblock *key)
988120948Snectar{
98955682Smarkm    struct encryption_type *et =_find_enctype(enctype);
99055682Smarkm    struct salt_type *st;
99178536Sassar    if(et == NULL) {
99278536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
99378536Sassar			      enctype);
99455682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
99578536Sassar    }
99655682Smarkm    for(st = et->keytype->string_to_key; st && st->type; st++)
99755682Smarkm	if(st->type == salt.salttype)
998120948Snectar	    return (*st->string_to_key)(context, enctype, password,
999120948Snectar					salt, opaque, key);
100078536Sassar    krb5_set_error_string(context, "salt type %d not supported",
100178536Sassar			  salt.salttype);
100255682Smarkm    return HEIM_ERR_SALTTYPE_NOSUPP;
100355682Smarkm}
100455682Smarkm
100572448Sassar/*
100672448Sassar * Do a string -> key for encryption type `enctype' operation on the
100772448Sassar * string `password' (with salt `salt'), returning the resulting key
100872448Sassar * in `key'
100972448Sassar */
101072448Sassar
1011178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
101255682Smarkmkrb5_string_to_key_salt (krb5_context context,
101355682Smarkm			 krb5_enctype enctype,
101455682Smarkm			 const char *password,
101555682Smarkm			 krb5_salt salt,
101655682Smarkm			 krb5_keyblock *key)
101755682Smarkm{
101855682Smarkm    krb5_data pw;
1019178828Sdfr    pw.data = rk_UNCONST(password);
102055682Smarkm    pw.length = strlen(password);
102155682Smarkm    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
102255682Smarkm}
102355682Smarkm
1024178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1025178828Sdfrkrb5_string_to_key_salt_opaque (krb5_context context,
1026178828Sdfr				krb5_enctype enctype,
1027178828Sdfr				const char *password,
1028178828Sdfr				krb5_salt salt,
1029178828Sdfr				krb5_data opaque,
1030178828Sdfr				krb5_keyblock *key)
1031178828Sdfr{
1032178828Sdfr    krb5_data pw;
1033178828Sdfr    pw.data = rk_UNCONST(password);
1034178828Sdfr    pw.length = strlen(password);
1035178828Sdfr    return krb5_string_to_key_data_salt_opaque(context, enctype,
1036178828Sdfr					       pw, salt, opaque, key);
1037178828Sdfr}
1038178828Sdfr
1039178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
104055682Smarkmkrb5_keytype_to_string(krb5_context context,
104155682Smarkm		       krb5_keytype keytype,
104255682Smarkm		       char **string)
104355682Smarkm{
104455682Smarkm    struct key_type *kt = _find_keytype(keytype);
104578536Sassar    if(kt == NULL) {
104678536Sassar	krb5_set_error_string(context, "key type %d not supported", keytype);
104755682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
104878536Sassar    }
104955682Smarkm    *string = strdup(kt->name);
105078536Sassar    if(*string == NULL) {
105178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
105255682Smarkm	return ENOMEM;
105378536Sassar    }
105455682Smarkm    return 0;
105555682Smarkm}
105655682Smarkm
1057178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
105855682Smarkmkrb5_string_to_keytype(krb5_context context,
105955682Smarkm		       const char *string,
106055682Smarkm		       krb5_keytype *keytype)
106155682Smarkm{
106255682Smarkm    int i;
106355682Smarkm    for(i = 0; i < num_keytypes; i++)
106455682Smarkm	if(strcasecmp(keytypes[i]->name, string) == 0){
106555682Smarkm	    *keytype = keytypes[i]->type;
106655682Smarkm	    return 0;
106755682Smarkm	}
106878536Sassar    krb5_set_error_string(context, "key type %s not supported", string);
106955682Smarkm    return KRB5_PROG_KEYTYPE_NOSUPP;
107055682Smarkm}
107155682Smarkm
1072178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1073120948Snectarkrb5_enctype_keysize(krb5_context context,
1074120948Snectar		     krb5_enctype type,
1075120948Snectar		     size_t *keysize)
1076120948Snectar{
1077120948Snectar    struct encryption_type *et = _find_enctype(type);
1078120948Snectar    if(et == NULL) {
1079120948Snectar	krb5_set_error_string(context, "encryption type %d not supported",
1080120948Snectar			      type);
1081120948Snectar	return KRB5_PROG_ETYPE_NOSUPP;
1082120948Snectar    }
1083120948Snectar    *keysize = et->keytype->size;
1084120948Snectar    return 0;
1085120948Snectar}
1086120948Snectar
1087178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1088178828Sdfrkrb5_enctype_keybits(krb5_context context,
1089178828Sdfr		     krb5_enctype type,
1090178828Sdfr		     size_t *keybits)
1091178828Sdfr{
1092178828Sdfr    struct encryption_type *et = _find_enctype(type);
1093178828Sdfr    if(et == NULL) {
1094178828Sdfr	krb5_set_error_string(context, "encryption type %d not supported",
1095178828Sdfr			      type);
1096178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
1097178828Sdfr    }
1098178828Sdfr    *keybits = et->keytype->bits;
1099178828Sdfr    return 0;
1100178828Sdfr}
1101178828Sdfr
1102178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
110355682Smarkmkrb5_generate_random_keyblock(krb5_context context,
110455682Smarkm			      krb5_enctype type,
110555682Smarkm			      krb5_keyblock *key)
110655682Smarkm{
110755682Smarkm    krb5_error_code ret;
110855682Smarkm    struct encryption_type *et = _find_enctype(type);
110978536Sassar    if(et == NULL) {
111078536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
111178536Sassar			      type);
111255682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
111378536Sassar    }
111455682Smarkm    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
111555682Smarkm    if(ret)
111655682Smarkm	return ret;
111755682Smarkm    key->keytype = type;
111855682Smarkm    if(et->keytype->random_key)
111955682Smarkm	(*et->keytype->random_key)(context, key);
112055682Smarkm    else
112155682Smarkm	krb5_generate_random_block(key->keyvalue.data,
112255682Smarkm				   key->keyvalue.length);
112355682Smarkm    return 0;
112455682Smarkm}
112555682Smarkm
112655682Smarkmstatic krb5_error_code
112755682Smarkm_key_schedule(krb5_context context,
112855682Smarkm	      struct key_data *key)
112955682Smarkm{
113055682Smarkm    krb5_error_code ret;
113155682Smarkm    struct encryption_type *et = _find_enctype(key->key->keytype);
113255682Smarkm    struct key_type *kt = et->keytype;
113355682Smarkm
113455682Smarkm    if(kt->schedule == NULL)
113555682Smarkm	return 0;
113672448Sassar    if (key->schedule != NULL)
113772448Sassar	return 0;
113855682Smarkm    ALLOC(key->schedule, 1);
113978536Sassar    if(key->schedule == NULL) {
114078536Sassar	krb5_set_error_string(context, "malloc: out of memory");
114155682Smarkm	return ENOMEM;
114278536Sassar    }
114355682Smarkm    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
114455682Smarkm    if(ret) {
114555682Smarkm	free(key->schedule);
114655682Smarkm	key->schedule = NULL;
114755682Smarkm	return ret;
114855682Smarkm    }
114955682Smarkm    (*kt->schedule)(context, key);
115055682Smarkm    return 0;
115155682Smarkm}
115255682Smarkm
115355682Smarkm/************************************************************
115455682Smarkm *                                                          *
115555682Smarkm ************************************************************/
115655682Smarkm
115755682Smarkmstatic void
115855682SmarkmNONE_checksum(krb5_context context,
115955682Smarkm	      struct key_data *key,
116072448Sassar	      const void *data,
116155682Smarkm	      size_t len,
116272448Sassar	      unsigned usage,
116355682Smarkm	      Checksum *C)
116455682Smarkm{
116555682Smarkm}
116655682Smarkm
116755682Smarkmstatic void
116855682SmarkmCRC32_checksum(krb5_context context,
116955682Smarkm	       struct key_data *key,
117072448Sassar	       const void *data,
117155682Smarkm	       size_t len,
117272448Sassar	       unsigned usage,
117355682Smarkm	       Checksum *C)
117455682Smarkm{
1175178828Sdfr    uint32_t crc;
117655682Smarkm    unsigned char *r = C->checksum.data;
117755682Smarkm    _krb5_crc_init_table ();
117855682Smarkm    crc = _krb5_crc_update (data, len, 0);
117955682Smarkm    r[0] = crc & 0xff;
118055682Smarkm    r[1] = (crc >> 8)  & 0xff;
118155682Smarkm    r[2] = (crc >> 16) & 0xff;
118255682Smarkm    r[3] = (crc >> 24) & 0xff;
118355682Smarkm}
118455682Smarkm
118555682Smarkmstatic void
118655682SmarkmRSA_MD4_checksum(krb5_context context,
118755682Smarkm		 struct key_data *key,
118872448Sassar		 const void *data,
118955682Smarkm		 size_t len,
119072448Sassar		 unsigned usage,
119155682Smarkm		 Checksum *C)
119255682Smarkm{
119357416Smarkm    MD4_CTX m;
119457416Smarkm
119572448Sassar    MD4_Init (&m);
119672448Sassar    MD4_Update (&m, data, len);
119772448Sassar    MD4_Final (C->checksum.data, &m);
119855682Smarkm}
119955682Smarkm
120055682Smarkmstatic void
120155682SmarkmRSA_MD4_DES_checksum(krb5_context context,
120255682Smarkm		     struct key_data *key,
120372448Sassar		     const void *data,
120455682Smarkm		     size_t len,
120572448Sassar		     unsigned usage,
120655682Smarkm		     Checksum *cksum)
120755682Smarkm{
120857416Smarkm    MD4_CTX md4;
1209178828Sdfr    DES_cblock ivec;
121055682Smarkm    unsigned char *p = cksum->checksum.data;
121155682Smarkm
121255682Smarkm    krb5_generate_random_block(p, 8);
121372448Sassar    MD4_Init (&md4);
121472448Sassar    MD4_Update (&md4, p, 8);
121572448Sassar    MD4_Update (&md4, data, len);
121672448Sassar    MD4_Final (p + 8, &md4);
121755682Smarkm    memset (&ivec, 0, sizeof(ivec));
1218178828Sdfr    DES_cbc_encrypt(p,
121990929Snectar		    p,
122055682Smarkm		    24,
122155682Smarkm		    key->schedule->data,
122255682Smarkm		    &ivec,
122355682Smarkm		    DES_ENCRYPT);
122455682Smarkm}
122555682Smarkm
122655682Smarkmstatic krb5_error_code
122755682SmarkmRSA_MD4_DES_verify(krb5_context context,
122855682Smarkm		   struct key_data *key,
122972448Sassar		   const void *data,
123055682Smarkm		   size_t len,
123172448Sassar		   unsigned usage,
123255682Smarkm		   Checksum *C)
123355682Smarkm{
123457416Smarkm    MD4_CTX md4;
123555682Smarkm    unsigned char tmp[24];
123655682Smarkm    unsigned char res[16];
1237178828Sdfr    DES_cblock ivec;
123855682Smarkm    krb5_error_code ret = 0;
123955682Smarkm
124055682Smarkm    memset(&ivec, 0, sizeof(ivec));
1241178828Sdfr    DES_cbc_encrypt(C->checksum.data,
124255682Smarkm		    (void*)tmp,
124355682Smarkm		    C->checksum.length,
124455682Smarkm		    key->schedule->data,
124555682Smarkm		    &ivec,
124655682Smarkm		    DES_DECRYPT);
124772448Sassar    MD4_Init (&md4);
124872448Sassar    MD4_Update (&md4, tmp, 8); /* confounder */
124972448Sassar    MD4_Update (&md4, data, len);
125072448Sassar    MD4_Final (res, &md4);
125178536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
125278536Sassar	krb5_clear_error_string (context);
125355682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
125478536Sassar    }
125555682Smarkm    memset(tmp, 0, sizeof(tmp));
125655682Smarkm    memset(res, 0, sizeof(res));
125755682Smarkm    return ret;
125855682Smarkm}
125955682Smarkm
126055682Smarkmstatic void
126155682SmarkmRSA_MD5_checksum(krb5_context context,
126255682Smarkm		 struct key_data *key,
126372448Sassar		 const void *data,
126455682Smarkm		 size_t len,
126572448Sassar		 unsigned usage,
126655682Smarkm		 Checksum *C)
126755682Smarkm{
126857416Smarkm    MD5_CTX m;
126957416Smarkm
127072448Sassar    MD5_Init  (&m);
127172448Sassar    MD5_Update(&m, data, len);
127272448Sassar    MD5_Final (C->checksum.data, &m);
127355682Smarkm}
127455682Smarkm
127555682Smarkmstatic void
127655682SmarkmRSA_MD5_DES_checksum(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;
1284178828Sdfr    DES_cblock ivec;
128555682Smarkm    unsigned char *p = C->checksum.data;
128655682Smarkm
128755682Smarkm    krb5_generate_random_block(p, 8);
128872448Sassar    MD5_Init (&md5);
128972448Sassar    MD5_Update (&md5, p, 8);
129072448Sassar    MD5_Update (&md5, data, len);
129172448Sassar    MD5_Final (p + 8, &md5);
129255682Smarkm    memset (&ivec, 0, sizeof(ivec));
1293178828Sdfr    DES_cbc_encrypt(p,
129490929Snectar		    p,
129555682Smarkm		    24,
129655682Smarkm		    key->schedule->data,
129755682Smarkm		    &ivec,
129855682Smarkm		    DES_ENCRYPT);
129955682Smarkm}
130055682Smarkm
130155682Smarkmstatic krb5_error_code
130255682SmarkmRSA_MD5_DES_verify(krb5_context context,
130355682Smarkm		   struct key_data *key,
130472448Sassar		   const void *data,
130555682Smarkm		   size_t len,
130672448Sassar		   unsigned usage,
130755682Smarkm		   Checksum *C)
130855682Smarkm{
130957416Smarkm    MD5_CTX md5;
131055682Smarkm    unsigned char tmp[24];
131155682Smarkm    unsigned char res[16];
1312178828Sdfr    DES_cblock ivec;
1313178828Sdfr    DES_key_schedule *sched = key->schedule->data;
131455682Smarkm    krb5_error_code ret = 0;
131555682Smarkm
131655682Smarkm    memset(&ivec, 0, sizeof(ivec));
1317178828Sdfr    DES_cbc_encrypt(C->checksum.data,
131855682Smarkm		    (void*)tmp,
131955682Smarkm		    C->checksum.length,
1320178828Sdfr		    &sched[0],
132155682Smarkm		    &ivec,
132255682Smarkm		    DES_DECRYPT);
132372448Sassar    MD5_Init (&md5);
132472448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
132572448Sassar    MD5_Update (&md5, data, len);
132672448Sassar    MD5_Final (res, &md5);
132778536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
132878536Sassar	krb5_clear_error_string (context);
132955682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
133078536Sassar    }
133155682Smarkm    memset(tmp, 0, sizeof(tmp));
133255682Smarkm    memset(res, 0, sizeof(res));
133355682Smarkm    return ret;
133455682Smarkm}
133555682Smarkm
133655682Smarkmstatic void
133755682SmarkmRSA_MD5_DES3_checksum(krb5_context context,
133855682Smarkm		      struct key_data *key,
133972448Sassar		      const void *data,
134055682Smarkm		      size_t len,
134172448Sassar		      unsigned usage,
134255682Smarkm		      Checksum *C)
134355682Smarkm{
134457416Smarkm    MD5_CTX md5;
1345178828Sdfr    DES_cblock ivec;
134655682Smarkm    unsigned char *p = C->checksum.data;
1347178828Sdfr    DES_key_schedule *sched = key->schedule->data;
134855682Smarkm
134955682Smarkm    krb5_generate_random_block(p, 8);
135072448Sassar    MD5_Init (&md5);
135172448Sassar    MD5_Update (&md5, p, 8);
135272448Sassar    MD5_Update (&md5, data, len);
135372448Sassar    MD5_Final (p + 8, &md5);
135455682Smarkm    memset (&ivec, 0, sizeof(ivec));
1355178828Sdfr    DES_ede3_cbc_encrypt(p,
135690929Snectar			 p,
135755682Smarkm			 24,
1358178828Sdfr			 &sched[0], &sched[1], &sched[2],
135955682Smarkm			 &ivec,
136055682Smarkm			 DES_ENCRYPT);
136155682Smarkm}
136255682Smarkm
136355682Smarkmstatic krb5_error_code
136455682SmarkmRSA_MD5_DES3_verify(krb5_context context,
136555682Smarkm		    struct key_data *key,
136672448Sassar		    const void *data,
136755682Smarkm		    size_t len,
136872448Sassar		    unsigned usage,
136955682Smarkm		    Checksum *C)
137055682Smarkm{
137157416Smarkm    MD5_CTX md5;
137255682Smarkm    unsigned char tmp[24];
137355682Smarkm    unsigned char res[16];
1374178828Sdfr    DES_cblock ivec;
1375178828Sdfr    DES_key_schedule *sched = key->schedule->data;
137655682Smarkm    krb5_error_code ret = 0;
137755682Smarkm
137855682Smarkm    memset(&ivec, 0, sizeof(ivec));
1379178828Sdfr    DES_ede3_cbc_encrypt(C->checksum.data,
138055682Smarkm			 (void*)tmp,
138155682Smarkm			 C->checksum.length,
1382178828Sdfr			 &sched[0], &sched[1], &sched[2],
138355682Smarkm			 &ivec,
138455682Smarkm			 DES_DECRYPT);
138572448Sassar    MD5_Init (&md5);
138672448Sassar    MD5_Update (&md5, tmp, 8); /* confounder */
138772448Sassar    MD5_Update (&md5, data, len);
138872448Sassar    MD5_Final (res, &md5);
138978536Sassar    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
139078536Sassar	krb5_clear_error_string (context);
139155682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
139278536Sassar    }
139355682Smarkm    memset(tmp, 0, sizeof(tmp));
139455682Smarkm    memset(res, 0, sizeof(res));
139555682Smarkm    return ret;
139655682Smarkm}
139755682Smarkm
139855682Smarkmstatic void
139955682SmarkmSHA1_checksum(krb5_context context,
140055682Smarkm	      struct key_data *key,
140172448Sassar	      const void *data,
140255682Smarkm	      size_t len,
140372448Sassar	      unsigned usage,
140455682Smarkm	      Checksum *C)
140555682Smarkm{
140672448Sassar    SHA_CTX m;
140757416Smarkm
140872448Sassar    SHA1_Init(&m);
140972448Sassar    SHA1_Update(&m, data, len);
141072448Sassar    SHA1_Final(C->checksum.data, &m);
141155682Smarkm}
141255682Smarkm
141355682Smarkm/* HMAC according to RFC2104 */
1414127811Snectarstatic krb5_error_code
141555682Smarkmhmac(krb5_context context,
141655682Smarkm     struct checksum_type *cm,
141772448Sassar     const void *data,
141855682Smarkm     size_t len,
141972448Sassar     unsigned usage,
142055682Smarkm     struct key_data *keyblock,
142155682Smarkm     Checksum *result)
142255682Smarkm{
142355682Smarkm    unsigned char *ipad, *opad;
142455682Smarkm    unsigned char *key;
142555682Smarkm    size_t key_len;
142655682Smarkm    int i;
142755682Smarkm
1428127811Snectar    ipad = malloc(cm->blocksize + len);
1429127811Snectar    if (ipad == NULL)
1430127811Snectar	return ENOMEM;
1431127811Snectar    opad = malloc(cm->blocksize + cm->checksumsize);
1432127811Snectar    if (opad == NULL) {
1433127811Snectar	free(ipad);
1434127811Snectar	return ENOMEM;
1435127811Snectar    }
1436127811Snectar    memset(ipad, 0x36, cm->blocksize);
1437127811Snectar    memset(opad, 0x5c, cm->blocksize);
1438127811Snectar
143955682Smarkm    if(keyblock->key->keyvalue.length > cm->blocksize){
144055682Smarkm	(*cm->checksum)(context,
144155682Smarkm			keyblock,
144255682Smarkm			keyblock->key->keyvalue.data,
144355682Smarkm			keyblock->key->keyvalue.length,
144472448Sassar			usage,
144555682Smarkm			result);
144655682Smarkm	key = result->checksum.data;
144755682Smarkm	key_len = result->checksum.length;
144855682Smarkm    } else {
144955682Smarkm	key = keyblock->key->keyvalue.data;
145055682Smarkm	key_len = keyblock->key->keyvalue.length;
145155682Smarkm    }
145255682Smarkm    for(i = 0; i < key_len; i++){
145355682Smarkm	ipad[i] ^= key[i];
145455682Smarkm	opad[i] ^= key[i];
145555682Smarkm    }
145655682Smarkm    memcpy(ipad + cm->blocksize, data, len);
145772448Sassar    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
145872448Sassar		    usage, result);
145955682Smarkm    memcpy(opad + cm->blocksize, result->checksum.data,
146055682Smarkm	   result->checksum.length);
146155682Smarkm    (*cm->checksum)(context, keyblock, opad,
146272448Sassar		    cm->blocksize + cm->checksumsize, usage, result);
146355682Smarkm    memset(ipad, 0, cm->blocksize + len);
146455682Smarkm    free(ipad);
146555682Smarkm    memset(opad, 0, cm->blocksize + cm->checksumsize);
146655682Smarkm    free(opad);
1467127811Snectar
1468127811Snectar    return 0;
146955682Smarkm}
147055682Smarkm
1471178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1472127811Snectarkrb5_hmac(krb5_context context,
1473127811Snectar	  krb5_cksumtype cktype,
1474127811Snectar	  const void *data,
1475127811Snectar	  size_t len,
1476127811Snectar	  unsigned usage,
1477127811Snectar	  krb5_keyblock *key,
1478127811Snectar	  Checksum *result)
1479127811Snectar{
1480127811Snectar    struct checksum_type *c = _find_checksum(cktype);
1481127811Snectar    struct key_data kd;
1482127811Snectar    krb5_error_code ret;
1483127811Snectar
1484127811Snectar    if (c == NULL) {
1485127811Snectar	krb5_set_error_string (context, "checksum type %d not supported",
1486127811Snectar			       cktype);
1487127811Snectar	return KRB5_PROG_SUMTYPE_NOSUPP;
1488127811Snectar    }
1489127811Snectar
1490127811Snectar    kd.key = key;
1491127811Snectar    kd.schedule = NULL;
1492127811Snectar
1493127811Snectar    ret = hmac(context, c, data, len, usage, &kd, result);
1494127811Snectar
1495127811Snectar    if (kd.schedule)
1496127811Snectar	krb5_free_data(context, kd.schedule);
1497127811Snectar
1498127811Snectar    return ret;
1499127811Snectar }
1500127811Snectar
150155682Smarkmstatic void
1502120948SnectarSP_HMAC_SHA1_checksum(krb5_context context,
1503120948Snectar		      struct key_data *key,
1504120948Snectar		      const void *data,
1505120948Snectar		      size_t len,
1506120948Snectar		      unsigned usage,
1507120948Snectar		      Checksum *result)
150855682Smarkm{
150955682Smarkm    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
1510120948Snectar    Checksum res;
1511120948Snectar    char sha1_data[20];
1512127811Snectar    krb5_error_code ret;
151355682Smarkm
1514120948Snectar    res.checksum.data = sha1_data;
1515120948Snectar    res.checksum.length = sizeof(sha1_data);
1516120948Snectar
1517127811Snectar    ret = hmac(context, c, data, len, usage, key, &res);
1518127811Snectar    if (ret)
1519127811Snectar	krb5_abortx(context, "hmac failed");
1520120948Snectar    memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
152155682Smarkm}
152255682Smarkm
152372448Sassar/*
152472448Sassar * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
152572448Sassar */
152672448Sassar
152772448Sassarstatic void
152872448SassarHMAC_MD5_checksum(krb5_context context,
152972448Sassar		  struct key_data *key,
153072448Sassar		  const void *data,
153172448Sassar		  size_t len,
153272448Sassar		  unsigned usage,
153372448Sassar		  Checksum *result)
153472448Sassar{
153572448Sassar    MD5_CTX md5;
153672448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
153772448Sassar    const char signature[] = "signaturekey";
153872448Sassar    Checksum ksign_c;
153972448Sassar    struct key_data ksign;
154072448Sassar    krb5_keyblock kb;
154172448Sassar    unsigned char t[4];
154272448Sassar    unsigned char tmp[16];
154372448Sassar    unsigned char ksign_c_data[16];
1544127811Snectar    krb5_error_code ret;
154572448Sassar
154672448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
154772448Sassar    ksign_c.checksum.data   = ksign_c_data;
1548127811Snectar    ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
1549127811Snectar    if (ret)
1550127811Snectar	krb5_abortx(context, "hmac failed");
155172448Sassar    ksign.key = &kb;
155272448Sassar    kb.keyvalue = ksign_c.checksum;
155372448Sassar    MD5_Init (&md5);
155472448Sassar    t[0] = (usage >>  0) & 0xFF;
155572448Sassar    t[1] = (usage >>  8) & 0xFF;
155672448Sassar    t[2] = (usage >> 16) & 0xFF;
155772448Sassar    t[3] = (usage >> 24) & 0xFF;
155872448Sassar    MD5_Update (&md5, t, 4);
155972448Sassar    MD5_Update (&md5, data, len);
156072448Sassar    MD5_Final (tmp, &md5);
1561127811Snectar    ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
1562127811Snectar    if (ret)
1563127811Snectar	krb5_abortx(context, "hmac failed");
156472448Sassar}
156572448Sassar
156672448Sassar/*
156772448Sassar * same as previous but being used while encrypting.
156872448Sassar */
156972448Sassar
157072448Sassarstatic void
157172448SassarHMAC_MD5_checksum_enc(krb5_context context,
157272448Sassar		      struct key_data *key,
157372448Sassar		      const void *data,
157472448Sassar		      size_t len,
157572448Sassar		      unsigned usage,
157672448Sassar		      Checksum *result)
157772448Sassar{
157872448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
157972448Sassar    Checksum ksign_c;
158072448Sassar    struct key_data ksign;
158172448Sassar    krb5_keyblock kb;
158272448Sassar    unsigned char t[4];
158372448Sassar    unsigned char ksign_c_data[16];
1584127811Snectar    krb5_error_code ret;
158572448Sassar
158672448Sassar    t[0] = (usage >>  0) & 0xFF;
158772448Sassar    t[1] = (usage >>  8) & 0xFF;
158872448Sassar    t[2] = (usage >> 16) & 0xFF;
158972448Sassar    t[3] = (usage >> 24) & 0xFF;
159072448Sassar
159172448Sassar    ksign_c.checksum.length = sizeof(ksign_c_data);
159272448Sassar    ksign_c.checksum.data   = ksign_c_data;
1593127811Snectar    ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
1594127811Snectar    if (ret)
1595127811Snectar	krb5_abortx(context, "hmac failed");
159672448Sassar    ksign.key = &kb;
159772448Sassar    kb.keyvalue = ksign_c.checksum;
1598127811Snectar    ret = hmac(context, c, data, len, 0, &ksign, result);
1599127811Snectar    if (ret)
1600127811Snectar	krb5_abortx(context, "hmac failed");
160172448Sassar}
160272448Sassar
1603178828Sdfrstatic struct checksum_type checksum_none = {
160455682Smarkm    CKSUMTYPE_NONE,
160555682Smarkm    "none",
160655682Smarkm    1,
160755682Smarkm    0,
1608178828Sdfr    0,
160955682Smarkm    NONE_checksum,
161055682Smarkm    NULL
161155682Smarkm};
1612178828Sdfrstatic struct checksum_type checksum_crc32 = {
161355682Smarkm    CKSUMTYPE_CRC32,
161455682Smarkm    "crc32",
161555682Smarkm    1,
161655682Smarkm    4,
161755682Smarkm    0,
161855682Smarkm    CRC32_checksum,
161955682Smarkm    NULL
162055682Smarkm};
1621178828Sdfrstatic struct checksum_type checksum_rsa_md4 = {
162255682Smarkm    CKSUMTYPE_RSA_MD4,
162355682Smarkm    "rsa-md4",
162455682Smarkm    64,
162555682Smarkm    16,
162655682Smarkm    F_CPROOF,
162755682Smarkm    RSA_MD4_checksum,
162855682Smarkm    NULL
162955682Smarkm};
1630178828Sdfrstatic struct checksum_type checksum_rsa_md4_des = {
163155682Smarkm    CKSUMTYPE_RSA_MD4_DES,
163255682Smarkm    "rsa-md4-des",
163355682Smarkm    64,
163455682Smarkm    24,
163555682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
163655682Smarkm    RSA_MD4_DES_checksum,
163755682Smarkm    RSA_MD4_DES_verify
163855682Smarkm};
163955682Smarkm#if 0
1640178828Sdfrstatic struct checksum_type checksum_des_mac = {
164155682Smarkm    CKSUMTYPE_DES_MAC,
164255682Smarkm    "des-mac",
164355682Smarkm    0,
164455682Smarkm    0,
164555682Smarkm    0,
164672448Sassar    DES_MAC_checksum
164755682Smarkm};
1648178828Sdfrstatic struct checksum_type checksum_des_mac_k = {
164955682Smarkm    CKSUMTYPE_DES_MAC_K,
165055682Smarkm    "des-mac-k",
165155682Smarkm    0,
165255682Smarkm    0,
165355682Smarkm    0,
165472448Sassar    DES_MAC_K_checksum
165555682Smarkm};
1656178828Sdfrstatic struct checksum_type checksum_rsa_md4_des_k = {
165755682Smarkm    CKSUMTYPE_RSA_MD4_DES_K,
165855682Smarkm    "rsa-md4-des-k",
165955682Smarkm    0,
166055682Smarkm    0,
166155682Smarkm    0,
166272448Sassar    RSA_MD4_DES_K_checksum,
166372448Sassar    RSA_MD4_DES_K_verify
166455682Smarkm};
166555682Smarkm#endif
1666178828Sdfrstatic struct checksum_type checksum_rsa_md5 = {
166755682Smarkm    CKSUMTYPE_RSA_MD5,
166855682Smarkm    "rsa-md5",
166955682Smarkm    64,
167055682Smarkm    16,
167155682Smarkm    F_CPROOF,
167255682Smarkm    RSA_MD5_checksum,
167355682Smarkm    NULL
167455682Smarkm};
1675178828Sdfrstatic struct checksum_type checksum_rsa_md5_des = {
167655682Smarkm    CKSUMTYPE_RSA_MD5_DES,
167755682Smarkm    "rsa-md5-des",
167855682Smarkm    64,
167955682Smarkm    24,
168055682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
168155682Smarkm    RSA_MD5_DES_checksum,
168272448Sassar    RSA_MD5_DES_verify
168355682Smarkm};
1684178828Sdfrstatic struct checksum_type checksum_rsa_md5_des3 = {
168555682Smarkm    CKSUMTYPE_RSA_MD5_DES3,
168655682Smarkm    "rsa-md5-des3",
168755682Smarkm    64,
168855682Smarkm    24,
168955682Smarkm    F_KEYED | F_CPROOF | F_VARIANT,
169055682Smarkm    RSA_MD5_DES3_checksum,
169172448Sassar    RSA_MD5_DES3_verify
169255682Smarkm};
1693178828Sdfrstatic struct checksum_type checksum_sha1 = {
169455682Smarkm    CKSUMTYPE_SHA1,
169555682Smarkm    "sha1",
169655682Smarkm    64,
169755682Smarkm    20,
169855682Smarkm    F_CPROOF,
169955682Smarkm    SHA1_checksum,
170055682Smarkm    NULL
170155682Smarkm};
1702178828Sdfrstatic struct checksum_type checksum_hmac_sha1_des3 = {
170355682Smarkm    CKSUMTYPE_HMAC_SHA1_DES3,
170455682Smarkm    "hmac-sha1-des3",
170555682Smarkm    64,
170655682Smarkm    20,
170755682Smarkm    F_KEYED | F_CPROOF | F_DERIVED,
1708120948Snectar    SP_HMAC_SHA1_checksum,
170955682Smarkm    NULL
171055682Smarkm};
171155682Smarkm
1712178828Sdfrstatic struct checksum_type checksum_hmac_sha1_aes128 = {
1713120948Snectar    CKSUMTYPE_HMAC_SHA1_96_AES_128,
1714120948Snectar    "hmac-sha1-96-aes128",
1715120948Snectar    64,
1716120948Snectar    12,
1717120948Snectar    F_KEYED | F_CPROOF | F_DERIVED,
1718120948Snectar    SP_HMAC_SHA1_checksum,
1719120948Snectar    NULL
1720120948Snectar};
1721120948Snectar
1722178828Sdfrstatic struct checksum_type checksum_hmac_sha1_aes256 = {
1723120948Snectar    CKSUMTYPE_HMAC_SHA1_96_AES_256,
1724120948Snectar    "hmac-sha1-96-aes256",
1725120948Snectar    64,
1726120948Snectar    12,
1727120948Snectar    F_KEYED | F_CPROOF | F_DERIVED,
1728120948Snectar    SP_HMAC_SHA1_checksum,
1729120948Snectar    NULL
1730120948Snectar};
1731120948Snectar
1732178828Sdfrstatic struct checksum_type checksum_hmac_md5 = {
173372448Sassar    CKSUMTYPE_HMAC_MD5,
173472448Sassar    "hmac-md5",
173572448Sassar    64,
173672448Sassar    16,
173772448Sassar    F_KEYED | F_CPROOF,
173872448Sassar    HMAC_MD5_checksum,
173972448Sassar    NULL
174072448Sassar};
174172448Sassar
1742178828Sdfrstatic struct checksum_type checksum_hmac_md5_enc = {
174372448Sassar    CKSUMTYPE_HMAC_MD5_ENC,
174472448Sassar    "hmac-md5-enc",
174572448Sassar    64,
174672448Sassar    16,
174772448Sassar    F_KEYED | F_CPROOF | F_PSEUDO,
174872448Sassar    HMAC_MD5_checksum_enc,
174972448Sassar    NULL
175072448Sassar};
175172448Sassar
1752178828Sdfrstatic struct checksum_type *checksum_types[] = {
175355682Smarkm    &checksum_none,
175455682Smarkm    &checksum_crc32,
175555682Smarkm    &checksum_rsa_md4,
175655682Smarkm    &checksum_rsa_md4_des,
175755682Smarkm#if 0
175855682Smarkm    &checksum_des_mac,
175955682Smarkm    &checksum_des_mac_k,
176055682Smarkm    &checksum_rsa_md4_des_k,
176155682Smarkm#endif
176255682Smarkm    &checksum_rsa_md5,
176355682Smarkm    &checksum_rsa_md5_des,
176455682Smarkm    &checksum_rsa_md5_des3,
176555682Smarkm    &checksum_sha1,
176672448Sassar    &checksum_hmac_sha1_des3,
1767120948Snectar    &checksum_hmac_sha1_aes128,
1768120948Snectar    &checksum_hmac_sha1_aes256,
176972448Sassar    &checksum_hmac_md5,
177072448Sassar    &checksum_hmac_md5_enc
177155682Smarkm};
177255682Smarkm
177355682Smarkmstatic int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
177455682Smarkm
177555682Smarkmstatic struct checksum_type *
177655682Smarkm_find_checksum(krb5_cksumtype type)
177755682Smarkm{
177855682Smarkm    int i;
177955682Smarkm    for(i = 0; i < num_checksums; i++)
178055682Smarkm	if(checksum_types[i]->type == type)
178155682Smarkm	    return checksum_types[i];
178255682Smarkm    return NULL;
178355682Smarkm}
178455682Smarkm
178555682Smarkmstatic krb5_error_code
178655682Smarkmget_checksum_key(krb5_context context,
178755682Smarkm		 krb5_crypto crypto,
178855682Smarkm		 unsigned usage,  /* not krb5_key_usage */
178955682Smarkm		 struct checksum_type *ct,
179055682Smarkm		 struct key_data **key)
179155682Smarkm{
179255682Smarkm    krb5_error_code ret = 0;
179355682Smarkm
179455682Smarkm    if(ct->flags & F_DERIVED)
179555682Smarkm	ret = _get_derived_key(context, crypto, usage, key);
179655682Smarkm    else if(ct->flags & F_VARIANT) {
179755682Smarkm	int i;
179855682Smarkm
179955682Smarkm	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
180078536Sassar	if(*key == NULL) {
180178536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
180255682Smarkm	    return ENOMEM;
180378536Sassar	}
180455682Smarkm	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
180555682Smarkm	if(ret)
180655682Smarkm	    return ret;
180755682Smarkm	for(i = 0; i < (*key)->key->keyvalue.length; i++)
180855682Smarkm	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
180955682Smarkm    } else {
181055682Smarkm	*key = &crypto->key;
181155682Smarkm    }
181255682Smarkm    if(ret == 0)
181355682Smarkm	ret = _key_schedule(context, *key);
181455682Smarkm    return ret;
181555682Smarkm}
181655682Smarkm
181755682Smarkmstatic krb5_error_code
1818127811Snectarcreate_checksum (krb5_context context,
1819127811Snectar		 struct checksum_type *ct,
1820127811Snectar		 krb5_crypto crypto,
1821127811Snectar		 unsigned usage,
1822127811Snectar		 void *data,
1823127811Snectar		 size_t len,
1824127811Snectar		 Checksum *result)
182555682Smarkm{
182655682Smarkm    krb5_error_code ret;
182755682Smarkm    struct key_data *dkey;
182855682Smarkm    int keyed_checksum;
1829127811Snectar
1830178828Sdfr    if (ct->flags & F_DISABLED) {
1831178828Sdfr	krb5_clear_error_string (context);
1832178828Sdfr	return KRB5_PROG_SUMTYPE_NOSUPP;
1833178828Sdfr    }
183455682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
183578536Sassar    if(keyed_checksum && crypto == NULL) {
1836178828Sdfr	krb5_set_error_string (context, "Checksum type %s is keyed "
1837178828Sdfr			       "but no crypto context (key) was passed in",
1838178828Sdfr			       ct->name);
183955682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
184078536Sassar    }
184172448Sassar    if(keyed_checksum) {
184255682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
184372448Sassar	if (ret)
184472448Sassar	    return ret;
184572448Sassar    } else
184655682Smarkm	dkey = NULL;
184755682Smarkm    result->cksumtype = ct->type;
1848178828Sdfr    ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
1849178828Sdfr    if (ret)
1850178828Sdfr	return (ret);
185172448Sassar    (*ct->checksum)(context, dkey, data, len, usage, result);
185255682Smarkm    return 0;
185355682Smarkm}
185455682Smarkm
1855127811Snectarstatic int
1856127811Snectararcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
185755682Smarkm{
1858127811Snectar    return (ct->type == CKSUMTYPE_HMAC_MD5) &&
1859127811Snectar	(crypto->key.key->keytype == KEYTYPE_ARCFOUR);
1860127811Snectar}
1861127811Snectar
1862178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1863127811Snectarkrb5_create_checksum(krb5_context context,
1864127811Snectar		     krb5_crypto crypto,
1865127811Snectar		     krb5_key_usage usage,
1866127811Snectar		     int type,
1867127811Snectar		     void *data,
1868127811Snectar		     size_t len,
1869127811Snectar		     Checksum *result)
1870127811Snectar{
187178536Sassar    struct checksum_type *ct = NULL;
1872127811Snectar    unsigned keyusage;
187355682Smarkm
1874127811Snectar    /* type 0 -> pick from crypto */
187578536Sassar    if (type) {
187678536Sassar	ct = _find_checksum(type);
187778536Sassar    } else if (crypto) {
187855682Smarkm	ct = crypto->et->keyed_checksum;
187978536Sassar	if (ct == NULL)
188078536Sassar	    ct = crypto->et->checksum;
188178536Sassar    }
188278536Sassar
188378536Sassar    if(ct == NULL) {
188478536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
188578536Sassar			       type);
188655682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
188778536Sassar    }
188855682Smarkm
1889127811Snectar    if (arcfour_checksum_p(ct, crypto)) {
1890127811Snectar	keyusage = usage;
1891127811Snectar	usage2arcfour(context, &keyusage);
1892127811Snectar    } else
1893127811Snectar	keyusage = CHECKSUM_USAGE(usage);
1894127811Snectar
1895127811Snectar    return create_checksum(context, ct, crypto, keyusage,
1896127811Snectar			   data, len, result);
189755682Smarkm}
189855682Smarkm
189955682Smarkmstatic krb5_error_code
190055682Smarkmverify_checksum(krb5_context context,
190155682Smarkm		krb5_crypto crypto,
190255682Smarkm		unsigned usage, /* not krb5_key_usage */
190355682Smarkm		void *data,
190455682Smarkm		size_t len,
190555682Smarkm		Checksum *cksum)
190655682Smarkm{
190755682Smarkm    krb5_error_code ret;
190855682Smarkm    struct key_data *dkey;
190955682Smarkm    int keyed_checksum;
191055682Smarkm    Checksum c;
191155682Smarkm    struct checksum_type *ct;
191255682Smarkm
191355682Smarkm    ct = _find_checksum(cksum->cksumtype);
1914178828Sdfr    if (ct == NULL || (ct->flags & F_DISABLED)) {
191578536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
191678536Sassar			       cksum->cksumtype);
191755682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
191878536Sassar    }
191978536Sassar    if(ct->checksumsize != cksum->checksum.length) {
192078536Sassar	krb5_clear_error_string (context);
192155682Smarkm	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
192278536Sassar    }
192355682Smarkm    keyed_checksum = (ct->flags & F_KEYED) != 0;
192478536Sassar    if(keyed_checksum && crypto == NULL) {
1925178828Sdfr	krb5_set_error_string (context, "Checksum type %s is keyed "
1926178828Sdfr			       "but no crypto context (key) was passed in",
1927178828Sdfr			       ct->name);
192855682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
192978536Sassar    }
193055682Smarkm    if(keyed_checksum)
193155682Smarkm	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
193255682Smarkm    else
193355682Smarkm	dkey = NULL;
193455682Smarkm    if(ct->verify)
193572448Sassar	return (*ct->verify)(context, dkey, data, len, usage, cksum);
193655682Smarkm
193755682Smarkm    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
193855682Smarkm    if (ret)
193955682Smarkm	return ret;
194055682Smarkm
194172448Sassar    (*ct->checksum)(context, dkey, data, len, usage, &c);
194255682Smarkm
194355682Smarkm    if(c.checksum.length != cksum->checksum.length ||
194478536Sassar       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
194578536Sassar	krb5_clear_error_string (context);
194655682Smarkm	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
194778536Sassar    } else {
194855682Smarkm	ret = 0;
194978536Sassar    }
195055682Smarkm    krb5_data_free (&c.checksum);
195155682Smarkm    return ret;
195255682Smarkm}
195355682Smarkm
1954178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
195555682Smarkmkrb5_verify_checksum(krb5_context context,
195655682Smarkm		     krb5_crypto crypto,
195755682Smarkm		     krb5_key_usage usage,
195855682Smarkm		     void *data,
195955682Smarkm		     size_t len,
196055682Smarkm		     Checksum *cksum)
196155682Smarkm{
1962127811Snectar    struct checksum_type *ct;
1963127811Snectar    unsigned keyusage;
1964127811Snectar
1965127811Snectar    ct = _find_checksum(cksum->cksumtype);
1966127811Snectar    if(ct == NULL) {
1967127811Snectar	krb5_set_error_string (context, "checksum type %d not supported",
1968127811Snectar			       cksum->cksumtype);
1969127811Snectar	return KRB5_PROG_SUMTYPE_NOSUPP;
1970127811Snectar    }
1971127811Snectar
1972127811Snectar    if (arcfour_checksum_p(ct, crypto)) {
1973127811Snectar	keyusage = usage;
1974127811Snectar	usage2arcfour(context, &keyusage);
1975127811Snectar    } else
1976127811Snectar	keyusage = CHECKSUM_USAGE(usage);
1977127811Snectar
1978127811Snectar    return verify_checksum(context, crypto, keyusage,
1979127811Snectar			   data, len, cksum);
198055682Smarkm}
198155682Smarkm
1982178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
1983178828Sdfrkrb5_crypto_get_checksum_type(krb5_context context,
1984178828Sdfr                              krb5_crypto crypto,
1985178828Sdfr			      krb5_cksumtype *type)
1986178828Sdfr{
1987178828Sdfr    struct checksum_type *ct = NULL;
1988178828Sdfr
1989178828Sdfr    if (crypto != NULL) {
1990178828Sdfr        ct = crypto->et->keyed_checksum;
1991178828Sdfr        if (ct == NULL)
1992178828Sdfr            ct = crypto->et->checksum;
1993178828Sdfr    }
1994178828Sdfr
1995178828Sdfr    if (ct == NULL) {
1996178828Sdfr	krb5_set_error_string (context, "checksum type not found");
1997178828Sdfr        return KRB5_PROG_SUMTYPE_NOSUPP;
1998178828Sdfr    }
1999178828Sdfr
2000178828Sdfr    *type = ct->type;
2001178828Sdfr
2002178828Sdfr    return 0;
2003178828Sdfr}
2004178828Sdfr
2005178828Sdfr
2006178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
200755682Smarkmkrb5_checksumsize(krb5_context context,
200855682Smarkm		  krb5_cksumtype type,
200955682Smarkm		  size_t *size)
201055682Smarkm{
201155682Smarkm    struct checksum_type *ct = _find_checksum(type);
201278536Sassar    if(ct == NULL) {
201378536Sassar	krb5_set_error_string (context, "checksum type %d not supported",
201478536Sassar			       type);
201555682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
201678536Sassar    }
201755682Smarkm    *size = ct->checksumsize;
201855682Smarkm    return 0;
201955682Smarkm}
202055682Smarkm
2021178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION
202255682Smarkmkrb5_checksum_is_keyed(krb5_context context,
202355682Smarkm		       krb5_cksumtype type)
202455682Smarkm{
202555682Smarkm    struct checksum_type *ct = _find_checksum(type);
202678536Sassar    if(ct == NULL) {
2027178828Sdfr	if (context)
2028178828Sdfr	    krb5_set_error_string (context, "checksum type %d not supported",
2029178828Sdfr				   type);
203055682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
203178536Sassar    }
203255682Smarkm    return ct->flags & F_KEYED;
203355682Smarkm}
203455682Smarkm
2035178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION
203655682Smarkmkrb5_checksum_is_collision_proof(krb5_context context,
203755682Smarkm				 krb5_cksumtype type)
203855682Smarkm{
203955682Smarkm    struct checksum_type *ct = _find_checksum(type);
204078536Sassar    if(ct == NULL) {
2041178828Sdfr	if (context)
2042178828Sdfr	    krb5_set_error_string (context, "checksum type %d not supported",
2043178828Sdfr				   type);
204455682Smarkm	return KRB5_PROG_SUMTYPE_NOSUPP;
204578536Sassar    }
204655682Smarkm    return ct->flags & F_CPROOF;
204755682Smarkm}
204855682Smarkm
2049178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
2050178828Sdfrkrb5_checksum_disable(krb5_context context,
2051178828Sdfr		      krb5_cksumtype type)
2052178828Sdfr{
2053178828Sdfr    struct checksum_type *ct = _find_checksum(type);
2054178828Sdfr    if(ct == NULL) {
2055178828Sdfr	if (context)
2056178828Sdfr	    krb5_set_error_string (context, "checksum type %d not supported",
2057178828Sdfr				   type);
2058178828Sdfr	return KRB5_PROG_SUMTYPE_NOSUPP;
2059178828Sdfr    }
2060178828Sdfr    ct->flags |= F_DISABLED;
2061178828Sdfr    return 0;
2062178828Sdfr}
2063178828Sdfr
206455682Smarkm/************************************************************
206555682Smarkm *                                                          *
206655682Smarkm ************************************************************/
206755682Smarkm
206872448Sassarstatic krb5_error_code
206978536SassarNULL_encrypt(krb5_context context,
207078536Sassar	     struct key_data *key,
207155682Smarkm	     void *data,
207255682Smarkm	     size_t len,
2073178828Sdfr	     krb5_boolean encryptp,
207472448Sassar	     int usage,
207572448Sassar	     void *ivec)
207655682Smarkm{
207772448Sassar    return 0;
207855682Smarkm}
207955682Smarkm
208072448Sassarstatic krb5_error_code
208178536SassarDES_CBC_encrypt_null_ivec(krb5_context context,
208278536Sassar			  struct key_data *key,
208355682Smarkm			  void *data,
208455682Smarkm			  size_t len,
2085178828Sdfr			  krb5_boolean encryptp,
208672448Sassar			  int usage,
208772448Sassar			  void *ignore_ivec)
208855682Smarkm{
2089178828Sdfr    DES_cblock ivec;
2090178828Sdfr    DES_key_schedule *s = key->schedule->data;
209155682Smarkm    memset(&ivec, 0, sizeof(ivec));
2092178828Sdfr    DES_cbc_encrypt(data, data, len, s, &ivec, encryptp);
209372448Sassar    return 0;
209455682Smarkm}
209555682Smarkm
209672448Sassarstatic krb5_error_code
209778536SassarDES_CBC_encrypt_key_ivec(krb5_context context,
209878536Sassar			 struct key_data *key,
209955682Smarkm			 void *data,
210055682Smarkm			 size_t len,
2101178828Sdfr			 krb5_boolean encryptp,
210272448Sassar			 int usage,
210372448Sassar			 void *ignore_ivec)
210455682Smarkm{
2105178828Sdfr    DES_cblock ivec;
2106178828Sdfr    DES_key_schedule *s = key->schedule->data;
210755682Smarkm    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
2108178828Sdfr    DES_cbc_encrypt(data, data, len, s, &ivec, encryptp);
210972448Sassar    return 0;
211055682Smarkm}
211155682Smarkm
211272448Sassarstatic krb5_error_code
211378536SassarDES3_CBC_encrypt(krb5_context context,
211478536Sassar		 struct key_data *key,
211555682Smarkm		 void *data,
211655682Smarkm		 size_t len,
2117178828Sdfr		 krb5_boolean encryptp,
211872448Sassar		 int usage,
2119103426Snectar		 void *ivec)
212055682Smarkm{
2121178828Sdfr    DES_cblock local_ivec;
2122178828Sdfr    DES_key_schedule *s = key->schedule->data;
2123103426Snectar    if(ivec == NULL) {
2124103426Snectar	ivec = &local_ivec;
2125103426Snectar	memset(local_ivec, 0, sizeof(local_ivec));
2126103426Snectar    }
2127178828Sdfr    DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encryptp);
212872448Sassar    return 0;
212972448Sassar}
213072448Sassar
213172448Sassarstatic krb5_error_code
213278536SassarDES_CFB64_encrypt_null_ivec(krb5_context context,
213378536Sassar			    struct key_data *key,
213472448Sassar			    void *data,
213572448Sassar			    size_t len,
2136178828Sdfr			    krb5_boolean encryptp,
213772448Sassar			    int usage,
213872448Sassar			    void *ignore_ivec)
213972448Sassar{
2140178828Sdfr    DES_cblock ivec;
214172448Sassar    int num = 0;
2142178828Sdfr    DES_key_schedule *s = key->schedule->data;
214372448Sassar    memset(&ivec, 0, sizeof(ivec));
214472448Sassar
2145178828Sdfr    DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp);
214672448Sassar    return 0;
214772448Sassar}
214872448Sassar
214972448Sassarstatic krb5_error_code
215078536SassarDES_PCBC_encrypt_key_ivec(krb5_context context,
215178536Sassar			  struct key_data *key,
215272448Sassar			  void *data,
215372448Sassar			  size_t len,
2154178828Sdfr			  krb5_boolean encryptp,
215572448Sassar			  int usage,
215672448Sassar			  void *ignore_ivec)
215772448Sassar{
2158178828Sdfr    DES_cblock ivec;
2159178828Sdfr    DES_key_schedule *s = key->schedule->data;
216072448Sassar    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
216172448Sassar
2162178828Sdfr    DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp);
216372448Sassar    return 0;
216472448Sassar}
216572448Sassar
216672448Sassar/*
2167120948Snectar * AES draft-raeburn-krb-rijndael-krb-02
2168120948Snectar */
2169120948Snectar
2170178828Sdfrvoid KRB5_LIB_FUNCTION
2171120948Snectar_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out,
2172178828Sdfr		      size_t len, const AES_KEY *key,
2173178828Sdfr		      unsigned char *ivec, const int encryptp)
2174120948Snectar{
2175120948Snectar    unsigned char tmp[AES_BLOCK_SIZE];
2176120948Snectar    int i;
2177120948Snectar
2178120948Snectar    /*
2179120948Snectar     * In the framework of kerberos, the length can never be shorter
2180120948Snectar     * then at least one blocksize.
2181120948Snectar     */
2182120948Snectar
2183178828Sdfr    if (encryptp) {
2184120948Snectar
2185120948Snectar	while(len > AES_BLOCK_SIZE) {
2186120948Snectar	    for (i = 0; i < AES_BLOCK_SIZE; i++)
2187120948Snectar		tmp[i] = in[i] ^ ivec[i];
2188120948Snectar	    AES_encrypt(tmp, out, key);
2189120948Snectar	    memcpy(ivec, out, AES_BLOCK_SIZE);
2190120948Snectar	    len -= AES_BLOCK_SIZE;
2191120948Snectar	    in += AES_BLOCK_SIZE;
2192120948Snectar	    out += AES_BLOCK_SIZE;
2193120948Snectar	}
2194120948Snectar
2195120948Snectar	for (i = 0; i < len; i++)
2196120948Snectar	    tmp[i] = in[i] ^ ivec[i];
2197120948Snectar	for (; i < AES_BLOCK_SIZE; i++)
2198120948Snectar	    tmp[i] = 0 ^ ivec[i];
2199120948Snectar
2200120948Snectar	AES_encrypt(tmp, out - AES_BLOCK_SIZE, key);
2201120948Snectar
2202120948Snectar	memcpy(out, ivec, len);
2203178828Sdfr	memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
2204120948Snectar
2205120948Snectar    } else {
2206178828Sdfr	unsigned char tmp2[AES_BLOCK_SIZE];
2207178828Sdfr	unsigned char tmp3[AES_BLOCK_SIZE];
2208120948Snectar
2209120948Snectar	while(len > AES_BLOCK_SIZE * 2) {
2210120948Snectar	    memcpy(tmp, in, AES_BLOCK_SIZE);
2211120948Snectar	    AES_decrypt(in, out, key);
2212120948Snectar	    for (i = 0; i < AES_BLOCK_SIZE; i++)
2213120948Snectar		out[i] ^= ivec[i];
2214120948Snectar	    memcpy(ivec, tmp, AES_BLOCK_SIZE);
2215120948Snectar	    len -= AES_BLOCK_SIZE;
2216120948Snectar	    in += AES_BLOCK_SIZE;
2217120948Snectar	    out += AES_BLOCK_SIZE;
2218120948Snectar	}
2219120948Snectar
2220120948Snectar	len -= AES_BLOCK_SIZE;
2221120948Snectar
2222178828Sdfr	memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */
2223120948Snectar	AES_decrypt(in, tmp2, key);
2224120948Snectar
2225120948Snectar	memcpy(tmp3, in + AES_BLOCK_SIZE, len);
2226120948Snectar	memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */
2227120948Snectar
2228120948Snectar	for (i = 0; i < len; i++)
2229120948Snectar	    out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i];
2230120948Snectar
2231120948Snectar	AES_decrypt(tmp3, out, key);
2232120948Snectar	for (i = 0; i < AES_BLOCK_SIZE; i++)
2233120948Snectar	    out[i] ^= ivec[i];
2234178828Sdfr	memcpy(ivec, tmp, AES_BLOCK_SIZE);
2235120948Snectar    }
2236120948Snectar}
2237120948Snectar
2238120948Snectarstatic krb5_error_code
2239120948SnectarAES_CTS_encrypt(krb5_context context,
2240120948Snectar		struct key_data *key,
2241120948Snectar		void *data,
2242120948Snectar		size_t len,
2243178828Sdfr		krb5_boolean encryptp,
2244120948Snectar		int usage,
2245120948Snectar		void *ivec)
2246120948Snectar{
2247178828Sdfr    struct krb5_aes_schedule *aeskey = key->schedule->data;
2248120948Snectar    char local_ivec[AES_BLOCK_SIZE];
2249178828Sdfr    AES_KEY *k;
2250120948Snectar
2251178828Sdfr    if (encryptp)
2252178828Sdfr	k = &aeskey->ekey;
2253120948Snectar    else
2254178828Sdfr	k = &aeskey->dkey;
2255120948Snectar
2256120948Snectar    if (len < AES_BLOCK_SIZE)
2257127811Snectar	krb5_abortx(context, "invalid use of AES_CTS_encrypt");
2258120948Snectar    if (len == AES_BLOCK_SIZE) {
2259178828Sdfr	if (encryptp)
2260120948Snectar	    AES_encrypt(data, data, k);
2261120948Snectar	else
2262120948Snectar	    AES_decrypt(data, data, k);
2263120948Snectar    } else {
2264120948Snectar	if(ivec == NULL) {
2265120948Snectar	    memset(local_ivec, 0, sizeof(local_ivec));
2266120948Snectar	    ivec = local_ivec;
2267120948Snectar	}
2268178828Sdfr	_krb5_aes_cts_encrypt(data, data, len, k, ivec, encryptp);
2269120948Snectar    }
2270120948Snectar
2271120948Snectar    return 0;
2272120948Snectar}
2273120948Snectar
2274120948Snectar/*
227572448Sassar * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
227672448Sassar *
227772448Sassar * warning: not for small children
227872448Sassar */
227972448Sassar
228072448Sassarstatic krb5_error_code
228178536SassarARCFOUR_subencrypt(krb5_context context,
228278536Sassar		   struct key_data *key,
228372448Sassar		   void *data,
228472448Sassar		   size_t len,
2285178828Sdfr		   unsigned usage,
228672448Sassar		   void *ivec)
228772448Sassar{
228872448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
228972448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
229072448Sassar    struct key_data ke;
229172448Sassar    krb5_keyblock kb;
229272448Sassar    unsigned char t[4];
229372448Sassar    RC4_KEY rc4_key;
229490929Snectar    unsigned char *cdata = data;
229572448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
2296127811Snectar    krb5_error_code ret;
229772448Sassar
229872448Sassar    t[0] = (usage >>  0) & 0xFF;
229972448Sassar    t[1] = (usage >>  8) & 0xFF;
230072448Sassar    t[2] = (usage >> 16) & 0xFF;
230172448Sassar    t[3] = (usage >> 24) & 0xFF;
230272448Sassar
230372448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
230472448Sassar    k1_c.checksum.data   = k1_c_data;
230572448Sassar
2306127811Snectar    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2307127811Snectar    if (ret)
2308127811Snectar	krb5_abortx(context, "hmac failed");
230972448Sassar
231072448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
231172448Sassar
231272448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
231372448Sassar    k2_c.checksum.data   = k2_c_data;
231472448Sassar
231572448Sassar    ke.key = &kb;
231672448Sassar    kb.keyvalue = k2_c.checksum;
231772448Sassar
231872448Sassar    cksum.checksum.length = 16;
231972448Sassar    cksum.checksum.data   = data;
232072448Sassar
2321127811Snectar    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2322127811Snectar    if (ret)
2323127811Snectar	krb5_abortx(context, "hmac failed");
232472448Sassar
232572448Sassar    ke.key = &kb;
232672448Sassar    kb.keyvalue = k1_c.checksum;
232772448Sassar
232872448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
232972448Sassar    k3_c.checksum.data   = k3_c_data;
233072448Sassar
2331127811Snectar    ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
2332127811Snectar    if (ret)
2333127811Snectar	krb5_abortx(context, "hmac failed");
233472448Sassar
233572448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
233672448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
233772448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
233872448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
233972448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
234072448Sassar    return 0;
234172448Sassar}
234272448Sassar
234372448Sassarstatic krb5_error_code
234478536SassarARCFOUR_subdecrypt(krb5_context context,
234578536Sassar		   struct key_data *key,
234672448Sassar		   void *data,
234772448Sassar		   size_t len,
2348178828Sdfr		   unsigned usage,
234972448Sassar		   void *ivec)
235072448Sassar{
235172448Sassar    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
235272448Sassar    Checksum k1_c, k2_c, k3_c, cksum;
235372448Sassar    struct key_data ke;
235472448Sassar    krb5_keyblock kb;
235572448Sassar    unsigned char t[4];
235672448Sassar    RC4_KEY rc4_key;
235790929Snectar    unsigned char *cdata = data;
235872448Sassar    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
235972448Sassar    unsigned char cksum_data[16];
2360127811Snectar    krb5_error_code ret;
236172448Sassar
236272448Sassar    t[0] = (usage >>  0) & 0xFF;
236372448Sassar    t[1] = (usage >>  8) & 0xFF;
236472448Sassar    t[2] = (usage >> 16) & 0xFF;
236572448Sassar    t[3] = (usage >> 24) & 0xFF;
236672448Sassar
236772448Sassar    k1_c.checksum.length = sizeof(k1_c_data);
236872448Sassar    k1_c.checksum.data   = k1_c_data;
236972448Sassar
2370127811Snectar    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
2371127811Snectar    if (ret)
2372127811Snectar	krb5_abortx(context, "hmac failed");
237372448Sassar
237472448Sassar    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
237572448Sassar
237672448Sassar    k2_c.checksum.length = sizeof(k2_c_data);
237772448Sassar    k2_c.checksum.data   = k2_c_data;
237872448Sassar
237972448Sassar    ke.key = &kb;
238072448Sassar    kb.keyvalue = k1_c.checksum;
238172448Sassar
238272448Sassar    k3_c.checksum.length = sizeof(k3_c_data);
238372448Sassar    k3_c.checksum.data   = k3_c_data;
238472448Sassar
2385127811Snectar    ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
2386127811Snectar    if (ret)
2387127811Snectar	krb5_abortx(context, "hmac failed");
238872448Sassar
238972448Sassar    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
239072448Sassar    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
239172448Sassar
239272448Sassar    ke.key = &kb;
239372448Sassar    kb.keyvalue = k2_c.checksum;
239472448Sassar
239572448Sassar    cksum.checksum.length = 16;
239672448Sassar    cksum.checksum.data   = cksum_data;
239772448Sassar
2398127811Snectar    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
2399127811Snectar    if (ret)
2400127811Snectar	krb5_abortx(context, "hmac failed");
240172448Sassar
240272448Sassar    memset (k1_c_data, 0, sizeof(k1_c_data));
240372448Sassar    memset (k2_c_data, 0, sizeof(k2_c_data));
240472448Sassar    memset (k3_c_data, 0, sizeof(k3_c_data));
240572448Sassar
240678536Sassar    if (memcmp (cksum.checksum.data, data, 16) != 0) {
240778536Sassar	krb5_clear_error_string (context);
240872448Sassar	return KRB5KRB_AP_ERR_BAD_INTEGRITY;
240978536Sassar    } else {
241072448Sassar	return 0;
241178536Sassar    }
241272448Sassar}
241372448Sassar
241472448Sassar/*
241572448Sassar * convert the usage numbers used in
241672448Sassar * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
2417127811Snectar * draft-brezak-win2k-krb-rc4-hmac-04.txt
241872448Sassar */
241972448Sassar
2420102647Snectarstatic krb5_error_code
2421178828Sdfrusage2arcfour (krb5_context context, unsigned *usage)
242272448Sassar{
2423102647Snectar    switch (*usage) {
2424127811Snectar    case KRB5_KU_AS_REP_ENC_PART : /* 3 */
2425127811Snectar    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
2426102647Snectar	*usage = 8;
2427102647Snectar	return 0;
2428127811Snectar    case KRB5_KU_USAGE_SEAL :  /* 22 */
2429127811Snectar	*usage = 13;
2430102647Snectar	return 0;
2431127811Snectar    case KRB5_KU_USAGE_SIGN : /* 23 */
2432127811Snectar        *usage = 15;
2433127811Snectar        return 0;
2434127811Snectar    case KRB5_KU_USAGE_SEQ: /* 24 */
2435102647Snectar	*usage = 0;
243672448Sassar	return 0;
243772448Sassar    default :
2438127811Snectar	return 0;
243972448Sassar    }
244072448Sassar}
244172448Sassar
244272448Sassarstatic krb5_error_code
244378536SassarARCFOUR_encrypt(krb5_context context,
244478536Sassar		struct key_data *key,
244555682Smarkm		void *data,
244655682Smarkm		size_t len,
2447178828Sdfr		krb5_boolean encryptp,
244872448Sassar		int usage,
244972448Sassar		void *ivec)
245055682Smarkm{
2451102647Snectar    krb5_error_code ret;
2452178828Sdfr    unsigned keyusage = usage;
2453178828Sdfr
2454178828Sdfr    if((ret = usage2arcfour (context, &keyusage)) != 0)
2455102647Snectar	return ret;
245655682Smarkm
2457178828Sdfr    if (encryptp)
2458178828Sdfr	return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
245972448Sassar    else
2460178828Sdfr	return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
246155682Smarkm}
246255682Smarkm
246372448Sassar
246455682Smarkm/*
2465178828Sdfr *
2466178828Sdfr */
2467178828Sdfr
2468178828Sdfrstatic krb5_error_code
2469178828SdfrAES_PRF(krb5_context context,
2470178828Sdfr	krb5_crypto crypto,
2471178828Sdfr	const krb5_data *in,
2472178828Sdfr	krb5_data *out)
2473178828Sdfr{
2474178828Sdfr    struct checksum_type *ct = crypto->et->checksum;
2475178828Sdfr    krb5_error_code ret;
2476178828Sdfr    Checksum result;
2477178828Sdfr    krb5_keyblock *derived;
2478178828Sdfr
2479178828Sdfr    result.cksumtype = ct->type;
2480178828Sdfr    ret = krb5_data_alloc(&result.checksum, ct->checksumsize);
2481178828Sdfr    if (ret) {
2482178828Sdfr	krb5_set_error_string(context, "out memory");
2483178828Sdfr	return ret;
2484178828Sdfr    }
2485178828Sdfr
2486178828Sdfr    (*ct->checksum)(context, NULL, in->data, in->length, 0, &result);
2487178828Sdfr
2488178828Sdfr    if (result.checksum.length < crypto->et->blocksize)
2489178828Sdfr	krb5_abortx(context, "internal prf error");
2490178828Sdfr
2491178828Sdfr    derived = NULL;
2492178828Sdfr    ret = krb5_derive_key(context, crypto->key.key,
2493178828Sdfr			  crypto->et->type, "prf", 3, &derived);
2494178828Sdfr    if (ret)
2495178828Sdfr	krb5_abortx(context, "krb5_derive_key");
2496178828Sdfr
2497178828Sdfr    ret = krb5_data_alloc(out, crypto->et->blocksize);
2498178828Sdfr    if (ret)
2499178828Sdfr	krb5_abortx(context, "malloc failed");
2500178828Sdfr
2501178828Sdfr    {
2502178828Sdfr	AES_KEY key;
2503178828Sdfr
2504178828Sdfr	AES_set_encrypt_key(derived->keyvalue.data,
2505178828Sdfr			    crypto->et->keytype->bits, &key);
2506178828Sdfr	AES_encrypt(result.checksum.data, out->data, &key);
2507178828Sdfr	memset(&key, 0, sizeof(key));
2508178828Sdfr    }
2509178828Sdfr
2510178828Sdfr    krb5_data_free(&result.checksum);
2511178828Sdfr    krb5_free_keyblock(context, derived);
2512178828Sdfr
2513178828Sdfr    return ret;
2514178828Sdfr}
2515178828Sdfr
2516178828Sdfr/*
251755682Smarkm * these should currently be in reverse preference order.
251872448Sassar * (only relevant for !F_PSEUDO) */
251955682Smarkm
252078536Sassarstatic struct encryption_type enctype_null = {
252178536Sassar    ETYPE_NULL,
252278536Sassar    "null",
2523178828Sdfr    NULL,
252478536Sassar    1,
2525120948Snectar    1,
252678536Sassar    0,
252778536Sassar    &keytype_null,
252878536Sassar    &checksum_none,
252978536Sassar    NULL,
2530178828Sdfr    F_DISABLED,
2531178828Sdfr    NULL_encrypt,
253278536Sassar    0,
2533178828Sdfr    NULL
253455682Smarkm};
253578536Sassarstatic struct encryption_type enctype_des_cbc_crc = {
253678536Sassar    ETYPE_DES_CBC_CRC,
253778536Sassar    "des-cbc-crc",
2538178828Sdfr    NULL,
253978536Sassar    8,
254078536Sassar    8,
2541120948Snectar    8,
254278536Sassar    &keytype_des,
254378536Sassar    &checksum_crc32,
254478536Sassar    NULL,
254578536Sassar    0,
254678536Sassar    DES_CBC_encrypt_key_ivec,
2547178828Sdfr    0,
2548178828Sdfr    NULL
254978536Sassar};
255078536Sassarstatic struct encryption_type enctype_des_cbc_md4 = {
255178536Sassar    ETYPE_DES_CBC_MD4,
255278536Sassar    "des-cbc-md4",
2553178828Sdfr    NULL,
255478536Sassar    8,
255578536Sassar    8,
2556120948Snectar    8,
255778536Sassar    &keytype_des,
255878536Sassar    &checksum_rsa_md4,
255978536Sassar    &checksum_rsa_md4_des,
256078536Sassar    0,
256178536Sassar    DES_CBC_encrypt_null_ivec,
2562178828Sdfr    0,
2563178828Sdfr    NULL
256478536Sassar};
256578536Sassarstatic struct encryption_type enctype_des_cbc_md5 = {
256678536Sassar    ETYPE_DES_CBC_MD5,
256778536Sassar    "des-cbc-md5",
2568178828Sdfr    NULL,
256978536Sassar    8,
257078536Sassar    8,
2571120948Snectar    8,
257278536Sassar    &keytype_des,
257378536Sassar    &checksum_rsa_md5,
257478536Sassar    &checksum_rsa_md5_des,
257578536Sassar    0,
257678536Sassar    DES_CBC_encrypt_null_ivec,
2577178828Sdfr    0,
2578178828Sdfr    NULL
257978536Sassar};
258078536Sassarstatic struct encryption_type enctype_arcfour_hmac_md5 = {
258178536Sassar    ETYPE_ARCFOUR_HMAC_MD5,
258278536Sassar    "arcfour-hmac-md5",
2583178828Sdfr    NULL,
258478536Sassar    1,
2585120948Snectar    1,
258678536Sassar    8,
258778536Sassar    &keytype_arcfour,
258890929Snectar    &checksum_hmac_md5,
2589178828Sdfr    NULL,
259078536Sassar    F_SPECIAL,
2591178828Sdfr    ARCFOUR_encrypt,
2592178828Sdfr    0,
2593178828Sdfr    NULL
259478536Sassar};
259578536Sassarstatic struct encryption_type enctype_des3_cbc_md5 = {
259678536Sassar    ETYPE_DES3_CBC_MD5,
259778536Sassar    "des3-cbc-md5",
2598178828Sdfr    NULL,
259978536Sassar    8,
260078536Sassar    8,
2601120948Snectar    8,
260278536Sassar    &keytype_des3,
260378536Sassar    &checksum_rsa_md5,
260478536Sassar    &checksum_rsa_md5_des3,
260578536Sassar    0,
260678536Sassar    DES3_CBC_encrypt,
2607178828Sdfr    0,
2608178828Sdfr    NULL
260978536Sassar};
261078536Sassarstatic struct encryption_type enctype_des3_cbc_sha1 = {
261178536Sassar    ETYPE_DES3_CBC_SHA1,
261278536Sassar    "des3-cbc-sha1",
2613178828Sdfr    NULL,
261478536Sassar    8,
261578536Sassar    8,
2616120948Snectar    8,
261778536Sassar    &keytype_des3_derived,
261878536Sassar    &checksum_sha1,
261978536Sassar    &checksum_hmac_sha1_des3,
262078536Sassar    F_DERIVED,
262178536Sassar    DES3_CBC_encrypt,
2622178828Sdfr    0,
2623178828Sdfr    NULL
262478536Sassar};
262578536Sassarstatic struct encryption_type enctype_old_des3_cbc_sha1 = {
262678536Sassar    ETYPE_OLD_DES3_CBC_SHA1,
262778536Sassar    "old-des3-cbc-sha1",
2628178828Sdfr    NULL,
262978536Sassar    8,
263078536Sassar    8,
2631120948Snectar    8,
263278536Sassar    &keytype_des3,
263378536Sassar    &checksum_sha1,
263478536Sassar    &checksum_hmac_sha1_des3,
263578536Sassar    0,
263678536Sassar    DES3_CBC_encrypt,
2637178828Sdfr    0,
2638178828Sdfr    NULL
263978536Sassar};
2640120948Snectarstatic struct encryption_type enctype_aes128_cts_hmac_sha1 = {
2641120948Snectar    ETYPE_AES128_CTS_HMAC_SHA1_96,
2642120948Snectar    "aes128-cts-hmac-sha1-96",
2643178828Sdfr    NULL,
2644120948Snectar    16,
2645120948Snectar    1,
2646120948Snectar    16,
2647120948Snectar    &keytype_aes128,
2648120948Snectar    &checksum_sha1,
2649120948Snectar    &checksum_hmac_sha1_aes128,
2650178828Sdfr    F_DERIVED,
2651120948Snectar    AES_CTS_encrypt,
2652178828Sdfr    16,
2653178828Sdfr    AES_PRF
2654120948Snectar};
2655120948Snectarstatic struct encryption_type enctype_aes256_cts_hmac_sha1 = {
2656120948Snectar    ETYPE_AES256_CTS_HMAC_SHA1_96,
2657120948Snectar    "aes256-cts-hmac-sha1-96",
2658178828Sdfr    NULL,
2659120948Snectar    16,
2660120948Snectar    1,
2661120948Snectar    16,
2662120948Snectar    &keytype_aes256,
2663120948Snectar    &checksum_sha1,
2664120948Snectar    &checksum_hmac_sha1_aes256,
2665178828Sdfr    F_DERIVED,
2666120948Snectar    AES_CTS_encrypt,
2667178828Sdfr    16,
2668178828Sdfr    AES_PRF
2669120948Snectar};
267078536Sassarstatic struct encryption_type enctype_des_cbc_none = {
267178536Sassar    ETYPE_DES_CBC_NONE,
267278536Sassar    "des-cbc-none",
2673178828Sdfr    NULL,
267478536Sassar    8,
2675120948Snectar    8,
267678536Sassar    0,
267778536Sassar    &keytype_des,
267878536Sassar    &checksum_none,
267978536Sassar    NULL,
268078536Sassar    F_PSEUDO,
268178536Sassar    DES_CBC_encrypt_null_ivec,
2682178828Sdfr    0,
2683178828Sdfr    NULL
268478536Sassar};
268578536Sassarstatic struct encryption_type enctype_des_cfb64_none = {
268678536Sassar    ETYPE_DES_CFB64_NONE,
268778536Sassar    "des-cfb64-none",
2688178828Sdfr    NULL,
268978536Sassar    1,
2690120948Snectar    1,
269178536Sassar    0,
269278536Sassar    &keytype_des,
269378536Sassar    &checksum_none,
269478536Sassar    NULL,
269578536Sassar    F_PSEUDO,
269678536Sassar    DES_CFB64_encrypt_null_ivec,
2697178828Sdfr    0,
2698178828Sdfr    NULL
269978536Sassar};
270078536Sassarstatic struct encryption_type enctype_des_pcbc_none = {
270178536Sassar    ETYPE_DES_PCBC_NONE,
270278536Sassar    "des-pcbc-none",
2703178828Sdfr    NULL,
270478536Sassar    8,
2705120948Snectar    8,
270678536Sassar    0,
270778536Sassar    &keytype_des,
270878536Sassar    &checksum_none,
270978536Sassar    NULL,
271078536Sassar    F_PSEUDO,
271178536Sassar    DES_PCBC_encrypt_key_ivec,
2712178828Sdfr    0,
2713178828Sdfr    NULL
271478536Sassar};
271578536Sassarstatic struct encryption_type enctype_des3_cbc_none = {
271678536Sassar    ETYPE_DES3_CBC_NONE,
271778536Sassar    "des3-cbc-none",
2718178828Sdfr    NULL,
271978536Sassar    8,
2720120948Snectar    8,
272178536Sassar    0,
272278536Sassar    &keytype_des3_derived,
272378536Sassar    &checksum_none,
272478536Sassar    NULL,
272578536Sassar    F_PSEUDO,
272678536Sassar    DES3_CBC_encrypt,
2727178828Sdfr    0,
2728178828Sdfr    NULL
272978536Sassar};
273055682Smarkm
273178536Sassarstatic struct encryption_type *etypes[] = {
273278536Sassar    &enctype_null,
273378536Sassar    &enctype_des_cbc_crc,
273478536Sassar    &enctype_des_cbc_md4,
273578536Sassar    &enctype_des_cbc_md5,
273678536Sassar    &enctype_arcfour_hmac_md5,
273778536Sassar    &enctype_des3_cbc_md5,
273878536Sassar    &enctype_des3_cbc_sha1,
273978536Sassar    &enctype_old_des3_cbc_sha1,
2740120948Snectar    &enctype_aes128_cts_hmac_sha1,
2741120948Snectar    &enctype_aes256_cts_hmac_sha1,
274278536Sassar    &enctype_des_cbc_none,
274378536Sassar    &enctype_des_cfb64_none,
274478536Sassar    &enctype_des_pcbc_none,
2745103426Snectar    &enctype_des3_cbc_none
274678536Sassar};
274778536Sassar
274855682Smarkmstatic unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
274955682Smarkm
275055682Smarkm
275155682Smarkmstatic struct encryption_type *
275255682Smarkm_find_enctype(krb5_enctype type)
275355682Smarkm{
275455682Smarkm    int i;
275555682Smarkm    for(i = 0; i < num_etypes; i++)
275678536Sassar	if(etypes[i]->type == type)
275778536Sassar	    return etypes[i];
275855682Smarkm    return NULL;
275955682Smarkm}
276055682Smarkm
276155682Smarkm
2762178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
276355682Smarkmkrb5_enctype_to_string(krb5_context context,
276455682Smarkm		       krb5_enctype etype,
276555682Smarkm		       char **string)
276655682Smarkm{
276755682Smarkm    struct encryption_type *e;
276855682Smarkm    e = _find_enctype(etype);
276978536Sassar    if(e == NULL) {
277078536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
277178536Sassar			       etype);
2772178828Sdfr	*string = NULL;
277355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
277478536Sassar    }
277555682Smarkm    *string = strdup(e->name);
277678536Sassar    if(*string == NULL) {
277778536Sassar	krb5_set_error_string(context, "malloc: out of memory");
277855682Smarkm	return ENOMEM;
277978536Sassar    }
278055682Smarkm    return 0;
278155682Smarkm}
278255682Smarkm
2783178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
278455682Smarkmkrb5_string_to_enctype(krb5_context context,
278555682Smarkm		       const char *string,
278655682Smarkm		       krb5_enctype *etype)
278755682Smarkm{
278855682Smarkm    int i;
278955682Smarkm    for(i = 0; i < num_etypes; i++)
279078536Sassar	if(strcasecmp(etypes[i]->name, string) == 0){
279178536Sassar	    *etype = etypes[i]->type;
279255682Smarkm	    return 0;
279355682Smarkm	}
279478536Sassar    krb5_set_error_string (context, "encryption type %s not supported",
279578536Sassar			   string);
279655682Smarkm    return KRB5_PROG_ETYPE_NOSUPP;
279755682Smarkm}
279855682Smarkm
2799178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
2800178828Sdfr_krb5_enctype_to_oid(krb5_context context,
2801178828Sdfr		    krb5_enctype etype,
2802178828Sdfr		    heim_oid *oid)
2803178828Sdfr{
2804178828Sdfr    struct encryption_type *et = _find_enctype(etype);
2805178828Sdfr    if(et == NULL) {
2806178828Sdfr	krb5_set_error_string (context, "encryption type %d not supported",
2807178828Sdfr			       etype);
2808178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
2809178828Sdfr    }
2810178828Sdfr    if(et->oid == NULL) {
2811178828Sdfr	krb5_set_error_string (context, "%s have not oid", et->name);
2812178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
2813178828Sdfr    }
2814178828Sdfr    krb5_clear_error_string(context);
2815178828Sdfr    return der_copy_oid(et->oid, oid);
2816178828Sdfr}
2817178828Sdfr
2818178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
2819178828Sdfr_krb5_oid_to_enctype(krb5_context context,
2820178828Sdfr		     const heim_oid *oid,
2821178828Sdfr		     krb5_enctype *etype)
2822178828Sdfr{
2823178828Sdfr    int i;
2824178828Sdfr    for(i = 0; i < num_etypes; i++) {
2825178828Sdfr	if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) {
2826178828Sdfr	    *etype = etypes[i]->type;
2827178828Sdfr	    return 0;
2828178828Sdfr	}
2829178828Sdfr    }
2830178828Sdfr    krb5_set_error_string(context, "enctype for oid not supported");
2831178828Sdfr    return KRB5_PROG_ETYPE_NOSUPP;
2832178828Sdfr}
2833178828Sdfr
2834178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
283555682Smarkmkrb5_enctype_to_keytype(krb5_context context,
283655682Smarkm			krb5_enctype etype,
283755682Smarkm			krb5_keytype *keytype)
283855682Smarkm{
283955682Smarkm    struct encryption_type *e = _find_enctype(etype);
284078536Sassar    if(e == NULL) {
284178536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
284278536Sassar			       etype);
284355682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
284478536Sassar    }
284555682Smarkm    *keytype = e->keytype->type; /* XXX */
284655682Smarkm    return 0;
284755682Smarkm}
284855682Smarkm
284955682Smarkm#if 0
2850178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
285155682Smarkmkrb5_keytype_to_enctype(krb5_context context,
285255682Smarkm			krb5_keytype keytype,
285355682Smarkm			krb5_enctype *etype)
285455682Smarkm{
285555682Smarkm    struct key_type *kt = _find_keytype(keytype);
285655682Smarkm    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
285755682Smarkm    if(kt == NULL)
285855682Smarkm	return KRB5_PROG_KEYTYPE_NOSUPP;
285955682Smarkm    *etype = kt->best_etype;
286055682Smarkm    return 0;
286155682Smarkm}
286255682Smarkm#endif
286355682Smarkm
2864178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
286555682Smarkmkrb5_keytype_to_enctypes (krb5_context context,
286655682Smarkm			  krb5_keytype keytype,
286755682Smarkm			  unsigned *len,
286890929Snectar			  krb5_enctype **val)
286955682Smarkm{
287055682Smarkm    int i;
287155682Smarkm    unsigned n = 0;
287290929Snectar    krb5_enctype *ret;
287355682Smarkm
287455682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
287578536Sassar	if (etypes[i]->keytype->type == keytype
287678536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
287755682Smarkm	    ++n;
287855682Smarkm    }
287990929Snectar    ret = malloc(n * sizeof(*ret));
288078536Sassar    if (ret == NULL && n != 0) {
288178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
288255682Smarkm	return ENOMEM;
288378536Sassar    }
288455682Smarkm    n = 0;
288555682Smarkm    for (i = num_etypes - 1; i >= 0; --i) {
288678536Sassar	if (etypes[i]->keytype->type == keytype
288778536Sassar	    && !(etypes[i]->flags & F_PSEUDO))
288878536Sassar	    ret[n++] = etypes[i]->type;
288955682Smarkm    }
289055682Smarkm    *len = n;
289155682Smarkm    *val = ret;
289255682Smarkm    return 0;
289355682Smarkm}
289455682Smarkm
289555682Smarkm/*
289655682Smarkm * First take the configured list of etypes for `keytype' if available,
289755682Smarkm * else, do `krb5_keytype_to_enctypes'.
289855682Smarkm */
289955682Smarkm
2900178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
290155682Smarkmkrb5_keytype_to_enctypes_default (krb5_context context,
290255682Smarkm				  krb5_keytype keytype,
290355682Smarkm				  unsigned *len,
290490929Snectar				  krb5_enctype **val)
290555682Smarkm{
290655682Smarkm    int i, n;
290790929Snectar    krb5_enctype *ret;
290855682Smarkm
290955682Smarkm    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
291055682Smarkm	return krb5_keytype_to_enctypes (context, keytype, len, val);
291155682Smarkm
291255682Smarkm    for (n = 0; context->etypes_des[n]; ++n)
291355682Smarkm	;
291455682Smarkm    ret = malloc (n * sizeof(*ret));
291578536Sassar    if (ret == NULL && n != 0) {
291678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
291755682Smarkm	return ENOMEM;
291878536Sassar    }
291955682Smarkm    for (i = 0; i < n; ++i)
292055682Smarkm	ret[i] = context->etypes_des[i];
292155682Smarkm    *len = n;
292255682Smarkm    *val = ret;
292355682Smarkm    return 0;
292455682Smarkm}
292555682Smarkm
2926178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
292755682Smarkmkrb5_enctype_valid(krb5_context context,
292855682Smarkm		 krb5_enctype etype)
292955682Smarkm{
2930178828Sdfr    struct encryption_type *e = _find_enctype(etype);
2931178828Sdfr    if(e == NULL) {
2932178828Sdfr	krb5_set_error_string (context, "encryption type %d not supported",
2933178828Sdfr			       etype);
2934178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
2935178828Sdfr    }
2936178828Sdfr    if (e->flags & F_DISABLED) {
2937178828Sdfr	krb5_set_error_string (context, "encryption type %s is disabled",
2938178828Sdfr			       e->name);
2939178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
2940178828Sdfr    }
2941178828Sdfr    return 0;
294255682Smarkm}
294355682Smarkm
2944178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
2945178828Sdfrkrb5_cksumtype_valid(krb5_context context,
2946178828Sdfr		     krb5_cksumtype ctype)
2947178828Sdfr{
2948178828Sdfr    struct checksum_type *c = _find_checksum(ctype);
2949178828Sdfr    if (c == NULL) {
2950178828Sdfr	krb5_set_error_string (context, "checksum type %d not supported",
2951178828Sdfr			       ctype);
2952178828Sdfr	return KRB5_PROG_SUMTYPE_NOSUPP;
2953178828Sdfr    }
2954178828Sdfr    if (c->flags & F_DISABLED) {
2955178828Sdfr	krb5_set_error_string (context, "checksum type %s is disabled",
2956178828Sdfr			       c->name);
2957178828Sdfr	return KRB5_PROG_SUMTYPE_NOSUPP;
2958178828Sdfr    }
2959178828Sdfr    return 0;
2960178828Sdfr}
2961178828Sdfr
2962178828Sdfr
296355682Smarkm/* if two enctypes have compatible keys */
2964178828Sdfrkrb5_boolean KRB5_LIB_FUNCTION
296555682Smarkmkrb5_enctypes_compatible_keys(krb5_context context,
296655682Smarkm			      krb5_enctype etype1,
296755682Smarkm			      krb5_enctype etype2)
296855682Smarkm{
296955682Smarkm    struct encryption_type *e1 = _find_enctype(etype1);
297055682Smarkm    struct encryption_type *e2 = _find_enctype(etype2);
297155682Smarkm    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
297255682Smarkm}
297355682Smarkm
297455682Smarkmstatic krb5_boolean
297555682Smarkmderived_crypto(krb5_context context,
297655682Smarkm	       krb5_crypto crypto)
297755682Smarkm{
297855682Smarkm    return (crypto->et->flags & F_DERIVED) != 0;
297955682Smarkm}
298055682Smarkm
298172448Sassarstatic krb5_boolean
298272448Sassarspecial_crypto(krb5_context context,
298372448Sassar	       krb5_crypto crypto)
298472448Sassar{
298572448Sassar    return (crypto->et->flags & F_SPECIAL) != 0;
298672448Sassar}
298755682Smarkm
298855682Smarkm#define CHECKSUMSIZE(C) ((C)->checksumsize)
298955682Smarkm#define CHECKSUMTYPE(C) ((C)->type)
299055682Smarkm
299155682Smarkmstatic krb5_error_code
299255682Smarkmencrypt_internal_derived(krb5_context context,
299355682Smarkm			 krb5_crypto crypto,
299455682Smarkm			 unsigned usage,
2995178828Sdfr			 const void *data,
299655682Smarkm			 size_t len,
299772448Sassar			 krb5_data *result,
299872448Sassar			 void *ivec)
299955682Smarkm{
300090929Snectar    size_t sz, block_sz, checksum_sz, total_sz;
300155682Smarkm    Checksum cksum;
300255682Smarkm    unsigned char *p, *q;
300355682Smarkm    krb5_error_code ret;
300455682Smarkm    struct key_data *dkey;
300590929Snectar    const struct encryption_type *et = crypto->et;
300655682Smarkm
300755682Smarkm    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
300855682Smarkm
300990929Snectar    sz = et->confoundersize + len;
3010120948Snectar    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
301190929Snectar    total_sz = block_sz + checksum_sz;
301290929Snectar    p = calloc(1, total_sz);
301390929Snectar    if(p == NULL) {
301490929Snectar	krb5_set_error_string(context, "malloc: out of memory");
301555682Smarkm	return ENOMEM;
301690929Snectar    }
301755682Smarkm
301855682Smarkm    q = p;
301955682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
302055682Smarkm    q += et->confoundersize;
302155682Smarkm    memcpy(q, data, len);
302255682Smarkm
302355682Smarkm    ret = create_checksum(context,
3024127811Snectar			  et->keyed_checksum,
302555682Smarkm			  crypto,
302655682Smarkm			  INTEGRITY_USAGE(usage),
302755682Smarkm			  p,
302855682Smarkm			  block_sz,
302955682Smarkm			  &cksum);
303072448Sassar    if(ret == 0 && cksum.checksum.length != checksum_sz) {
303172448Sassar	free_Checksum (&cksum);
303278536Sassar	krb5_clear_error_string (context);
303372448Sassar	ret = KRB5_CRYPTO_INTERNAL;
303472448Sassar    }
303590929Snectar    if(ret)
303690929Snectar	goto fail;
303755682Smarkm    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
303872448Sassar    free_Checksum (&cksum);
303955682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
304090929Snectar    if(ret)
304190929Snectar	goto fail;
304255682Smarkm    ret = _key_schedule(context, dkey);
304390929Snectar    if(ret)
304490929Snectar	goto fail;
304555682Smarkm#ifdef CRYPTO_DEBUG
304655682Smarkm    krb5_crypto_debug(context, 1, block_sz, dkey->key);
304755682Smarkm#endif
304890929Snectar    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
304990929Snectar    if (ret)
305090929Snectar	goto fail;
305155682Smarkm    result->data = p;
305290929Snectar    result->length = total_sz;
305355682Smarkm    return 0;
305490929Snectar fail:
305590929Snectar    memset(p, 0, total_sz);
305690929Snectar    free(p);
305790929Snectar    return ret;
305855682Smarkm}
305955682Smarkm
306090929Snectar
306155682Smarkmstatic krb5_error_code
306255682Smarkmencrypt_internal(krb5_context context,
306355682Smarkm		 krb5_crypto crypto,
3064178828Sdfr		 const void *data,
306555682Smarkm		 size_t len,
306672448Sassar		 krb5_data *result,
306772448Sassar		 void *ivec)
306855682Smarkm{
306955682Smarkm    size_t sz, block_sz, checksum_sz;
307055682Smarkm    Checksum cksum;
307155682Smarkm    unsigned char *p, *q;
307255682Smarkm    krb5_error_code ret;
307390929Snectar    const struct encryption_type *et = crypto->et;
307455682Smarkm
307578536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
307655682Smarkm
307755682Smarkm    sz = et->confoundersize + checksum_sz + len;
3078120948Snectar    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
307955682Smarkm    p = calloc(1, block_sz);
308078536Sassar    if(p == NULL) {
308178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
308255682Smarkm	return ENOMEM;
308378536Sassar    }
308455682Smarkm
308555682Smarkm    q = p;
308655682Smarkm    krb5_generate_random_block(q, et->confoundersize); /* XXX */
308755682Smarkm    q += et->confoundersize;
308855682Smarkm    memset(q, 0, checksum_sz);
308955682Smarkm    q += checksum_sz;
309055682Smarkm    memcpy(q, data, len);
309155682Smarkm
309255682Smarkm    ret = create_checksum(context,
3093127811Snectar			  et->checksum,
309478536Sassar			  crypto,
309555682Smarkm			  0,
309655682Smarkm			  p,
309755682Smarkm			  block_sz,
309855682Smarkm			  &cksum);
309955682Smarkm    if(ret == 0 && cksum.checksum.length != checksum_sz) {
310078536Sassar	krb5_clear_error_string (context);
310190929Snectar	free_Checksum(&cksum);
310255682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
310355682Smarkm    }
310490929Snectar    if(ret)
310590929Snectar	goto fail;
310655682Smarkm    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
310755682Smarkm    free_Checksum(&cksum);
310855682Smarkm    ret = _key_schedule(context, &crypto->key);
310990929Snectar    if(ret)
311090929Snectar	goto fail;
311190929Snectar#ifdef CRYPTO_DEBUG
311290929Snectar    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
311390929Snectar#endif
311490929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
311590929Snectar    if (ret) {
311655682Smarkm	memset(p, 0, block_sz);
311755682Smarkm	free(p);
311855682Smarkm	return ret;
311955682Smarkm    }
312055682Smarkm    result->data = p;
312155682Smarkm    result->length = block_sz;
312255682Smarkm    return 0;
312390929Snectar fail:
312490929Snectar    memset(p, 0, block_sz);
312590929Snectar    free(p);
312690929Snectar    return ret;
312755682Smarkm}
312855682Smarkm
312955682Smarkmstatic krb5_error_code
313072448Sassarencrypt_internal_special(krb5_context context,
313172448Sassar			 krb5_crypto crypto,
313272448Sassar			 int usage,
3133178828Sdfr			 const void *data,
313472448Sassar			 size_t len,
313572448Sassar			 krb5_data *result,
313672448Sassar			 void *ivec)
313772448Sassar{
313872448Sassar    struct encryption_type *et = crypto->et;
313978536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
314072448Sassar    size_t sz = len + cksum_sz + et->confoundersize;
314172448Sassar    char *tmp, *p;
314290929Snectar    krb5_error_code ret;
314372448Sassar
314472448Sassar    tmp = malloc (sz);
314578536Sassar    if (tmp == NULL) {
314678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
314772448Sassar	return ENOMEM;
314878536Sassar    }
314972448Sassar    p = tmp;
315072448Sassar    memset (p, 0, cksum_sz);
315172448Sassar    p += cksum_sz;
315272448Sassar    krb5_generate_random_block(p, et->confoundersize);
315372448Sassar    p += et->confoundersize;
315472448Sassar    memcpy (p, data, len);
315590929Snectar    ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
315690929Snectar    if (ret) {
315790929Snectar	memset(tmp, 0, sz);
315890929Snectar	free(tmp);
315990929Snectar	return ret;
316090929Snectar    }
316172448Sassar    result->data   = tmp;
316272448Sassar    result->length = sz;
316372448Sassar    return 0;
316472448Sassar}
316572448Sassar
316672448Sassarstatic krb5_error_code
316755682Smarkmdecrypt_internal_derived(krb5_context context,
316855682Smarkm			 krb5_crypto crypto,
316955682Smarkm			 unsigned usage,
317055682Smarkm			 void *data,
317155682Smarkm			 size_t len,
317272448Sassar			 krb5_data *result,
317372448Sassar			 void *ivec)
317455682Smarkm{
317555682Smarkm    size_t checksum_sz;
317655682Smarkm    Checksum cksum;
317755682Smarkm    unsigned char *p;
317855682Smarkm    krb5_error_code ret;
317955682Smarkm    struct key_data *dkey;
318055682Smarkm    struct encryption_type *et = crypto->et;
318155682Smarkm    unsigned long l;
318255682Smarkm
318372448Sassar    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
3184178828Sdfr    if (len < checksum_sz + et->confoundersize) {
3185178828Sdfr	krb5_set_error_string(context, "Encrypted data shorter then "
3186178828Sdfr			      "checksum + confunder");
3187178828Sdfr	return KRB5_BAD_MSIZE;
318878536Sassar    }
318972448Sassar
3190127811Snectar    if (((len - checksum_sz) % et->padsize) != 0) {
3191127811Snectar	krb5_clear_error_string(context);
3192127811Snectar	return KRB5_BAD_MSIZE;
3193127811Snectar    }
3194127811Snectar
319555682Smarkm    p = malloc(len);
319678536Sassar    if(len != 0 && p == NULL) {
319778536Sassar	krb5_set_error_string(context, "malloc: out of memory");
319855682Smarkm	return ENOMEM;
319978536Sassar    }
320055682Smarkm    memcpy(p, data, len);
320155682Smarkm
320255682Smarkm    len -= checksum_sz;
320355682Smarkm
320455682Smarkm    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
320555682Smarkm    if(ret) {
320655682Smarkm	free(p);
320755682Smarkm	return ret;
320855682Smarkm    }
320955682Smarkm    ret = _key_schedule(context, dkey);
321055682Smarkm    if(ret) {
321155682Smarkm	free(p);
321255682Smarkm	return ret;
321355682Smarkm    }
321455682Smarkm#ifdef CRYPTO_DEBUG
321555682Smarkm    krb5_crypto_debug(context, 0, len, dkey->key);
321655682Smarkm#endif
321790929Snectar    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
321890929Snectar    if (ret) {
321990929Snectar	free(p);
322090929Snectar	return ret;
322190929Snectar    }
322255682Smarkm
322355682Smarkm    cksum.checksum.data   = p + len;
322455682Smarkm    cksum.checksum.length = checksum_sz;
322555682Smarkm    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
322655682Smarkm
322755682Smarkm    ret = verify_checksum(context,
322855682Smarkm			  crypto,
322955682Smarkm			  INTEGRITY_USAGE(usage),
323055682Smarkm			  p,
323155682Smarkm			  len,
323255682Smarkm			  &cksum);
323355682Smarkm    if(ret) {
323455682Smarkm	free(p);
323555682Smarkm	return ret;
323655682Smarkm    }
323755682Smarkm    l = len - et->confoundersize;
323855682Smarkm    memmove(p, p + et->confoundersize, l);
323955682Smarkm    result->data = realloc(p, l);
3240178828Sdfr    if(result->data == NULL && l != 0) {
324155682Smarkm	free(p);
324278536Sassar	krb5_set_error_string(context, "malloc: out of memory");
324355682Smarkm	return ENOMEM;
324455682Smarkm    }
324555682Smarkm    result->length = l;
324655682Smarkm    return 0;
324755682Smarkm}
324855682Smarkm
324955682Smarkmstatic krb5_error_code
325055682Smarkmdecrypt_internal(krb5_context context,
325155682Smarkm		 krb5_crypto crypto,
325255682Smarkm		 void *data,
325355682Smarkm		 size_t len,
325472448Sassar		 krb5_data *result,
325572448Sassar		 void *ivec)
325655682Smarkm{
325755682Smarkm    krb5_error_code ret;
325855682Smarkm    unsigned char *p;
325955682Smarkm    Checksum cksum;
326055682Smarkm    size_t checksum_sz, l;
326155682Smarkm    struct encryption_type *et = crypto->et;
326255682Smarkm
3263127811Snectar    if ((len % et->padsize) != 0) {
3264127811Snectar	krb5_clear_error_string(context);
3265127811Snectar	return KRB5_BAD_MSIZE;
3266127811Snectar    }
3267127811Snectar
326878536Sassar    checksum_sz = CHECKSUMSIZE(et->checksum);
326955682Smarkm    p = malloc(len);
327078536Sassar    if(len != 0 && p == NULL) {
327178536Sassar	krb5_set_error_string(context, "malloc: out of memory");
327255682Smarkm	return ENOMEM;
327378536Sassar    }
327455682Smarkm    memcpy(p, data, len);
327555682Smarkm
327655682Smarkm    ret = _key_schedule(context, &crypto->key);
327755682Smarkm    if(ret) {
327855682Smarkm	free(p);
327955682Smarkm	return ret;
328055682Smarkm    }
328155682Smarkm#ifdef CRYPTO_DEBUG
328255682Smarkm    krb5_crypto_debug(context, 0, len, crypto->key.key);
328355682Smarkm#endif
328490929Snectar    ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
328590929Snectar    if (ret) {
328690929Snectar	free(p);
328790929Snectar	return ret;
328890929Snectar    }
328955682Smarkm    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
329055682Smarkm    if(ret) {
329172448Sassar 	free(p);
329272448Sassar 	return ret;
329355682Smarkm    }
329455682Smarkm    memset(p + et->confoundersize, 0, checksum_sz);
329578536Sassar    cksum.cksumtype = CHECKSUMTYPE(et->checksum);
329655682Smarkm    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
329755682Smarkm    free_Checksum(&cksum);
329855682Smarkm    if(ret) {
329955682Smarkm	free(p);
330055682Smarkm	return ret;
330155682Smarkm    }
330255682Smarkm    l = len - et->confoundersize - checksum_sz;
330355682Smarkm    memmove(p, p + et->confoundersize + checksum_sz, l);
330455682Smarkm    result->data = realloc(p, l);
3305178828Sdfr    if(result->data == NULL && l != 0) {
330655682Smarkm	free(p);
330778536Sassar	krb5_set_error_string(context, "malloc: out of memory");
330855682Smarkm	return ENOMEM;
330955682Smarkm    }
331055682Smarkm    result->length = l;
331155682Smarkm    return 0;
331255682Smarkm}
331355682Smarkm
331472448Sassarstatic krb5_error_code
331572448Sassardecrypt_internal_special(krb5_context context,
331672448Sassar			 krb5_crypto crypto,
331772448Sassar			 int usage,
331872448Sassar			 void *data,
331972448Sassar			 size_t len,
332072448Sassar			 krb5_data *result,
332172448Sassar			 void *ivec)
332272448Sassar{
332372448Sassar    struct encryption_type *et = crypto->et;
332478536Sassar    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
332572448Sassar    size_t sz = len - cksum_sz - et->confoundersize;
3326127811Snectar    unsigned char *p;
332790929Snectar    krb5_error_code ret;
332872448Sassar
3329127811Snectar    if ((len % et->padsize) != 0) {
3330127811Snectar	krb5_clear_error_string(context);
3331127811Snectar	return KRB5_BAD_MSIZE;
3332127811Snectar    }
3333127811Snectar
3334127811Snectar    p = malloc (len);
3335127811Snectar    if (p == NULL) {
333678536Sassar	krb5_set_error_string(context, "malloc: out of memory");
333772448Sassar	return ENOMEM;
333878536Sassar    }
3339127811Snectar    memcpy(p, data, len);
334072448Sassar
3341127811Snectar    ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
334290929Snectar    if (ret) {
3343127811Snectar	free(p);
334490929Snectar	return ret;
334590929Snectar    }
334672448Sassar
3347127811Snectar    memmove (p, p + cksum_sz + et->confoundersize, sz);
3348127811Snectar    result->data = realloc(p, sz);
3349178828Sdfr    if(result->data == NULL && sz != 0) {
3350127811Snectar	free(p);
3351127811Snectar	krb5_set_error_string(context, "malloc: out of memory");
3352127811Snectar	return ENOMEM;
3353127811Snectar    }
335472448Sassar    result->length = sz;
335572448Sassar    return 0;
335672448Sassar}
335772448Sassar
335872448Sassar
3359178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
336072448Sassarkrb5_encrypt_ivec(krb5_context context,
336172448Sassar		  krb5_crypto crypto,
336272448Sassar		  unsigned usage,
3363178828Sdfr		  const void *data,
336472448Sassar		  size_t len,
336572448Sassar		  krb5_data *result,
336672448Sassar		  void *ivec)
336772448Sassar{
336872448Sassar    if(derived_crypto(context, crypto))
336972448Sassar	return encrypt_internal_derived(context, crypto, usage,
337072448Sassar					data, len, result, ivec);
337172448Sassar    else if (special_crypto(context, crypto))
337272448Sassar	return encrypt_internal_special (context, crypto, usage,
337372448Sassar					 data, len, result, ivec);
337472448Sassar    else
337572448Sassar	return encrypt_internal(context, crypto, data, len, result, ivec);
337672448Sassar}
337772448Sassar
3378178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
337955682Smarkmkrb5_encrypt(krb5_context context,
338055682Smarkm	     krb5_crypto crypto,
338155682Smarkm	     unsigned usage,
3382178828Sdfr	     const void *data,
338355682Smarkm	     size_t len,
338455682Smarkm	     krb5_data *result)
338555682Smarkm{
338672448Sassar    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
338755682Smarkm}
338855682Smarkm
3389178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
339055682Smarkmkrb5_encrypt_EncryptedData(krb5_context context,
339155682Smarkm			   krb5_crypto crypto,
339255682Smarkm			   unsigned usage,
339355682Smarkm			   void *data,
339455682Smarkm			   size_t len,
339555682Smarkm			   int kvno,
339655682Smarkm			   EncryptedData *result)
339755682Smarkm{
339855682Smarkm    result->etype = CRYPTO_ETYPE(crypto);
339955682Smarkm    if(kvno){
340055682Smarkm	ALLOC(result->kvno, 1);
340155682Smarkm	*result->kvno = kvno;
340255682Smarkm    }else
340355682Smarkm	result->kvno = NULL;
340455682Smarkm    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
340555682Smarkm}
340655682Smarkm
3407178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
340872448Sassarkrb5_decrypt_ivec(krb5_context context,
340972448Sassar		  krb5_crypto crypto,
341072448Sassar		  unsigned usage,
341172448Sassar		  void *data,
341272448Sassar		  size_t len,
341372448Sassar		  krb5_data *result,
341472448Sassar		  void *ivec)
341572448Sassar{
341672448Sassar    if(derived_crypto(context, crypto))
341772448Sassar	return decrypt_internal_derived(context, crypto, usage,
341872448Sassar					data, len, result, ivec);
341972448Sassar    else if (special_crypto (context, crypto))
342072448Sassar	return decrypt_internal_special(context, crypto, usage,
342172448Sassar					data, len, result, ivec);
342272448Sassar    else
342372448Sassar	return decrypt_internal(context, crypto, data, len, result, ivec);
342472448Sassar}
342572448Sassar
3426178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
342755682Smarkmkrb5_decrypt(krb5_context context,
342855682Smarkm	     krb5_crypto crypto,
342955682Smarkm	     unsigned usage,
343055682Smarkm	     void *data,
343155682Smarkm	     size_t len,
343255682Smarkm	     krb5_data *result)
343355682Smarkm{
343472448Sassar    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
343572448Sassar			      NULL);
343655682Smarkm}
343755682Smarkm
3438178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
343955682Smarkmkrb5_decrypt_EncryptedData(krb5_context context,
344055682Smarkm			   krb5_crypto crypto,
344155682Smarkm			   unsigned usage,
344272448Sassar			   const EncryptedData *e,
344355682Smarkm			   krb5_data *result)
344455682Smarkm{
344555682Smarkm    return krb5_decrypt(context, crypto, usage,
344655682Smarkm			e->cipher.data, e->cipher.length, result);
344755682Smarkm}
344855682Smarkm
344955682Smarkm/************************************************************
345055682Smarkm *                                                          *
345155682Smarkm ************************************************************/
345255682Smarkm
3453178828Sdfr#define ENTROPY_NEEDED 128
345478536Sassar
345578536Sassarstatic int
345678536Sassarseed_something(void)
345778536Sassar{
345878536Sassar    char buf[1024], seedfile[256];
345978536Sassar
346078536Sassar    /* If there is a seed file, load it. But such a file cannot be trusted,
346178536Sassar       so use 0 for the entropy estimate */
346278536Sassar    if (RAND_file_name(seedfile, sizeof(seedfile))) {
3463178828Sdfr	int fd;
346478536Sassar	fd = open(seedfile, O_RDONLY);
346578536Sassar	if (fd >= 0) {
3466178828Sdfr	    ssize_t ret;
3467178828Sdfr	    ret = read(fd, buf, sizeof(buf));
3468178828Sdfr	    if (ret > 0)
3469178828Sdfr		RAND_add(buf, ret, 0.0);
3470178828Sdfr	    close(fd);
347178536Sassar	} else
347278536Sassar	    seedfile[0] = '\0';
347378536Sassar    } else
347478536Sassar	seedfile[0] = '\0';
347578536Sassar
347678536Sassar    /* Calling RAND_status() will try to use /dev/urandom if it exists so
347778536Sassar       we do not have to deal with it. */
347878536Sassar    if (RAND_status() != 1) {
347978536Sassar	krb5_context context;
348090929Snectar	const char *p;
348178536Sassar
348278536Sassar	/* Try using egd */
348378536Sassar	if (!krb5_init_context(&context)) {
348478536Sassar	    p = krb5_config_get_string(context, NULL, "libdefaults",
348578536Sassar		"egd_socket", NULL);
348678536Sassar	    if (p != NULL)
348778536Sassar		RAND_egd_bytes(p, ENTROPY_NEEDED);
348878536Sassar	    krb5_free_context(context);
348978536Sassar	}
349078536Sassar    }
349178536Sassar
349278536Sassar    if (RAND_status() == 1)	{
349378536Sassar	/* Update the seed file */
349478536Sassar	if (seedfile[0])
349578536Sassar	    RAND_write_file(seedfile);
349678536Sassar
349778536Sassar	return 0;
349878536Sassar    } else
349978536Sassar	return -1;
350078536Sassar}
350178536Sassar
3502178828Sdfrvoid KRB5_LIB_FUNCTION
350355682Smarkmkrb5_generate_random_block(void *buf, size_t len)
350455682Smarkm{
350578536Sassar    static int rng_initialized = 0;
350678536Sassar
3507178828Sdfr    HEIMDAL_MUTEX_lock(&crypto_mutex);
350878536Sassar    if (!rng_initialized) {
350978536Sassar	if (seed_something())
3510178828Sdfr	    krb5_abortx(NULL, "Fatal: could not seed the "
3511178828Sdfr			"random number generator");
351278536Sassar
351378536Sassar	rng_initialized = 1;
351478536Sassar    }
3515178828Sdfr    HEIMDAL_MUTEX_unlock(&crypto_mutex);
3516178828Sdfr    if (RAND_bytes(buf, len) != 1)
3517178828Sdfr	krb5_abortx(NULL, "Failed to generate random block");
351878536Sassar}
351978536Sassar
352055682Smarkmstatic void
352155682SmarkmDES3_postproc(krb5_context context,
352255682Smarkm	      unsigned char *k, size_t len, struct key_data *key)
352355682Smarkm{
3524178828Sdfr    DES3_random_to_key(context, key->key, k, len);
352555682Smarkm
352655682Smarkm    if (key->schedule) {
352755682Smarkm	krb5_free_data(context, key->schedule);
352855682Smarkm	key->schedule = NULL;
352955682Smarkm    }
353055682Smarkm}
353155682Smarkm
353255682Smarkmstatic krb5_error_code
353355682Smarkmderive_key(krb5_context context,
353455682Smarkm	   struct encryption_type *et,
353555682Smarkm	   struct key_data *key,
353678536Sassar	   const void *constant,
353755682Smarkm	   size_t len)
353855682Smarkm{
353955682Smarkm    unsigned char *k;
354055682Smarkm    unsigned int nblocks = 0, i;
354155682Smarkm    krb5_error_code ret = 0;
354255682Smarkm    struct key_type *kt = et->keytype;
3543178828Sdfr
354455682Smarkm    ret = _key_schedule(context, key);
354555682Smarkm    if(ret)
354655682Smarkm	return ret;
3547178828Sdfr    if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
354855682Smarkm	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
354955682Smarkm	k = malloc(nblocks * et->blocksize);
355078536Sassar	if(k == NULL) {
355178536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
355255682Smarkm	    return ENOMEM;
355378536Sassar	}
3554178828Sdfr	ret = _krb5_n_fold(constant, len, k, et->blocksize);
3555178828Sdfr	if (ret) {
3556178828Sdfr	    free(k);
3557178828Sdfr	    krb5_set_error_string(context, "out of memory");
3558178828Sdfr	    return ret;
3559178828Sdfr	}
356055682Smarkm	for(i = 0; i < nblocks; i++) {
356155682Smarkm	    if(i > 0)
356255682Smarkm		memcpy(k + i * et->blocksize,
356355682Smarkm		       k + (i - 1) * et->blocksize,
356455682Smarkm		       et->blocksize);
356578536Sassar	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
356678536Sassar			   1, 0, NULL);
356755682Smarkm	}
356855682Smarkm    } else {
356972448Sassar	/* this case is probably broken, but won't be run anyway */
357055682Smarkm	void *c = malloc(len);
357155682Smarkm	size_t res_len = (kt->bits + 7) / 8;
357255682Smarkm
357378536Sassar	if(len != 0 && c == NULL) {
357478536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
357555682Smarkm	    return ENOMEM;
357678536Sassar	}
357755682Smarkm	memcpy(c, constant, len);
357878536Sassar	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
357955682Smarkm	k = malloc(res_len);
358078536Sassar	if(res_len != 0 && k == NULL) {
358178536Sassar	    free(c);
358278536Sassar	    krb5_set_error_string(context, "malloc: out of memory");
358355682Smarkm	    return ENOMEM;
358478536Sassar	}
3585178828Sdfr	ret = _krb5_n_fold(c, len, k, res_len);
3586178828Sdfr	if (ret) {
3587178828Sdfr	    free(k);
3588178828Sdfr	    krb5_set_error_string(context, "out of memory");
3589178828Sdfr	    return ret;
3590178828Sdfr	}
359155682Smarkm	free(c);
359255682Smarkm    }
359355682Smarkm
359455682Smarkm    /* XXX keytype dependent post-processing */
359555682Smarkm    switch(kt->type) {
359655682Smarkm    case KEYTYPE_DES3:
359755682Smarkm	DES3_postproc(context, k, nblocks * et->blocksize, key);
359855682Smarkm	break;
3599120948Snectar    case KEYTYPE_AES128:
3600120948Snectar    case KEYTYPE_AES256:
3601120948Snectar	memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
3602120948Snectar	break;
360355682Smarkm    default:
360478536Sassar	krb5_set_error_string(context,
360578536Sassar			      "derive_key() called with unknown keytype (%u)",
360678536Sassar			      kt->type);
360755682Smarkm	ret = KRB5_CRYPTO_INTERNAL;
360855682Smarkm	break;
360955682Smarkm    }
3610178828Sdfr    if (key->schedule) {
3611178828Sdfr	krb5_free_data(context, key->schedule);
3612178828Sdfr	key->schedule = NULL;
3613178828Sdfr    }
361455682Smarkm    memset(k, 0, nblocks * et->blocksize);
361555682Smarkm    free(k);
361655682Smarkm    return ret;
361755682Smarkm}
361855682Smarkm
361955682Smarkmstatic struct key_data *
362055682Smarkm_new_derived_key(krb5_crypto crypto, unsigned usage)
362155682Smarkm{
362255682Smarkm    struct key_usage *d = crypto->key_usage;
362355682Smarkm    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
362455682Smarkm    if(d == NULL)
362555682Smarkm	return NULL;
362655682Smarkm    crypto->key_usage = d;
362755682Smarkm    d += crypto->num_key_usage++;
362855682Smarkm    memset(d, 0, sizeof(*d));
362955682Smarkm    d->usage = usage;
363055682Smarkm    return &d->key;
363155682Smarkm}
363255682Smarkm
3633178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
363478536Sassarkrb5_derive_key(krb5_context context,
363578536Sassar		const krb5_keyblock *key,
363678536Sassar		krb5_enctype etype,
363778536Sassar		const void *constant,
363878536Sassar		size_t constant_len,
363978536Sassar		krb5_keyblock **derived_key)
364078536Sassar{
364178536Sassar    krb5_error_code ret;
364278536Sassar    struct encryption_type *et;
364378536Sassar    struct key_data d;
364478536Sassar
3645178828Sdfr    *derived_key = NULL;
3646178828Sdfr
364778536Sassar    et = _find_enctype (etype);
364878536Sassar    if (et == NULL) {
364978536Sassar	krb5_set_error_string(context, "encryption type %d not supported",
365078536Sassar			      etype);
365178536Sassar	return KRB5_PROG_ETYPE_NOSUPP;
365278536Sassar    }
365378536Sassar
3654178828Sdfr    ret = krb5_copy_keyblock(context, key, &d.key);
365578536Sassar    if (ret)
365678536Sassar	return ret;
365778536Sassar
365878536Sassar    d.schedule = NULL;
365978536Sassar    ret = derive_key(context, et, &d, constant, constant_len);
3660178828Sdfr    if (ret == 0)
3661178828Sdfr	ret = krb5_copy_keyblock(context, d.key, derived_key);
3662178828Sdfr    free_key_data(context, &d);
366378536Sassar    return ret;
366478536Sassar}
366578536Sassar
366655682Smarkmstatic krb5_error_code
366755682Smarkm_get_derived_key(krb5_context context,
366855682Smarkm		 krb5_crypto crypto,
366955682Smarkm		 unsigned usage,
367055682Smarkm		 struct key_data **key)
367155682Smarkm{
367255682Smarkm    int i;
367355682Smarkm    struct key_data *d;
367455682Smarkm    unsigned char constant[5];
367555682Smarkm
367655682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
367755682Smarkm	if(crypto->key_usage[i].usage == usage) {
367855682Smarkm	    *key = &crypto->key_usage[i].key;
367955682Smarkm	    return 0;
368055682Smarkm	}
368155682Smarkm    d = _new_derived_key(crypto, usage);
368278536Sassar    if(d == NULL) {
368378536Sassar	krb5_set_error_string(context, "malloc: out of memory");
368455682Smarkm	return ENOMEM;
368578536Sassar    }
368655682Smarkm    krb5_copy_keyblock(context, crypto->key.key, &d->key);
368755682Smarkm    _krb5_put_int(constant, usage, 5);
368855682Smarkm    derive_key(context, crypto->et, d, constant, sizeof(constant));
368955682Smarkm    *key = d;
369055682Smarkm    return 0;
369155682Smarkm}
369255682Smarkm
369355682Smarkm
3694178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
369555682Smarkmkrb5_crypto_init(krb5_context context,
369678536Sassar		 const krb5_keyblock *key,
369755682Smarkm		 krb5_enctype etype,
369855682Smarkm		 krb5_crypto *crypto)
369955682Smarkm{
370055682Smarkm    krb5_error_code ret;
370155682Smarkm    ALLOC(*crypto, 1);
370278536Sassar    if(*crypto == NULL) {
370378536Sassar	krb5_set_error_string(context, "malloc: out of memory");
370455682Smarkm	return ENOMEM;
370578536Sassar    }
370655682Smarkm    if(etype == ETYPE_NULL)
370755682Smarkm	etype = key->keytype;
370855682Smarkm    (*crypto)->et = _find_enctype(etype);
3709178828Sdfr    if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
371055682Smarkm	free(*crypto);
3711178828Sdfr	*crypto = NULL;
371278536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
371378536Sassar			       etype);
371455682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
371555682Smarkm    }
3716102647Snectar    if((*crypto)->et->keytype->size != key->keyvalue.length) {
3717102647Snectar	free(*crypto);
3718178828Sdfr	*crypto = NULL;
3719102647Snectar	krb5_set_error_string (context, "encryption key has bad length");
3720102647Snectar	return KRB5_BAD_KEYSIZE;
3721102647Snectar    }
372255682Smarkm    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
372355682Smarkm    if(ret) {
372455682Smarkm	free(*crypto);
3725178828Sdfr	*crypto = NULL;
372655682Smarkm	return ret;
372755682Smarkm    }
372855682Smarkm    (*crypto)->key.schedule = NULL;
372955682Smarkm    (*crypto)->num_key_usage = 0;
373055682Smarkm    (*crypto)->key_usage = NULL;
373155682Smarkm    return 0;
373255682Smarkm}
373355682Smarkm
373455682Smarkmstatic void
373555682Smarkmfree_key_data(krb5_context context, struct key_data *key)
373655682Smarkm{
373755682Smarkm    krb5_free_keyblock(context, key->key);
373855682Smarkm    if(key->schedule) {
373955682Smarkm	memset(key->schedule->data, 0, key->schedule->length);
374055682Smarkm	krb5_free_data(context, key->schedule);
374155682Smarkm    }
374255682Smarkm}
374355682Smarkm
374455682Smarkmstatic void
374555682Smarkmfree_key_usage(krb5_context context, struct key_usage *ku)
374655682Smarkm{
374755682Smarkm    free_key_data(context, &ku->key);
374855682Smarkm}
374955682Smarkm
3750178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
375155682Smarkmkrb5_crypto_destroy(krb5_context context,
375255682Smarkm		    krb5_crypto crypto)
375355682Smarkm{
375455682Smarkm    int i;
375555682Smarkm
375655682Smarkm    for(i = 0; i < crypto->num_key_usage; i++)
375755682Smarkm	free_key_usage(context, &crypto->key_usage[i]);
375855682Smarkm    free(crypto->key_usage);
375955682Smarkm    free_key_data(context, &crypto->key);
376055682Smarkm    free (crypto);
376155682Smarkm    return 0;
376255682Smarkm}
376355682Smarkm
3764178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3765103426Snectarkrb5_crypto_getblocksize(krb5_context context,
3766103426Snectar			 krb5_crypto crypto,
3767103426Snectar			 size_t *blocksize)
3768103426Snectar{
3769103426Snectar    *blocksize = crypto->et->blocksize;
3770103426Snectar    return 0;
3771103426Snectar}
3772103426Snectar
3773178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3774178828Sdfrkrb5_crypto_getenctype(krb5_context context,
3775178828Sdfr		       krb5_crypto crypto,
3776178828Sdfr		       krb5_enctype *enctype)
3777178828Sdfr{
3778178828Sdfr    *enctype = crypto->et->type;
3779178828Sdfr     return 0;
3780178828Sdfr}
3781178828Sdfr
3782178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3783178828Sdfrkrb5_crypto_getpadsize(krb5_context context,
3784178828Sdfr                       krb5_crypto crypto,
3785178828Sdfr                       size_t *padsize)
3786178828Sdfr{
3787178828Sdfr    *padsize = crypto->et->padsize;
3788178828Sdfr    return 0;
3789178828Sdfr}
3790178828Sdfr
3791178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3792178828Sdfrkrb5_crypto_getconfoundersize(krb5_context context,
3793178828Sdfr                              krb5_crypto crypto,
3794178828Sdfr                              size_t *confoundersize)
3795178828Sdfr{
3796178828Sdfr    *confoundersize = crypto->et->confoundersize;
3797178828Sdfr    return 0;
3798178828Sdfr}
3799178828Sdfr
3800178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3801178828Sdfrkrb5_enctype_disable(krb5_context context,
3802178828Sdfr		     krb5_enctype enctype)
3803178828Sdfr{
3804178828Sdfr    struct encryption_type *et = _find_enctype(enctype);
3805178828Sdfr    if(et == NULL) {
3806178828Sdfr	if (context)
3807178828Sdfr	    krb5_set_error_string (context, "encryption type %d not supported",
3808178828Sdfr				   enctype);
3809178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
3810178828Sdfr    }
3811178828Sdfr    et->flags |= F_DISABLED;
3812178828Sdfr    return 0;
3813178828Sdfr}
3814178828Sdfr
3815178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
381655682Smarkmkrb5_string_to_key_derived(krb5_context context,
381755682Smarkm			   const void *str,
381855682Smarkm			   size_t len,
381955682Smarkm			   krb5_enctype etype,
382055682Smarkm			   krb5_keyblock *key)
382155682Smarkm{
382255682Smarkm    struct encryption_type *et = _find_enctype(etype);
382355682Smarkm    krb5_error_code ret;
382455682Smarkm    struct key_data kd;
3825178828Sdfr    size_t keylen;
382655682Smarkm    u_char *tmp;
382755682Smarkm
382878536Sassar    if(et == NULL) {
382978536Sassar	krb5_set_error_string (context, "encryption type %d not supported",
383078536Sassar			       etype);
383155682Smarkm	return KRB5_PROG_ETYPE_NOSUPP;
383278536Sassar    }
3833178828Sdfr    keylen = et->keytype->bits / 8;
3834178828Sdfr
383555682Smarkm    ALLOC(kd.key, 1);
383690929Snectar    if(kd.key == NULL) {
383790929Snectar	krb5_set_error_string (context, "malloc: out of memory");
383890929Snectar	return ENOMEM;
383990929Snectar    }
384090929Snectar    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
384190929Snectar    if(ret) {
384290929Snectar	free(kd.key);
384390929Snectar	return ret;
384490929Snectar    }
384555682Smarkm    kd.key->keytype = etype;
384690929Snectar    tmp = malloc (keylen);
384790929Snectar    if(tmp == NULL) {
384890929Snectar	krb5_free_keyblock(context, kd.key);
384990929Snectar	krb5_set_error_string (context, "malloc: out of memory");
385090929Snectar	return ENOMEM;
385190929Snectar    }
3852178828Sdfr    ret = _krb5_n_fold(str, len, tmp, keylen);
3853178828Sdfr    if (ret) {
3854178828Sdfr	free(tmp);
3855178828Sdfr	krb5_set_error_string(context, "out of memory");
3856178828Sdfr	return ret;
3857178828Sdfr    }
385855682Smarkm    kd.schedule = NULL;
385990929Snectar    DES3_postproc (context, tmp, keylen, &kd); /* XXX */
386090929Snectar    memset(tmp, 0, keylen);
386190929Snectar    free(tmp);
386290929Snectar    ret = derive_key(context,
386355682Smarkm		     et,
386455682Smarkm		     &kd,
386555682Smarkm		     "kerberos", /* XXX well known constant */
386655682Smarkm		     strlen("kerberos"));
386755682Smarkm    ret = krb5_copy_keyblock_contents(context, kd.key, key);
386855682Smarkm    free_key_data(context, &kd);
386955682Smarkm    return ret;
387055682Smarkm}
387155682Smarkm
387272448Sassarstatic size_t
387372448Sassarwrapped_length (krb5_context context,
387472448Sassar		krb5_crypto  crypto,
387572448Sassar		size_t       data_len)
387672448Sassar{
387772448Sassar    struct encryption_type *et = crypto->et;
3878120948Snectar    size_t padsize = et->padsize;
3879178828Sdfr    size_t checksumsize = CHECKSUMSIZE(et->checksum);
388072448Sassar    size_t res;
388172448Sassar
3882178828Sdfr    res =  et->confoundersize + checksumsize + data_len;
3883120948Snectar    res =  (res + padsize - 1) / padsize * padsize;
388472448Sassar    return res;
388572448Sassar}
388672448Sassar
388772448Sassarstatic size_t
388872448Sassarwrapped_length_dervied (krb5_context context,
388972448Sassar			krb5_crypto  crypto,
389072448Sassar			size_t       data_len)
389172448Sassar{
389272448Sassar    struct encryption_type *et = crypto->et;
3893120948Snectar    size_t padsize = et->padsize;
389472448Sassar    size_t res;
389572448Sassar
389672448Sassar    res =  et->confoundersize + data_len;
3897120948Snectar    res =  (res + padsize - 1) / padsize * padsize;
3898178828Sdfr    if (et->keyed_checksum)
3899178828Sdfr	res += et->keyed_checksum->checksumsize;
3900178828Sdfr    else
3901178828Sdfr	res += et->checksum->checksumsize;
390272448Sassar    return res;
390372448Sassar}
390472448Sassar
390555682Smarkm/*
390655682Smarkm * Return the size of an encrypted packet of length `data_len'
390755682Smarkm */
390855682Smarkm
390955682Smarkmsize_t
391055682Smarkmkrb5_get_wrapped_length (krb5_context context,
391155682Smarkm			 krb5_crypto  crypto,
391255682Smarkm			 size_t       data_len)
391355682Smarkm{
391472448Sassar    if (derived_crypto (context, crypto))
391572448Sassar	return wrapped_length_dervied (context, crypto, data_len);
391672448Sassar    else
391772448Sassar	return wrapped_length (context, crypto, data_len);
391855682Smarkm}
391955682Smarkm
3920178828Sdfr/*
3921178828Sdfr * Return the size of an encrypted packet of length `data_len'
3922178828Sdfr */
3923178828Sdfr
3924178828Sdfrstatic size_t
3925178828Sdfrcrypto_overhead (krb5_context context,
3926178828Sdfr		 krb5_crypto  crypto)
3927178828Sdfr{
3928178828Sdfr    struct encryption_type *et = crypto->et;
3929178828Sdfr    size_t res;
3930178828Sdfr
3931178828Sdfr    res = CHECKSUMSIZE(et->checksum);
3932178828Sdfr    res += et->confoundersize;
3933178828Sdfr    if (et->padsize > 1)
3934178828Sdfr	res += et->padsize;
3935178828Sdfr    return res;
3936178828Sdfr}
3937178828Sdfr
3938178828Sdfrstatic size_t
3939178828Sdfrcrypto_overhead_dervied (krb5_context context,
3940178828Sdfr			 krb5_crypto  crypto)
3941178828Sdfr{
3942178828Sdfr    struct encryption_type *et = crypto->et;
3943178828Sdfr    size_t res;
3944178828Sdfr
3945178828Sdfr    if (et->keyed_checksum)
3946178828Sdfr	res = CHECKSUMSIZE(et->keyed_checksum);
3947178828Sdfr    else
3948178828Sdfr	res = CHECKSUMSIZE(et->checksum);
3949178828Sdfr    res += et->confoundersize;
3950178828Sdfr    if (et->padsize > 1)
3951178828Sdfr	res += et->padsize;
3952178828Sdfr    return res;
3953178828Sdfr}
3954178828Sdfr
3955178828Sdfrsize_t
3956178828Sdfrkrb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
3957178828Sdfr{
3958178828Sdfr    if (derived_crypto (context, crypto))
3959178828Sdfr	return crypto_overhead_dervied (context, crypto);
3960178828Sdfr    else
3961178828Sdfr	return crypto_overhead (context, crypto);
3962178828Sdfr}
3963178828Sdfr
3964178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
3965178828Sdfrkrb5_random_to_key(krb5_context context,
3966178828Sdfr		   krb5_enctype type,
3967178828Sdfr		   const void *data,
3968178828Sdfr		   size_t size,
3969178828Sdfr		   krb5_keyblock *key)
3970178828Sdfr{
3971178828Sdfr    krb5_error_code ret;
3972178828Sdfr    struct encryption_type *et = _find_enctype(type);
3973178828Sdfr    if(et == NULL) {
3974178828Sdfr	krb5_set_error_string(context, "encryption type %d not supported",
3975178828Sdfr			      type);
3976178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
3977178828Sdfr    }
3978178828Sdfr    if ((et->keytype->bits + 7) / 8 > size) {
3979178828Sdfr	krb5_set_error_string(context, "encryption key %s needs %d bytes "
3980178828Sdfr			      "of random to make an encryption key out of it",
3981178828Sdfr			      et->name, (int)et->keytype->size);
3982178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
3983178828Sdfr    }
3984178828Sdfr    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
3985178828Sdfr    if(ret)
3986178828Sdfr	return ret;
3987178828Sdfr    key->keytype = type;
3988178828Sdfr    if (et->keytype->random_to_key)
3989178828Sdfr 	(*et->keytype->random_to_key)(context, key, data, size);
3990178828Sdfr    else
3991178828Sdfr	memcpy(key->keyvalue.data, data, et->keytype->size);
3992178828Sdfr
3993178828Sdfr    return 0;
3994178828Sdfr}
3995178828Sdfr
3996178828Sdfrkrb5_error_code
3997178828Sdfr_krb5_pk_octetstring2key(krb5_context context,
3998178828Sdfr			 krb5_enctype type,
3999178828Sdfr			 const void *dhdata,
4000178828Sdfr			 size_t dhsize,
4001178828Sdfr			 const heim_octet_string *c_n,
4002178828Sdfr			 const heim_octet_string *k_n,
4003178828Sdfr			 krb5_keyblock *key)
4004178828Sdfr{
4005178828Sdfr    struct encryption_type *et = _find_enctype(type);
4006178828Sdfr    krb5_error_code ret;
4007178828Sdfr    size_t keylen, offset;
4008178828Sdfr    void *keydata;
4009178828Sdfr    unsigned char counter;
4010178828Sdfr    unsigned char shaoutput[20];
4011178828Sdfr
4012178828Sdfr    if(et == NULL) {
4013178828Sdfr	krb5_set_error_string(context, "encryption type %d not supported",
4014178828Sdfr			      type);
4015178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
4016178828Sdfr    }
4017178828Sdfr    keylen = (et->keytype->bits + 7) / 8;
4018178828Sdfr
4019178828Sdfr    keydata = malloc(keylen);
4020178828Sdfr    if (keydata == NULL) {
4021178828Sdfr	krb5_set_error_string(context, "malloc: out of memory");
4022178828Sdfr	return ENOMEM;
4023178828Sdfr    }
4024178828Sdfr
4025178828Sdfr    counter = 0;
4026178828Sdfr    offset = 0;
4027178828Sdfr    do {
4028178828Sdfr	SHA_CTX m;
4029178828Sdfr
4030178828Sdfr	SHA1_Init(&m);
4031178828Sdfr	SHA1_Update(&m, &counter, 1);
4032178828Sdfr	SHA1_Update(&m, dhdata, dhsize);
4033178828Sdfr	if (c_n)
4034178828Sdfr	    SHA1_Update(&m, c_n->data, c_n->length);
4035178828Sdfr	if (k_n)
4036178828Sdfr	    SHA1_Update(&m, k_n->data, k_n->length);
4037178828Sdfr	SHA1_Final(shaoutput, &m);
4038178828Sdfr
4039178828Sdfr	memcpy((unsigned char *)keydata + offset,
4040178828Sdfr	       shaoutput,
4041178828Sdfr	       min(keylen - offset, sizeof(shaoutput)));
4042178828Sdfr
4043178828Sdfr	offset += sizeof(shaoutput);
4044178828Sdfr	counter++;
4045178828Sdfr    } while(offset < keylen);
4046178828Sdfr    memset(shaoutput, 0, sizeof(shaoutput));
4047178828Sdfr
4048178828Sdfr    ret = krb5_random_to_key(context, type, keydata, keylen, key);
4049178828Sdfr    memset(keydata, 0, sizeof(keylen));
4050178828Sdfr    free(keydata);
4051178828Sdfr    return ret;
4052178828Sdfr}
4053178828Sdfr
4054178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
4055178828Sdfrkrb5_crypto_prf_length(krb5_context context,
4056178828Sdfr		       krb5_enctype type,
4057178828Sdfr		       size_t *length)
4058178828Sdfr{
4059178828Sdfr    struct encryption_type *et = _find_enctype(type);
4060178828Sdfr
4061178828Sdfr    if(et == NULL || et->prf_length == 0) {
4062178828Sdfr	krb5_set_error_string(context, "encryption type %d not supported",
4063178828Sdfr			      type);
4064178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
4065178828Sdfr    }
4066178828Sdfr
4067178828Sdfr    *length = et->prf_length;
4068178828Sdfr    return 0;
4069178828Sdfr}
4070178828Sdfr
4071178828Sdfrkrb5_error_code KRB5_LIB_FUNCTION
4072178828Sdfrkrb5_crypto_prf(krb5_context context,
4073178828Sdfr		const krb5_crypto crypto,
4074178828Sdfr		const krb5_data *input,
4075178828Sdfr		krb5_data *output)
4076178828Sdfr{
4077178828Sdfr    struct encryption_type *et = crypto->et;
4078178828Sdfr
4079178828Sdfr    krb5_data_zero(output);
4080178828Sdfr
4081178828Sdfr    if(et->prf == NULL) {
4082178828Sdfr	krb5_set_error_string(context, "kerberos prf for %s not supported",
4083178828Sdfr			      et->name);
4084178828Sdfr	return KRB5_PROG_ETYPE_NOSUPP;
4085178828Sdfr    }
4086178828Sdfr
4087178828Sdfr    return (*et->prf)(context, crypto, input, output);
4088178828Sdfr}
4089178828Sdfr
4090178828Sdfr
4091178828Sdfr
4092178828Sdfr
409355682Smarkm#ifdef CRYPTO_DEBUG
409455682Smarkm
409555682Smarkmstatic krb5_error_code
409655682Smarkmkrb5_get_keyid(krb5_context context,
409755682Smarkm	       krb5_keyblock *key,
4098178828Sdfr	       uint32_t *keyid)
409955682Smarkm{
410057416Smarkm    MD5_CTX md5;
410155682Smarkm    unsigned char tmp[16];
410257416Smarkm
410372448Sassar    MD5_Init (&md5);
410472448Sassar    MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
410572448Sassar    MD5_Final (tmp, &md5);
410655682Smarkm    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
410755682Smarkm    return 0;
410855682Smarkm}
410955682Smarkm
411055682Smarkmstatic void
411155682Smarkmkrb5_crypto_debug(krb5_context context,
4112178828Sdfr		  int encryptp,
411355682Smarkm		  size_t len,
411455682Smarkm		  krb5_keyblock *key)
411555682Smarkm{
4116178828Sdfr    uint32_t keyid;
411755682Smarkm    char *kt;
411855682Smarkm    krb5_get_keyid(context, key, &keyid);
411955682Smarkm    krb5_enctype_to_string(context, key->keytype, &kt);
412055682Smarkm    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)",
4121178828Sdfr	       encryptp ? "encrypting" : "decrypting",
412255682Smarkm	       (unsigned long)len,
412355682Smarkm	       keyid,
412455682Smarkm	       kt);
412555682Smarkm    free(kt);
412655682Smarkm}
412755682Smarkm
412855682Smarkm#endif /* CRYPTO_DEBUG */
412972448Sassar
413072448Sassar#if 0
413172448Sassarint
413272448Sassarmain()
413372448Sassar{
413472448Sassar#if 0
413572448Sassar    int i;
413672448Sassar    krb5_context context;
413772448Sassar    krb5_crypto crypto;
413872448Sassar    struct key_data *d;
413972448Sassar    krb5_keyblock key;
414072448Sassar    char constant[4];
414172448Sassar    unsigned usage = ENCRYPTION_USAGE(3);
414272448Sassar    krb5_error_code ret;
414372448Sassar
414472448Sassar    ret = krb5_init_context(&context);
414572448Sassar    if (ret)
414672448Sassar	errx (1, "krb5_init_context failed: %d", ret);
414772448Sassar
414872448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
414972448Sassar    key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
415072448Sassar	"\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
415172448Sassar	"\xc8\xdf\xab\x26\x86\x64\x15\x25";
415272448Sassar    key.keyvalue.length = 24;
415372448Sassar
415472448Sassar    krb5_crypto_init(context, &key, 0, &crypto);
415572448Sassar
415672448Sassar    d = _new_derived_key(crypto, usage);
415772448Sassar    if(d == NULL)
4158178828Sdfr	krb5_errx(context, 1, "_new_derived_key failed");
415972448Sassar    krb5_copy_keyblock(context, crypto->key.key, &d->key);
416072448Sassar    _krb5_put_int(constant, usage, 4);
416172448Sassar    derive_key(context, crypto->et, d, constant, sizeof(constant));
416272448Sassar    return 0;
416372448Sassar#else
416472448Sassar    int i;
416572448Sassar    krb5_context context;
416672448Sassar    krb5_crypto crypto;
416772448Sassar    struct key_data *d;
416872448Sassar    krb5_keyblock key;
416972448Sassar    krb5_error_code ret;
417072448Sassar    Checksum res;
417172448Sassar
417272448Sassar    char *data = "what do ya want for nothing?";
417372448Sassar
417472448Sassar    ret = krb5_init_context(&context);
417572448Sassar    if (ret)
417672448Sassar	errx (1, "krb5_init_context failed: %d", ret);
417772448Sassar
417872448Sassar    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
417972448Sassar    key.keyvalue.data = "Jefe";
418072448Sassar    /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
418172448Sassar       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
418272448Sassar    key.keyvalue.length = 4;
418372448Sassar
4184178828Sdfr    d = ecalloc(1, sizeof(*d));
418572448Sassar    d->key = &key;
418672448Sassar    res.checksum.length = 20;
4187178828Sdfr    res.checksum.data = emalloc(res.checksum.length);
4188120948Snectar    SP_HMAC_SHA1_checksum(context, d, data, 28, &res);
418972448Sassar
419072448Sassar    return 0;
419172448Sassar#endif
419272448Sassar}
419372448Sassar#endif
4194