xref: /minix3/crypto/external/bsd/heimdal/dist/lib/krb5/crypto.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc /*	$NetBSD: crypto.c,v 1.1.1.1 2011/04/13 18:15:33 elric Exp $	*/
2*ebfedea0SLionel Sambuc 
3*ebfedea0SLionel Sambuc /*
4*ebfedea0SLionel Sambuc  * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5*ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6*ebfedea0SLionel Sambuc  * All rights reserved.
7*ebfedea0SLionel Sambuc  *
8*ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc  * are met:
11*ebfedea0SLionel Sambuc  *
12*ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14*ebfedea0SLionel Sambuc  *
15*ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17*ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18*ebfedea0SLionel Sambuc  *
19*ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20*ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21*ebfedea0SLionel Sambuc  *    without specific prior written permission.
22*ebfedea0SLionel Sambuc  *
23*ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24*ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27*ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34*ebfedea0SLionel Sambuc  */
35*ebfedea0SLionel Sambuc 
36*ebfedea0SLionel Sambuc #define KRB5_DEPRECATED
37*ebfedea0SLionel Sambuc 
38*ebfedea0SLionel Sambuc #include "krb5_locl.h"
39*ebfedea0SLionel Sambuc 
40*ebfedea0SLionel Sambuc struct _krb5_key_usage {
41*ebfedea0SLionel Sambuc     unsigned usage;
42*ebfedea0SLionel Sambuc     struct _krb5_key_data key;
43*ebfedea0SLionel Sambuc };
44*ebfedea0SLionel Sambuc 
45*ebfedea0SLionel Sambuc 
46*ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER
47*ebfedea0SLionel Sambuc #define DES3_OLD_ENCTYPE 1
48*ebfedea0SLionel Sambuc #endif
49*ebfedea0SLionel Sambuc 
50*ebfedea0SLionel Sambuc static krb5_error_code _get_derived_key(krb5_context, krb5_crypto,
51*ebfedea0SLionel Sambuc 					unsigned, struct _krb5_key_data**);
52*ebfedea0SLionel Sambuc static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
53*ebfedea0SLionel Sambuc 
54*ebfedea0SLionel Sambuc static void free_key_schedule(krb5_context,
55*ebfedea0SLionel Sambuc 			      struct _krb5_key_data *,
56*ebfedea0SLionel Sambuc 			      struct _krb5_encryption_type *);
57*ebfedea0SLionel Sambuc 
58*ebfedea0SLionel Sambuc /************************************************************
59*ebfedea0SLionel Sambuc  *                                                          *
60*ebfedea0SLionel Sambuc  ************************************************************/
61*ebfedea0SLionel Sambuc 
62*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
63*ebfedea0SLionel Sambuc krb5_enctype_keysize(krb5_context context,
64*ebfedea0SLionel Sambuc 		     krb5_enctype type,
65*ebfedea0SLionel Sambuc 		     size_t *keysize)
66*ebfedea0SLionel Sambuc {
67*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
68*ebfedea0SLionel Sambuc     if(et == NULL) {
69*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
70*ebfedea0SLionel Sambuc 			       N_("encryption type %d not supported", ""),
71*ebfedea0SLionel Sambuc 			       type);
72*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
73*ebfedea0SLionel Sambuc     }
74*ebfedea0SLionel Sambuc     *keysize = et->keytype->size;
75*ebfedea0SLionel Sambuc     return 0;
76*ebfedea0SLionel Sambuc }
77*ebfedea0SLionel Sambuc 
78*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
79*ebfedea0SLionel Sambuc krb5_enctype_keybits(krb5_context context,
80*ebfedea0SLionel Sambuc 		     krb5_enctype type,
81*ebfedea0SLionel Sambuc 		     size_t *keybits)
82*ebfedea0SLionel Sambuc {
83*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
84*ebfedea0SLionel Sambuc     if(et == NULL) {
85*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
86*ebfedea0SLionel Sambuc 			       "encryption type %d not supported",
87*ebfedea0SLionel Sambuc 			       type);
88*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
89*ebfedea0SLionel Sambuc     }
90*ebfedea0SLionel Sambuc     *keybits = et->keytype->bits;
91*ebfedea0SLionel Sambuc     return 0;
92*ebfedea0SLionel Sambuc }
93*ebfedea0SLionel Sambuc 
94*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
95*ebfedea0SLionel Sambuc krb5_generate_random_keyblock(krb5_context context,
96*ebfedea0SLionel Sambuc 			      krb5_enctype type,
97*ebfedea0SLionel Sambuc 			      krb5_keyblock *key)
98*ebfedea0SLionel Sambuc {
99*ebfedea0SLionel Sambuc     krb5_error_code ret;
100*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
101*ebfedea0SLionel Sambuc     if(et == NULL) {
102*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
103*ebfedea0SLionel Sambuc 			       N_("encryption type %d not supported", ""),
104*ebfedea0SLionel Sambuc 			       type);
105*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
106*ebfedea0SLionel Sambuc     }
107*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
108*ebfedea0SLionel Sambuc     if(ret)
109*ebfedea0SLionel Sambuc 	return ret;
110*ebfedea0SLionel Sambuc     key->keytype = type;
111*ebfedea0SLionel Sambuc     if(et->keytype->random_key)
112*ebfedea0SLionel Sambuc 	(*et->keytype->random_key)(context, key);
113*ebfedea0SLionel Sambuc     else
114*ebfedea0SLionel Sambuc 	krb5_generate_random_block(key->keyvalue.data,
115*ebfedea0SLionel Sambuc 				   key->keyvalue.length);
116*ebfedea0SLionel Sambuc     return 0;
117*ebfedea0SLionel Sambuc }
118*ebfedea0SLionel Sambuc 
119*ebfedea0SLionel Sambuc static krb5_error_code
120*ebfedea0SLionel Sambuc _key_schedule(krb5_context context,
121*ebfedea0SLionel Sambuc 	      struct _krb5_key_data *key)
122*ebfedea0SLionel Sambuc {
123*ebfedea0SLionel Sambuc     krb5_error_code ret;
124*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype);
125*ebfedea0SLionel Sambuc     struct _krb5_key_type *kt;
126*ebfedea0SLionel Sambuc 
127*ebfedea0SLionel Sambuc     if (et == NULL) {
128*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
129*ebfedea0SLionel Sambuc 				N_("encryption type %d not supported", ""),
130*ebfedea0SLionel Sambuc 				key->key->keytype);
131*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
132*ebfedea0SLionel Sambuc     }
133*ebfedea0SLionel Sambuc 
134*ebfedea0SLionel Sambuc     kt = et->keytype;
135*ebfedea0SLionel Sambuc 
136*ebfedea0SLionel Sambuc     if(kt->schedule == NULL)
137*ebfedea0SLionel Sambuc 	return 0;
138*ebfedea0SLionel Sambuc     if (key->schedule != NULL)
139*ebfedea0SLionel Sambuc 	return 0;
140*ebfedea0SLionel Sambuc     ALLOC(key->schedule, 1);
141*ebfedea0SLionel Sambuc     if(key->schedule == NULL) {
142*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
143*ebfedea0SLionel Sambuc 	return ENOMEM;
144*ebfedea0SLionel Sambuc     }
145*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(key->schedule, kt->schedule_size);
146*ebfedea0SLionel Sambuc     if(ret) {
147*ebfedea0SLionel Sambuc 	free(key->schedule);
148*ebfedea0SLionel Sambuc 	key->schedule = NULL;
149*ebfedea0SLionel Sambuc 	return ret;
150*ebfedea0SLionel Sambuc     }
151*ebfedea0SLionel Sambuc     (*kt->schedule)(context, kt, key);
152*ebfedea0SLionel Sambuc     return 0;
153*ebfedea0SLionel Sambuc }
154*ebfedea0SLionel Sambuc 
155*ebfedea0SLionel Sambuc /************************************************************
156*ebfedea0SLionel Sambuc  *                                                          *
157*ebfedea0SLionel Sambuc  ************************************************************/
158*ebfedea0SLionel Sambuc 
159*ebfedea0SLionel Sambuc static krb5_error_code
160*ebfedea0SLionel Sambuc SHA1_checksum(krb5_context context,
161*ebfedea0SLionel Sambuc 	      struct _krb5_key_data *key,
162*ebfedea0SLionel Sambuc 	      const void *data,
163*ebfedea0SLionel Sambuc 	      size_t len,
164*ebfedea0SLionel Sambuc 	      unsigned usage,
165*ebfedea0SLionel Sambuc 	      Checksum *C)
166*ebfedea0SLionel Sambuc {
167*ebfedea0SLionel Sambuc     if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1)
168*ebfedea0SLionel Sambuc 	krb5_abortx(context, "sha1 checksum failed");
169*ebfedea0SLionel Sambuc     return 0;
170*ebfedea0SLionel Sambuc }
171*ebfedea0SLionel Sambuc 
172*ebfedea0SLionel Sambuc /* HMAC according to RFC2104 */
173*ebfedea0SLionel Sambuc krb5_error_code
174*ebfedea0SLionel Sambuc _krb5_internal_hmac(krb5_context context,
175*ebfedea0SLionel Sambuc 		    struct _krb5_checksum_type *cm,
176*ebfedea0SLionel Sambuc 		    const void *data,
177*ebfedea0SLionel Sambuc 		    size_t len,
178*ebfedea0SLionel Sambuc 		    unsigned usage,
179*ebfedea0SLionel Sambuc 		    struct _krb5_key_data *keyblock,
180*ebfedea0SLionel Sambuc 		    Checksum *result)
181*ebfedea0SLionel Sambuc {
182*ebfedea0SLionel Sambuc     unsigned char *ipad, *opad;
183*ebfedea0SLionel Sambuc     unsigned char *key;
184*ebfedea0SLionel Sambuc     size_t key_len;
185*ebfedea0SLionel Sambuc     int i;
186*ebfedea0SLionel Sambuc 
187*ebfedea0SLionel Sambuc     ipad = malloc(cm->blocksize + len);
188*ebfedea0SLionel Sambuc     if (ipad == NULL)
189*ebfedea0SLionel Sambuc 	return ENOMEM;
190*ebfedea0SLionel Sambuc     opad = malloc(cm->blocksize + cm->checksumsize);
191*ebfedea0SLionel Sambuc     if (opad == NULL) {
192*ebfedea0SLionel Sambuc 	free(ipad);
193*ebfedea0SLionel Sambuc 	return ENOMEM;
194*ebfedea0SLionel Sambuc     }
195*ebfedea0SLionel Sambuc     memset(ipad, 0x36, cm->blocksize);
196*ebfedea0SLionel Sambuc     memset(opad, 0x5c, cm->blocksize);
197*ebfedea0SLionel Sambuc 
198*ebfedea0SLionel Sambuc     if(keyblock->key->keyvalue.length > cm->blocksize){
199*ebfedea0SLionel Sambuc 	(*cm->checksum)(context,
200*ebfedea0SLionel Sambuc 			keyblock,
201*ebfedea0SLionel Sambuc 			keyblock->key->keyvalue.data,
202*ebfedea0SLionel Sambuc 			keyblock->key->keyvalue.length,
203*ebfedea0SLionel Sambuc 			usage,
204*ebfedea0SLionel Sambuc 			result);
205*ebfedea0SLionel Sambuc 	key = result->checksum.data;
206*ebfedea0SLionel Sambuc 	key_len = result->checksum.length;
207*ebfedea0SLionel Sambuc     } else {
208*ebfedea0SLionel Sambuc 	key = keyblock->key->keyvalue.data;
209*ebfedea0SLionel Sambuc 	key_len = keyblock->key->keyvalue.length;
210*ebfedea0SLionel Sambuc     }
211*ebfedea0SLionel Sambuc     for(i = 0; i < key_len; i++){
212*ebfedea0SLionel Sambuc 	ipad[i] ^= key[i];
213*ebfedea0SLionel Sambuc 	opad[i] ^= key[i];
214*ebfedea0SLionel Sambuc     }
215*ebfedea0SLionel Sambuc     memcpy(ipad + cm->blocksize, data, len);
216*ebfedea0SLionel Sambuc     (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
217*ebfedea0SLionel Sambuc 		    usage, result);
218*ebfedea0SLionel Sambuc     memcpy(opad + cm->blocksize, result->checksum.data,
219*ebfedea0SLionel Sambuc 	   result->checksum.length);
220*ebfedea0SLionel Sambuc     (*cm->checksum)(context, keyblock, opad,
221*ebfedea0SLionel Sambuc 		    cm->blocksize + cm->checksumsize, usage, result);
222*ebfedea0SLionel Sambuc     memset(ipad, 0, cm->blocksize + len);
223*ebfedea0SLionel Sambuc     free(ipad);
224*ebfedea0SLionel Sambuc     memset(opad, 0, cm->blocksize + cm->checksumsize);
225*ebfedea0SLionel Sambuc     free(opad);
226*ebfedea0SLionel Sambuc 
227*ebfedea0SLionel Sambuc     return 0;
228*ebfedea0SLionel Sambuc }
229*ebfedea0SLionel Sambuc 
230*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
231*ebfedea0SLionel Sambuc krb5_hmac(krb5_context context,
232*ebfedea0SLionel Sambuc 	  krb5_cksumtype cktype,
233*ebfedea0SLionel Sambuc 	  const void *data,
234*ebfedea0SLionel Sambuc 	  size_t len,
235*ebfedea0SLionel Sambuc 	  unsigned usage,
236*ebfedea0SLionel Sambuc 	  krb5_keyblock *key,
237*ebfedea0SLionel Sambuc 	  Checksum *result)
238*ebfedea0SLionel Sambuc {
239*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *c = _krb5_find_checksum(cktype);
240*ebfedea0SLionel Sambuc     struct _krb5_key_data kd;
241*ebfedea0SLionel Sambuc     krb5_error_code ret;
242*ebfedea0SLionel Sambuc 
243*ebfedea0SLionel Sambuc     if (c == NULL) {
244*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
245*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
246*ebfedea0SLionel Sambuc 				cktype);
247*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
248*ebfedea0SLionel Sambuc     }
249*ebfedea0SLionel Sambuc 
250*ebfedea0SLionel Sambuc     kd.key = key;
251*ebfedea0SLionel Sambuc     kd.schedule = NULL;
252*ebfedea0SLionel Sambuc 
253*ebfedea0SLionel Sambuc     ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result);
254*ebfedea0SLionel Sambuc 
255*ebfedea0SLionel Sambuc     if (kd.schedule)
256*ebfedea0SLionel Sambuc 	krb5_free_data(context, kd.schedule);
257*ebfedea0SLionel Sambuc 
258*ebfedea0SLionel Sambuc     return ret;
259*ebfedea0SLionel Sambuc }
260*ebfedea0SLionel Sambuc 
261*ebfedea0SLionel Sambuc krb5_error_code
262*ebfedea0SLionel Sambuc _krb5_SP_HMAC_SHA1_checksum(krb5_context context,
263*ebfedea0SLionel Sambuc 			    struct _krb5_key_data *key,
264*ebfedea0SLionel Sambuc 			    const void *data,
265*ebfedea0SLionel Sambuc 			    size_t len,
266*ebfedea0SLionel Sambuc 			    unsigned usage,
267*ebfedea0SLionel Sambuc 			    Checksum *result)
268*ebfedea0SLionel Sambuc {
269*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
270*ebfedea0SLionel Sambuc     Checksum res;
271*ebfedea0SLionel Sambuc     char sha1_data[20];
272*ebfedea0SLionel Sambuc     krb5_error_code ret;
273*ebfedea0SLionel Sambuc 
274*ebfedea0SLionel Sambuc     res.checksum.data = sha1_data;
275*ebfedea0SLionel Sambuc     res.checksum.length = sizeof(sha1_data);
276*ebfedea0SLionel Sambuc 
277*ebfedea0SLionel Sambuc     ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res);
278*ebfedea0SLionel Sambuc     if (ret)
279*ebfedea0SLionel Sambuc 	krb5_abortx(context, "hmac failed");
280*ebfedea0SLionel Sambuc     memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
281*ebfedea0SLionel Sambuc     return 0;
282*ebfedea0SLionel Sambuc }
283*ebfedea0SLionel Sambuc 
284*ebfedea0SLionel Sambuc struct _krb5_checksum_type _krb5_checksum_sha1 = {
285*ebfedea0SLionel Sambuc     CKSUMTYPE_SHA1,
286*ebfedea0SLionel Sambuc     "sha1",
287*ebfedea0SLionel Sambuc     64,
288*ebfedea0SLionel Sambuc     20,
289*ebfedea0SLionel Sambuc     F_CPROOF,
290*ebfedea0SLionel Sambuc     SHA1_checksum,
291*ebfedea0SLionel Sambuc     NULL
292*ebfedea0SLionel Sambuc };
293*ebfedea0SLionel Sambuc 
294*ebfedea0SLionel Sambuc struct _krb5_checksum_type *
295*ebfedea0SLionel Sambuc _krb5_find_checksum(krb5_cksumtype type)
296*ebfedea0SLionel Sambuc {
297*ebfedea0SLionel Sambuc     int i;
298*ebfedea0SLionel Sambuc     for(i = 0; i < _krb5_num_checksums; i++)
299*ebfedea0SLionel Sambuc 	if(_krb5_checksum_types[i]->type == type)
300*ebfedea0SLionel Sambuc 	    return _krb5_checksum_types[i];
301*ebfedea0SLionel Sambuc     return NULL;
302*ebfedea0SLionel Sambuc }
303*ebfedea0SLionel Sambuc 
304*ebfedea0SLionel Sambuc static krb5_error_code
305*ebfedea0SLionel Sambuc get_checksum_key(krb5_context context,
306*ebfedea0SLionel Sambuc 		 krb5_crypto crypto,
307*ebfedea0SLionel Sambuc 		 unsigned usage,  /* not krb5_key_usage */
308*ebfedea0SLionel Sambuc 		 struct _krb5_checksum_type *ct,
309*ebfedea0SLionel Sambuc 		 struct _krb5_key_data **key)
310*ebfedea0SLionel Sambuc {
311*ebfedea0SLionel Sambuc     krb5_error_code ret = 0;
312*ebfedea0SLionel Sambuc 
313*ebfedea0SLionel Sambuc     if(ct->flags & F_DERIVED)
314*ebfedea0SLionel Sambuc 	ret = _get_derived_key(context, crypto, usage, key);
315*ebfedea0SLionel Sambuc     else if(ct->flags & F_VARIANT) {
316*ebfedea0SLionel Sambuc 	int i;
317*ebfedea0SLionel Sambuc 
318*ebfedea0SLionel Sambuc 	*key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
319*ebfedea0SLionel Sambuc 	if(*key == NULL) {
320*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
321*ebfedea0SLionel Sambuc 	    return ENOMEM;
322*ebfedea0SLionel Sambuc 	}
323*ebfedea0SLionel Sambuc 	ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
324*ebfedea0SLionel Sambuc 	if(ret)
325*ebfedea0SLionel Sambuc 	    return ret;
326*ebfedea0SLionel Sambuc 	for(i = 0; i < (*key)->key->keyvalue.length; i++)
327*ebfedea0SLionel Sambuc 	    ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
328*ebfedea0SLionel Sambuc     } else {
329*ebfedea0SLionel Sambuc 	*key = &crypto->key;
330*ebfedea0SLionel Sambuc     }
331*ebfedea0SLionel Sambuc     if(ret == 0)
332*ebfedea0SLionel Sambuc 	ret = _key_schedule(context, *key);
333*ebfedea0SLionel Sambuc     return ret;
334*ebfedea0SLionel Sambuc }
335*ebfedea0SLionel Sambuc 
336*ebfedea0SLionel Sambuc static krb5_error_code
337*ebfedea0SLionel Sambuc create_checksum (krb5_context context,
338*ebfedea0SLionel Sambuc 		 struct _krb5_checksum_type *ct,
339*ebfedea0SLionel Sambuc 		 krb5_crypto crypto,
340*ebfedea0SLionel Sambuc 		 unsigned usage,
341*ebfedea0SLionel Sambuc 		 void *data,
342*ebfedea0SLionel Sambuc 		 size_t len,
343*ebfedea0SLionel Sambuc 		 Checksum *result)
344*ebfedea0SLionel Sambuc {
345*ebfedea0SLionel Sambuc     krb5_error_code ret;
346*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
347*ebfedea0SLionel Sambuc     int keyed_checksum;
348*ebfedea0SLionel Sambuc 
349*ebfedea0SLionel Sambuc     if (ct->flags & F_DISABLED) {
350*ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
351*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
352*ebfedea0SLionel Sambuc     }
353*ebfedea0SLionel Sambuc     keyed_checksum = (ct->flags & F_KEYED) != 0;
354*ebfedea0SLionel Sambuc     if(keyed_checksum && crypto == NULL) {
355*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
356*ebfedea0SLionel Sambuc 				N_("Checksum type %s is keyed but no "
357*ebfedea0SLionel Sambuc 				   "crypto context (key) was passed in", ""),
358*ebfedea0SLionel Sambuc 				ct->name);
359*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
360*ebfedea0SLionel Sambuc     }
361*ebfedea0SLionel Sambuc     if(keyed_checksum) {
362*ebfedea0SLionel Sambuc 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
363*ebfedea0SLionel Sambuc 	if (ret)
364*ebfedea0SLionel Sambuc 	    return ret;
365*ebfedea0SLionel Sambuc     } else
366*ebfedea0SLionel Sambuc 	dkey = NULL;
367*ebfedea0SLionel Sambuc     result->cksumtype = ct->type;
368*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(&result->checksum, ct->checksumsize);
369*ebfedea0SLionel Sambuc     if (ret)
370*ebfedea0SLionel Sambuc 	return (ret);
371*ebfedea0SLionel Sambuc     return (*ct->checksum)(context, dkey, data, len, usage, result);
372*ebfedea0SLionel Sambuc }
373*ebfedea0SLionel Sambuc 
374*ebfedea0SLionel Sambuc static int
375*ebfedea0SLionel Sambuc arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto)
376*ebfedea0SLionel Sambuc {
377*ebfedea0SLionel Sambuc     return (ct->type == CKSUMTYPE_HMAC_MD5) &&
378*ebfedea0SLionel Sambuc 	(crypto->key.key->keytype == KEYTYPE_ARCFOUR);
379*ebfedea0SLionel Sambuc }
380*ebfedea0SLionel Sambuc 
381*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
382*ebfedea0SLionel Sambuc krb5_create_checksum(krb5_context context,
383*ebfedea0SLionel Sambuc 		     krb5_crypto crypto,
384*ebfedea0SLionel Sambuc 		     krb5_key_usage usage,
385*ebfedea0SLionel Sambuc 		     int type,
386*ebfedea0SLionel Sambuc 		     void *data,
387*ebfedea0SLionel Sambuc 		     size_t len,
388*ebfedea0SLionel Sambuc 		     Checksum *result)
389*ebfedea0SLionel Sambuc {
390*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = NULL;
391*ebfedea0SLionel Sambuc     unsigned keyusage;
392*ebfedea0SLionel Sambuc 
393*ebfedea0SLionel Sambuc     /* type 0 -> pick from crypto */
394*ebfedea0SLionel Sambuc     if (type) {
395*ebfedea0SLionel Sambuc 	ct = _krb5_find_checksum(type);
396*ebfedea0SLionel Sambuc     } else if (crypto) {
397*ebfedea0SLionel Sambuc 	ct = crypto->et->keyed_checksum;
398*ebfedea0SLionel Sambuc 	if (ct == NULL)
399*ebfedea0SLionel Sambuc 	    ct = crypto->et->checksum;
400*ebfedea0SLionel Sambuc     }
401*ebfedea0SLionel Sambuc 
402*ebfedea0SLionel Sambuc     if(ct == NULL) {
403*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
404*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
405*ebfedea0SLionel Sambuc 				type);
406*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
407*ebfedea0SLionel Sambuc     }
408*ebfedea0SLionel Sambuc 
409*ebfedea0SLionel Sambuc     if (arcfour_checksum_p(ct, crypto)) {
410*ebfedea0SLionel Sambuc 	keyusage = usage;
411*ebfedea0SLionel Sambuc 	_krb5_usage2arcfour(context, &keyusage);
412*ebfedea0SLionel Sambuc     } else
413*ebfedea0SLionel Sambuc 	keyusage = CHECKSUM_USAGE(usage);
414*ebfedea0SLionel Sambuc 
415*ebfedea0SLionel Sambuc     return create_checksum(context, ct, crypto, keyusage,
416*ebfedea0SLionel Sambuc 			   data, len, result);
417*ebfedea0SLionel Sambuc }
418*ebfedea0SLionel Sambuc 
419*ebfedea0SLionel Sambuc static krb5_error_code
420*ebfedea0SLionel Sambuc verify_checksum(krb5_context context,
421*ebfedea0SLionel Sambuc 		krb5_crypto crypto,
422*ebfedea0SLionel Sambuc 		unsigned usage, /* not krb5_key_usage */
423*ebfedea0SLionel Sambuc 		void *data,
424*ebfedea0SLionel Sambuc 		size_t len,
425*ebfedea0SLionel Sambuc 		Checksum *cksum)
426*ebfedea0SLionel Sambuc {
427*ebfedea0SLionel Sambuc     krb5_error_code ret;
428*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
429*ebfedea0SLionel Sambuc     int keyed_checksum;
430*ebfedea0SLionel Sambuc     Checksum c;
431*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct;
432*ebfedea0SLionel Sambuc 
433*ebfedea0SLionel Sambuc     ct = _krb5_find_checksum(cksum->cksumtype);
434*ebfedea0SLionel Sambuc     if (ct == NULL || (ct->flags & F_DISABLED)) {
435*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
436*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
437*ebfedea0SLionel Sambuc 				cksum->cksumtype);
438*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
439*ebfedea0SLionel Sambuc     }
440*ebfedea0SLionel Sambuc     if(ct->checksumsize != cksum->checksum.length) {
441*ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
442*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY,
443*ebfedea0SLionel Sambuc 			       N_("Decrypt integrity check failed for checksum type %s, "
444*ebfedea0SLionel Sambuc 				  "length was %u, expected %u", ""),
445*ebfedea0SLionel Sambuc 			       ct->name, (unsigned)cksum->checksum.length,
446*ebfedea0SLionel Sambuc 			       (unsigned)ct->checksumsize);
447*ebfedea0SLionel Sambuc 
448*ebfedea0SLionel Sambuc 	return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
449*ebfedea0SLionel Sambuc     }
450*ebfedea0SLionel Sambuc     keyed_checksum = (ct->flags & F_KEYED) != 0;
451*ebfedea0SLionel Sambuc     if(keyed_checksum) {
452*ebfedea0SLionel Sambuc 	struct _krb5_checksum_type *kct;
453*ebfedea0SLionel Sambuc 	if (crypto == NULL) {
454*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
455*ebfedea0SLionel Sambuc 				   N_("Checksum type %s is keyed but no "
456*ebfedea0SLionel Sambuc 				      "crypto context (key) was passed in", ""),
457*ebfedea0SLionel Sambuc 				   ct->name);
458*ebfedea0SLionel Sambuc 	    return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
459*ebfedea0SLionel Sambuc 	}
460*ebfedea0SLionel Sambuc 	kct = crypto->et->keyed_checksum;
461*ebfedea0SLionel Sambuc 	if (kct != NULL && kct->type != ct->type) {
462*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP,
463*ebfedea0SLionel Sambuc 				   N_("Checksum type %s is keyed, but "
464*ebfedea0SLionel Sambuc 				      "the key type %s passed didnt have that checksum "
465*ebfedea0SLionel Sambuc 				      "type as the keyed type", ""),
466*ebfedea0SLionel Sambuc 				    ct->name, crypto->et->name);
467*ebfedea0SLionel Sambuc 	    return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
468*ebfedea0SLionel Sambuc 	}
469*ebfedea0SLionel Sambuc 
470*ebfedea0SLionel Sambuc 	ret = get_checksum_key(context, crypto, usage, ct, &dkey);
471*ebfedea0SLionel Sambuc 	if (ret)
472*ebfedea0SLionel Sambuc 	    return ret;
473*ebfedea0SLionel Sambuc     } else
474*ebfedea0SLionel Sambuc 	dkey = NULL;
475*ebfedea0SLionel Sambuc 
476*ebfedea0SLionel Sambuc     /*
477*ebfedea0SLionel Sambuc      * If checksum have a verify function, lets use that instead of
478*ebfedea0SLionel Sambuc      * calling ->checksum and then compare result.
479*ebfedea0SLionel Sambuc      */
480*ebfedea0SLionel Sambuc 
481*ebfedea0SLionel Sambuc     if(ct->verify) {
482*ebfedea0SLionel Sambuc 	ret = (*ct->verify)(context, dkey, data, len, usage, cksum);
483*ebfedea0SLionel Sambuc 	if (ret)
484*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret,
485*ebfedea0SLionel Sambuc 				   N_("Decrypt integrity check failed for checksum "
486*ebfedea0SLionel Sambuc 				      "type %s, key type %s", ""),
487*ebfedea0SLionel Sambuc 				   ct->name, (crypto != NULL)? crypto->et->name : "(none)");
488*ebfedea0SLionel Sambuc 	return ret;
489*ebfedea0SLionel Sambuc     }
490*ebfedea0SLionel Sambuc 
491*ebfedea0SLionel Sambuc     ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
492*ebfedea0SLionel Sambuc     if (ret)
493*ebfedea0SLionel Sambuc 	return ret;
494*ebfedea0SLionel Sambuc 
495*ebfedea0SLionel Sambuc     ret = (*ct->checksum)(context, dkey, data, len, usage, &c);
496*ebfedea0SLionel Sambuc     if (ret) {
497*ebfedea0SLionel Sambuc 	krb5_data_free(&c.checksum);
498*ebfedea0SLionel Sambuc 	return ret;
499*ebfedea0SLionel Sambuc     }
500*ebfedea0SLionel Sambuc 
501*ebfedea0SLionel Sambuc     if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) {
502*ebfedea0SLionel Sambuc 	ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
503*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ret,
504*ebfedea0SLionel Sambuc 			       N_("Decrypt integrity check failed for checksum "
505*ebfedea0SLionel Sambuc 				  "type %s, key type %s", ""),
506*ebfedea0SLionel Sambuc 			       ct->name, crypto ? crypto->et->name : "(unkeyed)");
507*ebfedea0SLionel Sambuc     } else {
508*ebfedea0SLionel Sambuc 	ret = 0;
509*ebfedea0SLionel Sambuc     }
510*ebfedea0SLionel Sambuc     krb5_data_free (&c.checksum);
511*ebfedea0SLionel Sambuc     return ret;
512*ebfedea0SLionel Sambuc }
513*ebfedea0SLionel Sambuc 
514*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
515*ebfedea0SLionel Sambuc krb5_verify_checksum(krb5_context context,
516*ebfedea0SLionel Sambuc 		     krb5_crypto crypto,
517*ebfedea0SLionel Sambuc 		     krb5_key_usage usage,
518*ebfedea0SLionel Sambuc 		     void *data,
519*ebfedea0SLionel Sambuc 		     size_t len,
520*ebfedea0SLionel Sambuc 		     Checksum *cksum)
521*ebfedea0SLionel Sambuc {
522*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct;
523*ebfedea0SLionel Sambuc     unsigned keyusage;
524*ebfedea0SLionel Sambuc 
525*ebfedea0SLionel Sambuc     ct = _krb5_find_checksum(cksum->cksumtype);
526*ebfedea0SLionel Sambuc     if(ct == NULL) {
527*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
528*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
529*ebfedea0SLionel Sambuc 				cksum->cksumtype);
530*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
531*ebfedea0SLionel Sambuc     }
532*ebfedea0SLionel Sambuc 
533*ebfedea0SLionel Sambuc     if (arcfour_checksum_p(ct, crypto)) {
534*ebfedea0SLionel Sambuc 	keyusage = usage;
535*ebfedea0SLionel Sambuc 	_krb5_usage2arcfour(context, &keyusage);
536*ebfedea0SLionel Sambuc     } else
537*ebfedea0SLionel Sambuc 	keyusage = CHECKSUM_USAGE(usage);
538*ebfedea0SLionel Sambuc 
539*ebfedea0SLionel Sambuc     return verify_checksum(context, crypto, keyusage,
540*ebfedea0SLionel Sambuc 			   data, len, cksum);
541*ebfedea0SLionel Sambuc }
542*ebfedea0SLionel Sambuc 
543*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
544*ebfedea0SLionel Sambuc krb5_crypto_get_checksum_type(krb5_context context,
545*ebfedea0SLionel Sambuc                               krb5_crypto crypto,
546*ebfedea0SLionel Sambuc 			      krb5_cksumtype *type)
547*ebfedea0SLionel Sambuc {
548*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = NULL;
549*ebfedea0SLionel Sambuc 
550*ebfedea0SLionel Sambuc     if (crypto != NULL) {
551*ebfedea0SLionel Sambuc         ct = crypto->et->keyed_checksum;
552*ebfedea0SLionel Sambuc         if (ct == NULL)
553*ebfedea0SLionel Sambuc             ct = crypto->et->checksum;
554*ebfedea0SLionel Sambuc     }
555*ebfedea0SLionel Sambuc 
556*ebfedea0SLionel Sambuc     if (ct == NULL) {
557*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
558*ebfedea0SLionel Sambuc 				N_("checksum type not found", ""));
559*ebfedea0SLionel Sambuc         return KRB5_PROG_SUMTYPE_NOSUPP;
560*ebfedea0SLionel Sambuc     }
561*ebfedea0SLionel Sambuc 
562*ebfedea0SLionel Sambuc     *type = ct->type;
563*ebfedea0SLionel Sambuc 
564*ebfedea0SLionel Sambuc     return 0;
565*ebfedea0SLionel Sambuc }
566*ebfedea0SLionel Sambuc 
567*ebfedea0SLionel Sambuc 
568*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
569*ebfedea0SLionel Sambuc krb5_checksumsize(krb5_context context,
570*ebfedea0SLionel Sambuc 		  krb5_cksumtype type,
571*ebfedea0SLionel Sambuc 		  size_t *size)
572*ebfedea0SLionel Sambuc {
573*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
574*ebfedea0SLionel Sambuc     if(ct == NULL) {
575*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
576*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
577*ebfedea0SLionel Sambuc 				type);
578*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
579*ebfedea0SLionel Sambuc     }
580*ebfedea0SLionel Sambuc     *size = ct->checksumsize;
581*ebfedea0SLionel Sambuc     return 0;
582*ebfedea0SLionel Sambuc }
583*ebfedea0SLionel Sambuc 
584*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
585*ebfedea0SLionel Sambuc krb5_checksum_is_keyed(krb5_context context,
586*ebfedea0SLionel Sambuc 		       krb5_cksumtype type)
587*ebfedea0SLionel Sambuc {
588*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
589*ebfedea0SLionel Sambuc     if(ct == NULL) {
590*ebfedea0SLionel Sambuc 	if (context)
591*ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
592*ebfedea0SLionel Sambuc 				    N_("checksum type %d not supported", ""),
593*ebfedea0SLionel Sambuc 				    type);
594*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
595*ebfedea0SLionel Sambuc     }
596*ebfedea0SLionel Sambuc     return ct->flags & F_KEYED;
597*ebfedea0SLionel Sambuc }
598*ebfedea0SLionel Sambuc 
599*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
600*ebfedea0SLionel Sambuc krb5_checksum_is_collision_proof(krb5_context context,
601*ebfedea0SLionel Sambuc 				 krb5_cksumtype type)
602*ebfedea0SLionel Sambuc {
603*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
604*ebfedea0SLionel Sambuc     if(ct == NULL) {
605*ebfedea0SLionel Sambuc 	if (context)
606*ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
607*ebfedea0SLionel Sambuc 				    N_("checksum type %d not supported", ""),
608*ebfedea0SLionel Sambuc 				    type);
609*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
610*ebfedea0SLionel Sambuc     }
611*ebfedea0SLionel Sambuc     return ct->flags & F_CPROOF;
612*ebfedea0SLionel Sambuc }
613*ebfedea0SLionel Sambuc 
614*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
615*ebfedea0SLionel Sambuc krb5_checksum_disable(krb5_context context,
616*ebfedea0SLionel Sambuc 		      krb5_cksumtype type)
617*ebfedea0SLionel Sambuc {
618*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *ct = _krb5_find_checksum(type);
619*ebfedea0SLionel Sambuc     if(ct == NULL) {
620*ebfedea0SLionel Sambuc 	if (context)
621*ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
622*ebfedea0SLionel Sambuc 				    N_("checksum type %d not supported", ""),
623*ebfedea0SLionel Sambuc 				    type);
624*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
625*ebfedea0SLionel Sambuc     }
626*ebfedea0SLionel Sambuc     ct->flags |= F_DISABLED;
627*ebfedea0SLionel Sambuc     return 0;
628*ebfedea0SLionel Sambuc }
629*ebfedea0SLionel Sambuc 
630*ebfedea0SLionel Sambuc /************************************************************
631*ebfedea0SLionel Sambuc  *                                                          *
632*ebfedea0SLionel Sambuc  ************************************************************/
633*ebfedea0SLionel Sambuc 
634*ebfedea0SLionel Sambuc struct _krb5_encryption_type *
635*ebfedea0SLionel Sambuc _krb5_find_enctype(krb5_enctype type)
636*ebfedea0SLionel Sambuc {
637*ebfedea0SLionel Sambuc     int i;
638*ebfedea0SLionel Sambuc     for(i = 0; i < _krb5_num_etypes; i++)
639*ebfedea0SLionel Sambuc 	if(_krb5_etypes[i]->type == type)
640*ebfedea0SLionel Sambuc 	    return _krb5_etypes[i];
641*ebfedea0SLionel Sambuc     return NULL;
642*ebfedea0SLionel Sambuc }
643*ebfedea0SLionel Sambuc 
644*ebfedea0SLionel Sambuc 
645*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
646*ebfedea0SLionel Sambuc krb5_enctype_to_string(krb5_context context,
647*ebfedea0SLionel Sambuc 		       krb5_enctype etype,
648*ebfedea0SLionel Sambuc 		       char **string)
649*ebfedea0SLionel Sambuc {
650*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *e;
651*ebfedea0SLionel Sambuc     e = _krb5_find_enctype(etype);
652*ebfedea0SLionel Sambuc     if(e == NULL) {
653*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
654*ebfedea0SLionel Sambuc 				N_("encryption type %d not supported", ""),
655*ebfedea0SLionel Sambuc 				etype);
656*ebfedea0SLionel Sambuc 	*string = NULL;
657*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
658*ebfedea0SLionel Sambuc     }
659*ebfedea0SLionel Sambuc     *string = strdup(e->name);
660*ebfedea0SLionel Sambuc     if(*string == NULL) {
661*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
662*ebfedea0SLionel Sambuc 	return ENOMEM;
663*ebfedea0SLionel Sambuc     }
664*ebfedea0SLionel Sambuc     return 0;
665*ebfedea0SLionel Sambuc }
666*ebfedea0SLionel Sambuc 
667*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
668*ebfedea0SLionel Sambuc krb5_string_to_enctype(krb5_context context,
669*ebfedea0SLionel Sambuc 		       const char *string,
670*ebfedea0SLionel Sambuc 		       krb5_enctype *etype)
671*ebfedea0SLionel Sambuc {
672*ebfedea0SLionel Sambuc     int i;
673*ebfedea0SLionel Sambuc     for(i = 0; i < _krb5_num_etypes; i++)
674*ebfedea0SLionel Sambuc 	if(strcasecmp(_krb5_etypes[i]->name, string) == 0){
675*ebfedea0SLionel Sambuc 	    *etype = _krb5_etypes[i]->type;
676*ebfedea0SLionel Sambuc 	    return 0;
677*ebfedea0SLionel Sambuc 	}
678*ebfedea0SLionel Sambuc     krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
679*ebfedea0SLionel Sambuc 			    N_("encryption type %s not supported", ""),
680*ebfedea0SLionel Sambuc 			    string);
681*ebfedea0SLionel Sambuc     return KRB5_PROG_ETYPE_NOSUPP;
682*ebfedea0SLionel Sambuc }
683*ebfedea0SLionel Sambuc 
684*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
685*ebfedea0SLionel Sambuc krb5_enctype_to_keytype(krb5_context context,
686*ebfedea0SLionel Sambuc 			krb5_enctype etype,
687*ebfedea0SLionel Sambuc 			krb5_keytype *keytype)
688*ebfedea0SLionel Sambuc {
689*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
690*ebfedea0SLionel Sambuc     if(e == NULL) {
691*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
692*ebfedea0SLionel Sambuc 				N_("encryption type %d not supported", ""),
693*ebfedea0SLionel Sambuc 				etype);
694*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
695*ebfedea0SLionel Sambuc     }
696*ebfedea0SLionel Sambuc     *keytype = e->keytype->type; /* XXX */
697*ebfedea0SLionel Sambuc     return 0;
698*ebfedea0SLionel Sambuc }
699*ebfedea0SLionel Sambuc 
700*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
701*ebfedea0SLionel Sambuc krb5_enctype_valid(krb5_context context,
702*ebfedea0SLionel Sambuc 		   krb5_enctype etype)
703*ebfedea0SLionel Sambuc {
704*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *e = _krb5_find_enctype(etype);
705*ebfedea0SLionel Sambuc     if(e == NULL) {
706*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
707*ebfedea0SLionel Sambuc 				N_("encryption type %d not supported", ""),
708*ebfedea0SLionel Sambuc 				etype);
709*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
710*ebfedea0SLionel Sambuc     }
711*ebfedea0SLionel Sambuc     if (e->flags & F_DISABLED) {
712*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
713*ebfedea0SLionel Sambuc 				N_("encryption type %s is disabled", ""),
714*ebfedea0SLionel Sambuc 				e->name);
715*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
716*ebfedea0SLionel Sambuc     }
717*ebfedea0SLionel Sambuc     return 0;
718*ebfedea0SLionel Sambuc }
719*ebfedea0SLionel Sambuc 
720*ebfedea0SLionel Sambuc /**
721*ebfedea0SLionel Sambuc  * Return the coresponding encryption type for a checksum type.
722*ebfedea0SLionel Sambuc  *
723*ebfedea0SLionel Sambuc  * @param context Kerberos context
724*ebfedea0SLionel Sambuc  * @param ctype The checksum type to get the result enctype for
725*ebfedea0SLionel Sambuc  * @param etype The returned encryption, when the matching etype is
726*ebfedea0SLionel Sambuc  * not found, etype is set to ETYPE_NULL.
727*ebfedea0SLionel Sambuc  *
728*ebfedea0SLionel Sambuc  * @return Return an error code for an failure or 0 on success.
729*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
730*ebfedea0SLionel Sambuc  */
731*ebfedea0SLionel Sambuc 
732*ebfedea0SLionel Sambuc 
733*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
734*ebfedea0SLionel Sambuc krb5_cksumtype_to_enctype(krb5_context context,
735*ebfedea0SLionel Sambuc 			  krb5_cksumtype ctype,
736*ebfedea0SLionel Sambuc 			  krb5_enctype *etype)
737*ebfedea0SLionel Sambuc {
738*ebfedea0SLionel Sambuc     int i;
739*ebfedea0SLionel Sambuc 
740*ebfedea0SLionel Sambuc     *etype = ETYPE_NULL;
741*ebfedea0SLionel Sambuc 
742*ebfedea0SLionel Sambuc     for(i = 0; i < _krb5_num_etypes; i++) {
743*ebfedea0SLionel Sambuc 	if(_krb5_etypes[i]->keyed_checksum &&
744*ebfedea0SLionel Sambuc 	   _krb5_etypes[i]->keyed_checksum->type == ctype)
745*ebfedea0SLionel Sambuc 	    {
746*ebfedea0SLionel Sambuc 		*etype = _krb5_etypes[i]->type;
747*ebfedea0SLionel Sambuc 		return 0;
748*ebfedea0SLionel Sambuc 	    }
749*ebfedea0SLionel Sambuc     }
750*ebfedea0SLionel Sambuc 
751*ebfedea0SLionel Sambuc     krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
752*ebfedea0SLionel Sambuc 			    N_("checksum type %d not supported", ""),
753*ebfedea0SLionel Sambuc 			    (int)ctype);
754*ebfedea0SLionel Sambuc     return KRB5_PROG_SUMTYPE_NOSUPP;
755*ebfedea0SLionel Sambuc }
756*ebfedea0SLionel Sambuc 
757*ebfedea0SLionel Sambuc 
758*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
759*ebfedea0SLionel Sambuc krb5_cksumtype_valid(krb5_context context,
760*ebfedea0SLionel Sambuc 		     krb5_cksumtype ctype)
761*ebfedea0SLionel Sambuc {
762*ebfedea0SLionel Sambuc     struct _krb5_checksum_type *c = _krb5_find_checksum(ctype);
763*ebfedea0SLionel Sambuc     if (c == NULL) {
764*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
765*ebfedea0SLionel Sambuc 				N_("checksum type %d not supported", ""),
766*ebfedea0SLionel Sambuc 				ctype);
767*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
768*ebfedea0SLionel Sambuc     }
769*ebfedea0SLionel Sambuc     if (c->flags & F_DISABLED) {
770*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
771*ebfedea0SLionel Sambuc 				N_("checksum type %s is disabled", ""),
772*ebfedea0SLionel Sambuc 				c->name);
773*ebfedea0SLionel Sambuc 	return KRB5_PROG_SUMTYPE_NOSUPP;
774*ebfedea0SLionel Sambuc     }
775*ebfedea0SLionel Sambuc     return 0;
776*ebfedea0SLionel Sambuc }
777*ebfedea0SLionel Sambuc 
778*ebfedea0SLionel Sambuc 
779*ebfedea0SLionel Sambuc static krb5_boolean
780*ebfedea0SLionel Sambuc derived_crypto(krb5_context context,
781*ebfedea0SLionel Sambuc 	       krb5_crypto crypto)
782*ebfedea0SLionel Sambuc {
783*ebfedea0SLionel Sambuc     return (crypto->et->flags & F_DERIVED) != 0;
784*ebfedea0SLionel Sambuc }
785*ebfedea0SLionel Sambuc 
786*ebfedea0SLionel Sambuc static krb5_boolean
787*ebfedea0SLionel Sambuc special_crypto(krb5_context context,
788*ebfedea0SLionel Sambuc 	       krb5_crypto crypto)
789*ebfedea0SLionel Sambuc {
790*ebfedea0SLionel Sambuc     return (crypto->et->flags & F_SPECIAL) != 0;
791*ebfedea0SLionel Sambuc }
792*ebfedea0SLionel Sambuc 
793*ebfedea0SLionel Sambuc #define CHECKSUMSIZE(C) ((C)->checksumsize)
794*ebfedea0SLionel Sambuc #define CHECKSUMTYPE(C) ((C)->type)
795*ebfedea0SLionel Sambuc 
796*ebfedea0SLionel Sambuc static krb5_error_code
797*ebfedea0SLionel Sambuc encrypt_internal_derived(krb5_context context,
798*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
799*ebfedea0SLionel Sambuc 			 unsigned usage,
800*ebfedea0SLionel Sambuc 			 const void *data,
801*ebfedea0SLionel Sambuc 			 size_t len,
802*ebfedea0SLionel Sambuc 			 krb5_data *result,
803*ebfedea0SLionel Sambuc 			 void *ivec)
804*ebfedea0SLionel Sambuc {
805*ebfedea0SLionel Sambuc     size_t sz, block_sz, checksum_sz, total_sz;
806*ebfedea0SLionel Sambuc     Checksum cksum;
807*ebfedea0SLionel Sambuc     unsigned char *p, *q;
808*ebfedea0SLionel Sambuc     krb5_error_code ret;
809*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
810*ebfedea0SLionel Sambuc     const struct _krb5_encryption_type *et = crypto->et;
811*ebfedea0SLionel Sambuc 
812*ebfedea0SLionel Sambuc     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
813*ebfedea0SLionel Sambuc 
814*ebfedea0SLionel Sambuc     sz = et->confoundersize + len;
815*ebfedea0SLionel Sambuc     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
816*ebfedea0SLionel Sambuc     total_sz = block_sz + checksum_sz;
817*ebfedea0SLionel Sambuc     p = calloc(1, total_sz);
818*ebfedea0SLionel Sambuc     if(p == NULL) {
819*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
820*ebfedea0SLionel Sambuc 	return ENOMEM;
821*ebfedea0SLionel Sambuc     }
822*ebfedea0SLionel Sambuc 
823*ebfedea0SLionel Sambuc     q = p;
824*ebfedea0SLionel Sambuc     krb5_generate_random_block(q, et->confoundersize); /* XXX */
825*ebfedea0SLionel Sambuc     q += et->confoundersize;
826*ebfedea0SLionel Sambuc     memcpy(q, data, len);
827*ebfedea0SLionel Sambuc 
828*ebfedea0SLionel Sambuc     ret = create_checksum(context,
829*ebfedea0SLionel Sambuc 			  et->keyed_checksum,
830*ebfedea0SLionel Sambuc 			  crypto,
831*ebfedea0SLionel Sambuc 			  INTEGRITY_USAGE(usage),
832*ebfedea0SLionel Sambuc 			  p,
833*ebfedea0SLionel Sambuc 			  block_sz,
834*ebfedea0SLionel Sambuc 			  &cksum);
835*ebfedea0SLionel Sambuc     if(ret == 0 && cksum.checksum.length != checksum_sz) {
836*ebfedea0SLionel Sambuc 	free_Checksum (&cksum);
837*ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
838*ebfedea0SLionel Sambuc 	ret = KRB5_CRYPTO_INTERNAL;
839*ebfedea0SLionel Sambuc     }
840*ebfedea0SLionel Sambuc     if(ret)
841*ebfedea0SLionel Sambuc 	goto fail;
842*ebfedea0SLionel Sambuc     memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
843*ebfedea0SLionel Sambuc     free_Checksum (&cksum);
844*ebfedea0SLionel Sambuc     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
845*ebfedea0SLionel Sambuc     if(ret)
846*ebfedea0SLionel Sambuc 	goto fail;
847*ebfedea0SLionel Sambuc     ret = _key_schedule(context, dkey);
848*ebfedea0SLionel Sambuc     if(ret)
849*ebfedea0SLionel Sambuc 	goto fail;
850*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
851*ebfedea0SLionel Sambuc     if (ret)
852*ebfedea0SLionel Sambuc 	goto fail;
853*ebfedea0SLionel Sambuc     result->data = p;
854*ebfedea0SLionel Sambuc     result->length = total_sz;
855*ebfedea0SLionel Sambuc     return 0;
856*ebfedea0SLionel Sambuc  fail:
857*ebfedea0SLionel Sambuc     memset(p, 0, total_sz);
858*ebfedea0SLionel Sambuc     free(p);
859*ebfedea0SLionel Sambuc     return ret;
860*ebfedea0SLionel Sambuc }
861*ebfedea0SLionel Sambuc 
862*ebfedea0SLionel Sambuc 
863*ebfedea0SLionel Sambuc static krb5_error_code
864*ebfedea0SLionel Sambuc encrypt_internal(krb5_context context,
865*ebfedea0SLionel Sambuc 		 krb5_crypto crypto,
866*ebfedea0SLionel Sambuc 		 const void *data,
867*ebfedea0SLionel Sambuc 		 size_t len,
868*ebfedea0SLionel Sambuc 		 krb5_data *result,
869*ebfedea0SLionel Sambuc 		 void *ivec)
870*ebfedea0SLionel Sambuc {
871*ebfedea0SLionel Sambuc     size_t sz, block_sz, checksum_sz;
872*ebfedea0SLionel Sambuc     Checksum cksum;
873*ebfedea0SLionel Sambuc     unsigned char *p, *q;
874*ebfedea0SLionel Sambuc     krb5_error_code ret;
875*ebfedea0SLionel Sambuc     const struct _krb5_encryption_type *et = crypto->et;
876*ebfedea0SLionel Sambuc 
877*ebfedea0SLionel Sambuc     checksum_sz = CHECKSUMSIZE(et->checksum);
878*ebfedea0SLionel Sambuc 
879*ebfedea0SLionel Sambuc     sz = et->confoundersize + checksum_sz + len;
880*ebfedea0SLionel Sambuc     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
881*ebfedea0SLionel Sambuc     p = calloc(1, block_sz);
882*ebfedea0SLionel Sambuc     if(p == NULL) {
883*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
884*ebfedea0SLionel Sambuc 	return ENOMEM;
885*ebfedea0SLionel Sambuc     }
886*ebfedea0SLionel Sambuc 
887*ebfedea0SLionel Sambuc     q = p;
888*ebfedea0SLionel Sambuc     krb5_generate_random_block(q, et->confoundersize); /* XXX */
889*ebfedea0SLionel Sambuc     q += et->confoundersize;
890*ebfedea0SLionel Sambuc     memset(q, 0, checksum_sz);
891*ebfedea0SLionel Sambuc     q += checksum_sz;
892*ebfedea0SLionel Sambuc     memcpy(q, data, len);
893*ebfedea0SLionel Sambuc 
894*ebfedea0SLionel Sambuc     ret = create_checksum(context,
895*ebfedea0SLionel Sambuc 			  et->checksum,
896*ebfedea0SLionel Sambuc 			  crypto,
897*ebfedea0SLionel Sambuc 			  0,
898*ebfedea0SLionel Sambuc 			  p,
899*ebfedea0SLionel Sambuc 			  block_sz,
900*ebfedea0SLionel Sambuc 			  &cksum);
901*ebfedea0SLionel Sambuc     if(ret == 0 && cksum.checksum.length != checksum_sz) {
902*ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
903*ebfedea0SLionel Sambuc 	free_Checksum(&cksum);
904*ebfedea0SLionel Sambuc 	ret = KRB5_CRYPTO_INTERNAL;
905*ebfedea0SLionel Sambuc     }
906*ebfedea0SLionel Sambuc     if(ret)
907*ebfedea0SLionel Sambuc 	goto fail;
908*ebfedea0SLionel Sambuc     memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
909*ebfedea0SLionel Sambuc     free_Checksum(&cksum);
910*ebfedea0SLionel Sambuc     ret = _key_schedule(context, &crypto->key);
911*ebfedea0SLionel Sambuc     if(ret)
912*ebfedea0SLionel Sambuc 	goto fail;
913*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
914*ebfedea0SLionel Sambuc     if (ret) {
915*ebfedea0SLionel Sambuc 	memset(p, 0, block_sz);
916*ebfedea0SLionel Sambuc 	free(p);
917*ebfedea0SLionel Sambuc 	return ret;
918*ebfedea0SLionel Sambuc     }
919*ebfedea0SLionel Sambuc     result->data = p;
920*ebfedea0SLionel Sambuc     result->length = block_sz;
921*ebfedea0SLionel Sambuc     return 0;
922*ebfedea0SLionel Sambuc  fail:
923*ebfedea0SLionel Sambuc     memset(p, 0, block_sz);
924*ebfedea0SLionel Sambuc     free(p);
925*ebfedea0SLionel Sambuc     return ret;
926*ebfedea0SLionel Sambuc }
927*ebfedea0SLionel Sambuc 
928*ebfedea0SLionel Sambuc static krb5_error_code
929*ebfedea0SLionel Sambuc encrypt_internal_special(krb5_context context,
930*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
931*ebfedea0SLionel Sambuc 			 int usage,
932*ebfedea0SLionel Sambuc 			 const void *data,
933*ebfedea0SLionel Sambuc 			 size_t len,
934*ebfedea0SLionel Sambuc 			 krb5_data *result,
935*ebfedea0SLionel Sambuc 			 void *ivec)
936*ebfedea0SLionel Sambuc {
937*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
938*ebfedea0SLionel Sambuc     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
939*ebfedea0SLionel Sambuc     size_t sz = len + cksum_sz + et->confoundersize;
940*ebfedea0SLionel Sambuc     char *tmp, *p;
941*ebfedea0SLionel Sambuc     krb5_error_code ret;
942*ebfedea0SLionel Sambuc 
943*ebfedea0SLionel Sambuc     tmp = malloc (sz);
944*ebfedea0SLionel Sambuc     if (tmp == NULL) {
945*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
946*ebfedea0SLionel Sambuc 	return ENOMEM;
947*ebfedea0SLionel Sambuc     }
948*ebfedea0SLionel Sambuc     p = tmp;
949*ebfedea0SLionel Sambuc     memset (p, 0, cksum_sz);
950*ebfedea0SLionel Sambuc     p += cksum_sz;
951*ebfedea0SLionel Sambuc     krb5_generate_random_block(p, et->confoundersize);
952*ebfedea0SLionel Sambuc     p += et->confoundersize;
953*ebfedea0SLionel Sambuc     memcpy (p, data, len);
954*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
955*ebfedea0SLionel Sambuc     if (ret) {
956*ebfedea0SLionel Sambuc 	memset(tmp, 0, sz);
957*ebfedea0SLionel Sambuc 	free(tmp);
958*ebfedea0SLionel Sambuc 	return ret;
959*ebfedea0SLionel Sambuc     }
960*ebfedea0SLionel Sambuc     result->data   = tmp;
961*ebfedea0SLionel Sambuc     result->length = sz;
962*ebfedea0SLionel Sambuc     return 0;
963*ebfedea0SLionel Sambuc }
964*ebfedea0SLionel Sambuc 
965*ebfedea0SLionel Sambuc static krb5_error_code
966*ebfedea0SLionel Sambuc decrypt_internal_derived(krb5_context context,
967*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
968*ebfedea0SLionel Sambuc 			 unsigned usage,
969*ebfedea0SLionel Sambuc 			 void *data,
970*ebfedea0SLionel Sambuc 			 size_t len,
971*ebfedea0SLionel Sambuc 			 krb5_data *result,
972*ebfedea0SLionel Sambuc 			 void *ivec)
973*ebfedea0SLionel Sambuc {
974*ebfedea0SLionel Sambuc     size_t checksum_sz;
975*ebfedea0SLionel Sambuc     Checksum cksum;
976*ebfedea0SLionel Sambuc     unsigned char *p;
977*ebfedea0SLionel Sambuc     krb5_error_code ret;
978*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
979*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
980*ebfedea0SLionel Sambuc     unsigned long l;
981*ebfedea0SLionel Sambuc 
982*ebfedea0SLionel Sambuc     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
983*ebfedea0SLionel Sambuc     if (len < checksum_sz + et->confoundersize) {
984*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
985*ebfedea0SLionel Sambuc 			       N_("Encrypted data shorter then "
986*ebfedea0SLionel Sambuc 				  "checksum + confunder", ""));
987*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
988*ebfedea0SLionel Sambuc     }
989*ebfedea0SLionel Sambuc 
990*ebfedea0SLionel Sambuc     if (((len - checksum_sz) % et->padsize) != 0) {
991*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
992*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
993*ebfedea0SLionel Sambuc     }
994*ebfedea0SLionel Sambuc 
995*ebfedea0SLionel Sambuc     p = malloc(len);
996*ebfedea0SLionel Sambuc     if(len != 0 && p == NULL) {
997*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
998*ebfedea0SLionel Sambuc 	return ENOMEM;
999*ebfedea0SLionel Sambuc     }
1000*ebfedea0SLionel Sambuc     memcpy(p, data, len);
1001*ebfedea0SLionel Sambuc 
1002*ebfedea0SLionel Sambuc     len -= checksum_sz;
1003*ebfedea0SLionel Sambuc 
1004*ebfedea0SLionel Sambuc     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1005*ebfedea0SLionel Sambuc     if(ret) {
1006*ebfedea0SLionel Sambuc 	free(p);
1007*ebfedea0SLionel Sambuc 	return ret;
1008*ebfedea0SLionel Sambuc     }
1009*ebfedea0SLionel Sambuc     ret = _key_schedule(context, dkey);
1010*ebfedea0SLionel Sambuc     if(ret) {
1011*ebfedea0SLionel Sambuc 	free(p);
1012*ebfedea0SLionel Sambuc 	return ret;
1013*ebfedea0SLionel Sambuc     }
1014*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1015*ebfedea0SLionel Sambuc     if (ret) {
1016*ebfedea0SLionel Sambuc 	free(p);
1017*ebfedea0SLionel Sambuc 	return ret;
1018*ebfedea0SLionel Sambuc     }
1019*ebfedea0SLionel Sambuc 
1020*ebfedea0SLionel Sambuc     cksum.checksum.data   = p + len;
1021*ebfedea0SLionel Sambuc     cksum.checksum.length = checksum_sz;
1022*ebfedea0SLionel Sambuc     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
1023*ebfedea0SLionel Sambuc 
1024*ebfedea0SLionel Sambuc     ret = verify_checksum(context,
1025*ebfedea0SLionel Sambuc 			  crypto,
1026*ebfedea0SLionel Sambuc 			  INTEGRITY_USAGE(usage),
1027*ebfedea0SLionel Sambuc 			  p,
1028*ebfedea0SLionel Sambuc 			  len,
1029*ebfedea0SLionel Sambuc 			  &cksum);
1030*ebfedea0SLionel Sambuc     if(ret) {
1031*ebfedea0SLionel Sambuc 	free(p);
1032*ebfedea0SLionel Sambuc 	return ret;
1033*ebfedea0SLionel Sambuc     }
1034*ebfedea0SLionel Sambuc     l = len - et->confoundersize;
1035*ebfedea0SLionel Sambuc     memmove(p, p + et->confoundersize, l);
1036*ebfedea0SLionel Sambuc     result->data = realloc(p, l);
1037*ebfedea0SLionel Sambuc     if(result->data == NULL && l != 0) {
1038*ebfedea0SLionel Sambuc 	free(p);
1039*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1040*ebfedea0SLionel Sambuc 	return ENOMEM;
1041*ebfedea0SLionel Sambuc     }
1042*ebfedea0SLionel Sambuc     result->length = l;
1043*ebfedea0SLionel Sambuc     return 0;
1044*ebfedea0SLionel Sambuc }
1045*ebfedea0SLionel Sambuc 
1046*ebfedea0SLionel Sambuc static krb5_error_code
1047*ebfedea0SLionel Sambuc decrypt_internal(krb5_context context,
1048*ebfedea0SLionel Sambuc 		 krb5_crypto crypto,
1049*ebfedea0SLionel Sambuc 		 void *data,
1050*ebfedea0SLionel Sambuc 		 size_t len,
1051*ebfedea0SLionel Sambuc 		 krb5_data *result,
1052*ebfedea0SLionel Sambuc 		 void *ivec)
1053*ebfedea0SLionel Sambuc {
1054*ebfedea0SLionel Sambuc     krb5_error_code ret;
1055*ebfedea0SLionel Sambuc     unsigned char *p;
1056*ebfedea0SLionel Sambuc     Checksum cksum;
1057*ebfedea0SLionel Sambuc     size_t checksum_sz, l;
1058*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
1059*ebfedea0SLionel Sambuc 
1060*ebfedea0SLionel Sambuc     if ((len % et->padsize) != 0) {
1061*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1062*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1063*ebfedea0SLionel Sambuc     }
1064*ebfedea0SLionel Sambuc     checksum_sz = CHECKSUMSIZE(et->checksum);
1065*ebfedea0SLionel Sambuc     if (len < checksum_sz + et->confoundersize) {
1066*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1067*ebfedea0SLionel Sambuc 			       N_("Encrypted data shorter then "
1068*ebfedea0SLionel Sambuc 				  "checksum + confunder", ""));
1069*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1070*ebfedea0SLionel Sambuc     }
1071*ebfedea0SLionel Sambuc 
1072*ebfedea0SLionel Sambuc     p = malloc(len);
1073*ebfedea0SLionel Sambuc     if(len != 0 && p == NULL) {
1074*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1075*ebfedea0SLionel Sambuc 	return ENOMEM;
1076*ebfedea0SLionel Sambuc     }
1077*ebfedea0SLionel Sambuc     memcpy(p, data, len);
1078*ebfedea0SLionel Sambuc 
1079*ebfedea0SLionel Sambuc     ret = _key_schedule(context, &crypto->key);
1080*ebfedea0SLionel Sambuc     if(ret) {
1081*ebfedea0SLionel Sambuc 	free(p);
1082*ebfedea0SLionel Sambuc 	return ret;
1083*ebfedea0SLionel Sambuc     }
1084*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
1085*ebfedea0SLionel Sambuc     if (ret) {
1086*ebfedea0SLionel Sambuc 	free(p);
1087*ebfedea0SLionel Sambuc 	return ret;
1088*ebfedea0SLionel Sambuc     }
1089*ebfedea0SLionel Sambuc     ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
1090*ebfedea0SLionel Sambuc     if(ret) {
1091*ebfedea0SLionel Sambuc  	free(p);
1092*ebfedea0SLionel Sambuc  	return ret;
1093*ebfedea0SLionel Sambuc     }
1094*ebfedea0SLionel Sambuc     memset(p + et->confoundersize, 0, checksum_sz);
1095*ebfedea0SLionel Sambuc     cksum.cksumtype = CHECKSUMTYPE(et->checksum);
1096*ebfedea0SLionel Sambuc     ret = verify_checksum(context, NULL, 0, p, len, &cksum);
1097*ebfedea0SLionel Sambuc     free_Checksum(&cksum);
1098*ebfedea0SLionel Sambuc     if(ret) {
1099*ebfedea0SLionel Sambuc 	free(p);
1100*ebfedea0SLionel Sambuc 	return ret;
1101*ebfedea0SLionel Sambuc     }
1102*ebfedea0SLionel Sambuc     l = len - et->confoundersize - checksum_sz;
1103*ebfedea0SLionel Sambuc     memmove(p, p + et->confoundersize + checksum_sz, l);
1104*ebfedea0SLionel Sambuc     result->data = realloc(p, l);
1105*ebfedea0SLionel Sambuc     if(result->data == NULL && l != 0) {
1106*ebfedea0SLionel Sambuc 	free(p);
1107*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1108*ebfedea0SLionel Sambuc 	return ENOMEM;
1109*ebfedea0SLionel Sambuc     }
1110*ebfedea0SLionel Sambuc     result->length = l;
1111*ebfedea0SLionel Sambuc     return 0;
1112*ebfedea0SLionel Sambuc }
1113*ebfedea0SLionel Sambuc 
1114*ebfedea0SLionel Sambuc static krb5_error_code
1115*ebfedea0SLionel Sambuc decrypt_internal_special(krb5_context context,
1116*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
1117*ebfedea0SLionel Sambuc 			 int usage,
1118*ebfedea0SLionel Sambuc 			 void *data,
1119*ebfedea0SLionel Sambuc 			 size_t len,
1120*ebfedea0SLionel Sambuc 			 krb5_data *result,
1121*ebfedea0SLionel Sambuc 			 void *ivec)
1122*ebfedea0SLionel Sambuc {
1123*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
1124*ebfedea0SLionel Sambuc     size_t cksum_sz = CHECKSUMSIZE(et->checksum);
1125*ebfedea0SLionel Sambuc     size_t sz = len - cksum_sz - et->confoundersize;
1126*ebfedea0SLionel Sambuc     unsigned char *p;
1127*ebfedea0SLionel Sambuc     krb5_error_code ret;
1128*ebfedea0SLionel Sambuc 
1129*ebfedea0SLionel Sambuc     if ((len % et->padsize) != 0) {
1130*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1131*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1132*ebfedea0SLionel Sambuc     }
1133*ebfedea0SLionel Sambuc     if (len < cksum_sz + et->confoundersize) {
1134*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1135*ebfedea0SLionel Sambuc 			       N_("Encrypted data shorter then "
1136*ebfedea0SLionel Sambuc 				  "checksum + confunder", ""));
1137*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1138*ebfedea0SLionel Sambuc     }
1139*ebfedea0SLionel Sambuc 
1140*ebfedea0SLionel Sambuc     p = malloc (len);
1141*ebfedea0SLionel Sambuc     if (p == NULL) {
1142*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1143*ebfedea0SLionel Sambuc 	return ENOMEM;
1144*ebfedea0SLionel Sambuc     }
1145*ebfedea0SLionel Sambuc     memcpy(p, data, len);
1146*ebfedea0SLionel Sambuc 
1147*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
1148*ebfedea0SLionel Sambuc     if (ret) {
1149*ebfedea0SLionel Sambuc 	free(p);
1150*ebfedea0SLionel Sambuc 	return ret;
1151*ebfedea0SLionel Sambuc     }
1152*ebfedea0SLionel Sambuc 
1153*ebfedea0SLionel Sambuc     memmove (p, p + cksum_sz + et->confoundersize, sz);
1154*ebfedea0SLionel Sambuc     result->data = realloc(p, sz);
1155*ebfedea0SLionel Sambuc     if(result->data == NULL && sz != 0) {
1156*ebfedea0SLionel Sambuc 	free(p);
1157*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
1158*ebfedea0SLionel Sambuc 	return ENOMEM;
1159*ebfedea0SLionel Sambuc     }
1160*ebfedea0SLionel Sambuc     result->length = sz;
1161*ebfedea0SLionel Sambuc     return 0;
1162*ebfedea0SLionel Sambuc }
1163*ebfedea0SLionel Sambuc 
1164*ebfedea0SLionel Sambuc static krb5_crypto_iov *
1165*ebfedea0SLionel Sambuc find_iv(krb5_crypto_iov *data, int num_data, int type)
1166*ebfedea0SLionel Sambuc {
1167*ebfedea0SLionel Sambuc     int i;
1168*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++)
1169*ebfedea0SLionel Sambuc 	if (data[i].flags == type)
1170*ebfedea0SLionel Sambuc 	    return &data[i];
1171*ebfedea0SLionel Sambuc     return NULL;
1172*ebfedea0SLionel Sambuc }
1173*ebfedea0SLionel Sambuc 
1174*ebfedea0SLionel Sambuc /**
1175*ebfedea0SLionel Sambuc  * Inline encrypt a kerberos message
1176*ebfedea0SLionel Sambuc  *
1177*ebfedea0SLionel Sambuc  * @param context Kerberos context
1178*ebfedea0SLionel Sambuc  * @param crypto Kerberos crypto context
1179*ebfedea0SLionel Sambuc  * @param usage Key usage for this buffer
1180*ebfedea0SLionel Sambuc  * @param data array of buffers to process
1181*ebfedea0SLionel Sambuc  * @param num_data length of array
1182*ebfedea0SLionel Sambuc  * @param ivec initial cbc/cts vector
1183*ebfedea0SLionel Sambuc  *
1184*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
1185*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
1186*ebfedea0SLionel Sambuc  *
1187*ebfedea0SLionel Sambuc  * Kerberos encrypted data look like this:
1188*ebfedea0SLionel Sambuc  *
1189*ebfedea0SLionel Sambuc  * 1. KRB5_CRYPTO_TYPE_HEADER
1190*ebfedea0SLionel Sambuc  * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
1191*ebfedea0SLionel Sambuc  *    KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
1192*ebfedea0SLionel Sambuc  *    have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
1193*ebfedea0SLionel Sambuc  *    commonly used headers and trailers.
1194*ebfedea0SLionel Sambuc  * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
1195*ebfedea0SLionel Sambuc  * 4. KRB5_CRYPTO_TYPE_TRAILER
1196*ebfedea0SLionel Sambuc  */
1197*ebfedea0SLionel Sambuc 
1198*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1199*ebfedea0SLionel Sambuc krb5_encrypt_iov_ivec(krb5_context context,
1200*ebfedea0SLionel Sambuc 		      krb5_crypto crypto,
1201*ebfedea0SLionel Sambuc 		      unsigned usage,
1202*ebfedea0SLionel Sambuc 		      krb5_crypto_iov *data,
1203*ebfedea0SLionel Sambuc 		      int num_data,
1204*ebfedea0SLionel Sambuc 		      void *ivec)
1205*ebfedea0SLionel Sambuc {
1206*ebfedea0SLionel Sambuc     size_t headersz, trailersz, len;
1207*ebfedea0SLionel Sambuc     int i;
1208*ebfedea0SLionel Sambuc     size_t sz, block_sz, pad_sz;
1209*ebfedea0SLionel Sambuc     Checksum cksum;
1210*ebfedea0SLionel Sambuc     unsigned char *p, *q;
1211*ebfedea0SLionel Sambuc     krb5_error_code ret;
1212*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
1213*ebfedea0SLionel Sambuc     const struct _krb5_encryption_type *et = crypto->et;
1214*ebfedea0SLionel Sambuc     krb5_crypto_iov *tiv, *piv, *hiv;
1215*ebfedea0SLionel Sambuc 
1216*ebfedea0SLionel Sambuc     if (num_data < 0) {
1217*ebfedea0SLionel Sambuc         krb5_clear_error_message(context);
1218*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1219*ebfedea0SLionel Sambuc     }
1220*ebfedea0SLionel Sambuc 
1221*ebfedea0SLionel Sambuc     if(!derived_crypto(context, crypto)) {
1222*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1223*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1224*ebfedea0SLionel Sambuc     }
1225*ebfedea0SLionel Sambuc 
1226*ebfedea0SLionel Sambuc     headersz = et->confoundersize;
1227*ebfedea0SLionel Sambuc     trailersz = CHECKSUMSIZE(et->keyed_checksum);
1228*ebfedea0SLionel Sambuc 
1229*ebfedea0SLionel Sambuc     for (len = 0, i = 0; i < num_data; i++) {
1230*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1231*ebfedea0SLionel Sambuc 	    continue;
1232*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1233*ebfedea0SLionel Sambuc     }
1234*ebfedea0SLionel Sambuc 
1235*ebfedea0SLionel Sambuc     sz = headersz + len;
1236*ebfedea0SLionel Sambuc     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
1237*ebfedea0SLionel Sambuc 
1238*ebfedea0SLionel Sambuc     pad_sz = block_sz - sz;
1239*ebfedea0SLionel Sambuc 
1240*ebfedea0SLionel Sambuc     /* header */
1241*ebfedea0SLionel Sambuc 
1242*ebfedea0SLionel Sambuc     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1243*ebfedea0SLionel Sambuc     if (hiv == NULL || hiv->data.length != headersz)
1244*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1245*ebfedea0SLionel Sambuc 
1246*ebfedea0SLionel Sambuc     krb5_generate_random_block(hiv->data.data, hiv->data.length);
1247*ebfedea0SLionel Sambuc 
1248*ebfedea0SLionel Sambuc     /* padding */
1249*ebfedea0SLionel Sambuc     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
1250*ebfedea0SLionel Sambuc     /* its ok to have no TYPE_PADDING if there is no padding */
1251*ebfedea0SLionel Sambuc     if (piv == NULL && pad_sz != 0)
1252*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1253*ebfedea0SLionel Sambuc     if (piv) {
1254*ebfedea0SLionel Sambuc 	if (piv->data.length < pad_sz)
1255*ebfedea0SLionel Sambuc 	    return KRB5_BAD_MSIZE;
1256*ebfedea0SLionel Sambuc 	piv->data.length = pad_sz;
1257*ebfedea0SLionel Sambuc 	if (pad_sz)
1258*ebfedea0SLionel Sambuc 	    memset(piv->data.data, pad_sz, pad_sz);
1259*ebfedea0SLionel Sambuc 	else
1260*ebfedea0SLionel Sambuc 	    piv = NULL;
1261*ebfedea0SLionel Sambuc     }
1262*ebfedea0SLionel Sambuc 
1263*ebfedea0SLionel Sambuc     /* trailer */
1264*ebfedea0SLionel Sambuc     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1265*ebfedea0SLionel Sambuc     if (tiv == NULL || tiv->data.length != trailersz)
1266*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1267*ebfedea0SLionel Sambuc 
1268*ebfedea0SLionel Sambuc     /*
1269*ebfedea0SLionel Sambuc      * XXX replace with EVP_Sign? at least make create_checksum an iov
1270*ebfedea0SLionel Sambuc      * function.
1271*ebfedea0SLionel Sambuc      * XXX CTS EVP is broken, can't handle multi buffers :(
1272*ebfedea0SLionel Sambuc      */
1273*ebfedea0SLionel Sambuc 
1274*ebfedea0SLionel Sambuc     len = block_sz;
1275*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1276*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1277*ebfedea0SLionel Sambuc 	    continue;
1278*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1279*ebfedea0SLionel Sambuc     }
1280*ebfedea0SLionel Sambuc 
1281*ebfedea0SLionel Sambuc     p = q = malloc(len);
1282*ebfedea0SLionel Sambuc 
1283*ebfedea0SLionel Sambuc     memcpy(q, hiv->data.data, hiv->data.length);
1284*ebfedea0SLionel Sambuc     q += hiv->data.length;
1285*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1286*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1287*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1288*ebfedea0SLionel Sambuc 	    continue;
1289*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1290*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1291*ebfedea0SLionel Sambuc     }
1292*ebfedea0SLionel Sambuc     if (piv)
1293*ebfedea0SLionel Sambuc 	memset(q, 0, piv->data.length);
1294*ebfedea0SLionel Sambuc 
1295*ebfedea0SLionel Sambuc     ret = create_checksum(context,
1296*ebfedea0SLionel Sambuc 			  et->keyed_checksum,
1297*ebfedea0SLionel Sambuc 			  crypto,
1298*ebfedea0SLionel Sambuc 			  INTEGRITY_USAGE(usage),
1299*ebfedea0SLionel Sambuc 			  p,
1300*ebfedea0SLionel Sambuc 			  len,
1301*ebfedea0SLionel Sambuc 			  &cksum);
1302*ebfedea0SLionel Sambuc     free(p);
1303*ebfedea0SLionel Sambuc     if(ret == 0 && cksum.checksum.length != trailersz) {
1304*ebfedea0SLionel Sambuc 	free_Checksum (&cksum);
1305*ebfedea0SLionel Sambuc 	krb5_clear_error_message (context);
1306*ebfedea0SLionel Sambuc 	ret = KRB5_CRYPTO_INTERNAL;
1307*ebfedea0SLionel Sambuc     }
1308*ebfedea0SLionel Sambuc     if(ret)
1309*ebfedea0SLionel Sambuc 	return ret;
1310*ebfedea0SLionel Sambuc 
1311*ebfedea0SLionel Sambuc     /* save cksum at end */
1312*ebfedea0SLionel Sambuc     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
1313*ebfedea0SLionel Sambuc     free_Checksum (&cksum);
1314*ebfedea0SLionel Sambuc 
1315*ebfedea0SLionel Sambuc     /* XXX replace with EVP_Cipher */
1316*ebfedea0SLionel Sambuc     p = q = malloc(block_sz);
1317*ebfedea0SLionel Sambuc     if(p == NULL)
1318*ebfedea0SLionel Sambuc 	return ENOMEM;
1319*ebfedea0SLionel Sambuc 
1320*ebfedea0SLionel Sambuc     memcpy(q, hiv->data.data, hiv->data.length);
1321*ebfedea0SLionel Sambuc     q += hiv->data.length;
1322*ebfedea0SLionel Sambuc 
1323*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1324*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1325*ebfedea0SLionel Sambuc 	    continue;
1326*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1327*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1328*ebfedea0SLionel Sambuc     }
1329*ebfedea0SLionel Sambuc     if (piv)
1330*ebfedea0SLionel Sambuc 	memset(q, 0, piv->data.length);
1331*ebfedea0SLionel Sambuc 
1332*ebfedea0SLionel Sambuc 
1333*ebfedea0SLionel Sambuc     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1334*ebfedea0SLionel Sambuc     if(ret) {
1335*ebfedea0SLionel Sambuc 	free(p);
1336*ebfedea0SLionel Sambuc 	return ret;
1337*ebfedea0SLionel Sambuc     }
1338*ebfedea0SLionel Sambuc     ret = _key_schedule(context, dkey);
1339*ebfedea0SLionel Sambuc     if(ret) {
1340*ebfedea0SLionel Sambuc 	free(p);
1341*ebfedea0SLionel Sambuc 	return ret;
1342*ebfedea0SLionel Sambuc     }
1343*ebfedea0SLionel Sambuc 
1344*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
1345*ebfedea0SLionel Sambuc     if (ret) {
1346*ebfedea0SLionel Sambuc 	free(p);
1347*ebfedea0SLionel Sambuc 	return ret;
1348*ebfedea0SLionel Sambuc     }
1349*ebfedea0SLionel Sambuc 
1350*ebfedea0SLionel Sambuc     /* now copy data back to buffers */
1351*ebfedea0SLionel Sambuc     q = p;
1352*ebfedea0SLionel Sambuc 
1353*ebfedea0SLionel Sambuc     memcpy(hiv->data.data, q, hiv->data.length);
1354*ebfedea0SLionel Sambuc     q += hiv->data.length;
1355*ebfedea0SLionel Sambuc 
1356*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1357*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1358*ebfedea0SLionel Sambuc 	    continue;
1359*ebfedea0SLionel Sambuc 	memcpy(data[i].data.data, q, data[i].data.length);
1360*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1361*ebfedea0SLionel Sambuc     }
1362*ebfedea0SLionel Sambuc     if (piv)
1363*ebfedea0SLionel Sambuc 	memcpy(piv->data.data, q, pad_sz);
1364*ebfedea0SLionel Sambuc 
1365*ebfedea0SLionel Sambuc     free(p);
1366*ebfedea0SLionel Sambuc 
1367*ebfedea0SLionel Sambuc     return ret;
1368*ebfedea0SLionel Sambuc }
1369*ebfedea0SLionel Sambuc 
1370*ebfedea0SLionel Sambuc /**
1371*ebfedea0SLionel Sambuc  * Inline decrypt a Kerberos message.
1372*ebfedea0SLionel Sambuc  *
1373*ebfedea0SLionel Sambuc  * @param context Kerberos context
1374*ebfedea0SLionel Sambuc  * @param crypto Kerberos crypto context
1375*ebfedea0SLionel Sambuc  * @param usage Key usage for this buffer
1376*ebfedea0SLionel Sambuc  * @param data array of buffers to process
1377*ebfedea0SLionel Sambuc  * @param num_data length of array
1378*ebfedea0SLionel Sambuc  * @param ivec initial cbc/cts vector
1379*ebfedea0SLionel Sambuc  *
1380*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
1381*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
1382*ebfedea0SLionel Sambuc  *
1383*ebfedea0SLionel Sambuc  * 1. KRB5_CRYPTO_TYPE_HEADER
1384*ebfedea0SLionel Sambuc  * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
1385*ebfedea0SLionel Sambuc  *  any order, however the receiver have to aware of the
1386*ebfedea0SLionel Sambuc  *  order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
1387*ebfedea0SLionel Sambuc  *  protocol headers and trailers. The output data will be of same
1388*ebfedea0SLionel Sambuc  *  size as the input data or shorter.
1389*ebfedea0SLionel Sambuc  */
1390*ebfedea0SLionel Sambuc 
1391*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1392*ebfedea0SLionel Sambuc krb5_decrypt_iov_ivec(krb5_context context,
1393*ebfedea0SLionel Sambuc 		      krb5_crypto crypto,
1394*ebfedea0SLionel Sambuc 		      unsigned usage,
1395*ebfedea0SLionel Sambuc 		      krb5_crypto_iov *data,
1396*ebfedea0SLionel Sambuc 		      unsigned int num_data,
1397*ebfedea0SLionel Sambuc 		      void *ivec)
1398*ebfedea0SLionel Sambuc {
1399*ebfedea0SLionel Sambuc     unsigned int i;
1400*ebfedea0SLionel Sambuc     size_t headersz, trailersz, len;
1401*ebfedea0SLionel Sambuc     Checksum cksum;
1402*ebfedea0SLionel Sambuc     unsigned char *p, *q;
1403*ebfedea0SLionel Sambuc     krb5_error_code ret;
1404*ebfedea0SLionel Sambuc     struct _krb5_key_data *dkey;
1405*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
1406*ebfedea0SLionel Sambuc     krb5_crypto_iov *tiv, *hiv;
1407*ebfedea0SLionel Sambuc 
1408*ebfedea0SLionel Sambuc     if (num_data < 0) {
1409*ebfedea0SLionel Sambuc         krb5_clear_error_message(context);
1410*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1411*ebfedea0SLionel Sambuc     }
1412*ebfedea0SLionel Sambuc 
1413*ebfedea0SLionel Sambuc     if(!derived_crypto(context, crypto)) {
1414*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1415*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1416*ebfedea0SLionel Sambuc     }
1417*ebfedea0SLionel Sambuc 
1418*ebfedea0SLionel Sambuc     headersz = et->confoundersize;
1419*ebfedea0SLionel Sambuc 
1420*ebfedea0SLionel Sambuc     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
1421*ebfedea0SLionel Sambuc     if (hiv == NULL || hiv->data.length != headersz)
1422*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1423*ebfedea0SLionel Sambuc 
1424*ebfedea0SLionel Sambuc     /* trailer */
1425*ebfedea0SLionel Sambuc     trailersz = CHECKSUMSIZE(et->keyed_checksum);
1426*ebfedea0SLionel Sambuc 
1427*ebfedea0SLionel Sambuc     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
1428*ebfedea0SLionel Sambuc     if (tiv->data.length != trailersz)
1429*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1430*ebfedea0SLionel Sambuc 
1431*ebfedea0SLionel Sambuc     /* Find length of data we will decrypt */
1432*ebfedea0SLionel Sambuc 
1433*ebfedea0SLionel Sambuc     len = headersz;
1434*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1435*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1436*ebfedea0SLionel Sambuc 	    continue;
1437*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1438*ebfedea0SLionel Sambuc     }
1439*ebfedea0SLionel Sambuc 
1440*ebfedea0SLionel Sambuc     if ((len % et->padsize) != 0) {
1441*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1442*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1443*ebfedea0SLionel Sambuc     }
1444*ebfedea0SLionel Sambuc 
1445*ebfedea0SLionel Sambuc     /* XXX replace with EVP_Cipher */
1446*ebfedea0SLionel Sambuc 
1447*ebfedea0SLionel Sambuc     p = q = malloc(len);
1448*ebfedea0SLionel Sambuc     if (p == NULL)
1449*ebfedea0SLionel Sambuc 	return ENOMEM;
1450*ebfedea0SLionel Sambuc 
1451*ebfedea0SLionel Sambuc     memcpy(q, hiv->data.data, hiv->data.length);
1452*ebfedea0SLionel Sambuc     q += hiv->data.length;
1453*ebfedea0SLionel Sambuc 
1454*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1455*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1456*ebfedea0SLionel Sambuc 	    continue;
1457*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1458*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1459*ebfedea0SLionel Sambuc     }
1460*ebfedea0SLionel Sambuc 
1461*ebfedea0SLionel Sambuc     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
1462*ebfedea0SLionel Sambuc     if(ret) {
1463*ebfedea0SLionel Sambuc 	free(p);
1464*ebfedea0SLionel Sambuc 	return ret;
1465*ebfedea0SLionel Sambuc     }
1466*ebfedea0SLionel Sambuc     ret = _key_schedule(context, dkey);
1467*ebfedea0SLionel Sambuc     if(ret) {
1468*ebfedea0SLionel Sambuc 	free(p);
1469*ebfedea0SLionel Sambuc 	return ret;
1470*ebfedea0SLionel Sambuc     }
1471*ebfedea0SLionel Sambuc 
1472*ebfedea0SLionel Sambuc     ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
1473*ebfedea0SLionel Sambuc     if (ret) {
1474*ebfedea0SLionel Sambuc 	free(p);
1475*ebfedea0SLionel Sambuc 	return ret;
1476*ebfedea0SLionel Sambuc     }
1477*ebfedea0SLionel Sambuc 
1478*ebfedea0SLionel Sambuc     /* copy data back to buffers */
1479*ebfedea0SLionel Sambuc     memcpy(hiv->data.data, p, hiv->data.length);
1480*ebfedea0SLionel Sambuc     q = p + hiv->data.length;
1481*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1482*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
1483*ebfedea0SLionel Sambuc 	    continue;
1484*ebfedea0SLionel Sambuc 	memcpy(data[i].data.data, q, data[i].data.length);
1485*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1486*ebfedea0SLionel Sambuc     }
1487*ebfedea0SLionel Sambuc 
1488*ebfedea0SLionel Sambuc     free(p);
1489*ebfedea0SLionel Sambuc 
1490*ebfedea0SLionel Sambuc     /* check signature */
1491*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1492*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1493*ebfedea0SLionel Sambuc 	    continue;
1494*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1495*ebfedea0SLionel Sambuc     }
1496*ebfedea0SLionel Sambuc 
1497*ebfedea0SLionel Sambuc     p = q = malloc(len);
1498*ebfedea0SLionel Sambuc     if (p == NULL)
1499*ebfedea0SLionel Sambuc 	return ENOMEM;
1500*ebfedea0SLionel Sambuc 
1501*ebfedea0SLionel Sambuc     memcpy(q, hiv->data.data, hiv->data.length);
1502*ebfedea0SLionel Sambuc     q += hiv->data.length;
1503*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1504*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1505*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1506*ebfedea0SLionel Sambuc 	    continue;
1507*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1508*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1509*ebfedea0SLionel Sambuc     }
1510*ebfedea0SLionel Sambuc 
1511*ebfedea0SLionel Sambuc     cksum.checksum.data   = tiv->data.data;
1512*ebfedea0SLionel Sambuc     cksum.checksum.length = tiv->data.length;
1513*ebfedea0SLionel Sambuc     cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
1514*ebfedea0SLionel Sambuc 
1515*ebfedea0SLionel Sambuc     ret = verify_checksum(context,
1516*ebfedea0SLionel Sambuc 			  crypto,
1517*ebfedea0SLionel Sambuc 			  INTEGRITY_USAGE(usage),
1518*ebfedea0SLionel Sambuc 			  p,
1519*ebfedea0SLionel Sambuc 			  len,
1520*ebfedea0SLionel Sambuc 			  &cksum);
1521*ebfedea0SLionel Sambuc     free(p);
1522*ebfedea0SLionel Sambuc     return ret;
1523*ebfedea0SLionel Sambuc }
1524*ebfedea0SLionel Sambuc 
1525*ebfedea0SLionel Sambuc /**
1526*ebfedea0SLionel Sambuc  * Create a Kerberos message checksum.
1527*ebfedea0SLionel Sambuc  *
1528*ebfedea0SLionel Sambuc  * @param context Kerberos context
1529*ebfedea0SLionel Sambuc  * @param crypto Kerberos crypto context
1530*ebfedea0SLionel Sambuc  * @param usage Key usage for this buffer
1531*ebfedea0SLionel Sambuc  * @param data array of buffers to process
1532*ebfedea0SLionel Sambuc  * @param num_data length of array
1533*ebfedea0SLionel Sambuc  * @param type output data
1534*ebfedea0SLionel Sambuc  *
1535*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
1536*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
1537*ebfedea0SLionel Sambuc  */
1538*ebfedea0SLionel Sambuc 
1539*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1540*ebfedea0SLionel Sambuc krb5_create_checksum_iov(krb5_context context,
1541*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
1542*ebfedea0SLionel Sambuc 			 unsigned usage,
1543*ebfedea0SLionel Sambuc 			 krb5_crypto_iov *data,
1544*ebfedea0SLionel Sambuc 			 unsigned int num_data,
1545*ebfedea0SLionel Sambuc 			 krb5_cksumtype *type)
1546*ebfedea0SLionel Sambuc {
1547*ebfedea0SLionel Sambuc     Checksum cksum;
1548*ebfedea0SLionel Sambuc     krb5_crypto_iov *civ;
1549*ebfedea0SLionel Sambuc     krb5_error_code ret;
1550*ebfedea0SLionel Sambuc     int i;
1551*ebfedea0SLionel Sambuc     size_t len;
1552*ebfedea0SLionel Sambuc     char *p, *q;
1553*ebfedea0SLionel Sambuc 
1554*ebfedea0SLionel Sambuc     if (num_data < 0) {
1555*ebfedea0SLionel Sambuc         krb5_clear_error_message(context);
1556*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1557*ebfedea0SLionel Sambuc     }
1558*ebfedea0SLionel Sambuc 
1559*ebfedea0SLionel Sambuc     if(!derived_crypto(context, crypto)) {
1560*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1561*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1562*ebfedea0SLionel Sambuc     }
1563*ebfedea0SLionel Sambuc 
1564*ebfedea0SLionel Sambuc     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1565*ebfedea0SLionel Sambuc     if (civ == NULL)
1566*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1567*ebfedea0SLionel Sambuc 
1568*ebfedea0SLionel Sambuc     len = 0;
1569*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1570*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1571*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1572*ebfedea0SLionel Sambuc 	    continue;
1573*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1574*ebfedea0SLionel Sambuc     }
1575*ebfedea0SLionel Sambuc 
1576*ebfedea0SLionel Sambuc     p = q = malloc(len);
1577*ebfedea0SLionel Sambuc 
1578*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1579*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1580*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1581*ebfedea0SLionel Sambuc 	    continue;
1582*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1583*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1584*ebfedea0SLionel Sambuc     }
1585*ebfedea0SLionel Sambuc 
1586*ebfedea0SLionel Sambuc     ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum);
1587*ebfedea0SLionel Sambuc     free(p);
1588*ebfedea0SLionel Sambuc     if (ret)
1589*ebfedea0SLionel Sambuc 	return ret;
1590*ebfedea0SLionel Sambuc 
1591*ebfedea0SLionel Sambuc     if (type)
1592*ebfedea0SLionel Sambuc 	*type = cksum.cksumtype;
1593*ebfedea0SLionel Sambuc 
1594*ebfedea0SLionel Sambuc     if (cksum.checksum.length > civ->data.length) {
1595*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_BAD_MSIZE,
1596*ebfedea0SLionel Sambuc 			       N_("Checksum larger then input buffer", ""));
1597*ebfedea0SLionel Sambuc 	free_Checksum(&cksum);
1598*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1599*ebfedea0SLionel Sambuc     }
1600*ebfedea0SLionel Sambuc 
1601*ebfedea0SLionel Sambuc     civ->data.length = cksum.checksum.length;
1602*ebfedea0SLionel Sambuc     memcpy(civ->data.data, cksum.checksum.data, civ->data.length);
1603*ebfedea0SLionel Sambuc     free_Checksum(&cksum);
1604*ebfedea0SLionel Sambuc 
1605*ebfedea0SLionel Sambuc     return 0;
1606*ebfedea0SLionel Sambuc }
1607*ebfedea0SLionel Sambuc 
1608*ebfedea0SLionel Sambuc /**
1609*ebfedea0SLionel Sambuc  * Verify a Kerberos message checksum.
1610*ebfedea0SLionel Sambuc  *
1611*ebfedea0SLionel Sambuc  * @param context Kerberos context
1612*ebfedea0SLionel Sambuc  * @param crypto Kerberos crypto context
1613*ebfedea0SLionel Sambuc  * @param usage Key usage for this buffer
1614*ebfedea0SLionel Sambuc  * @param data array of buffers to process
1615*ebfedea0SLionel Sambuc  * @param num_data length of array
1616*ebfedea0SLionel Sambuc  * @param type return checksum type if not NULL
1617*ebfedea0SLionel Sambuc  *
1618*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
1619*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
1620*ebfedea0SLionel Sambuc  */
1621*ebfedea0SLionel Sambuc 
1622*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1623*ebfedea0SLionel Sambuc krb5_verify_checksum_iov(krb5_context context,
1624*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
1625*ebfedea0SLionel Sambuc 			 unsigned usage,
1626*ebfedea0SLionel Sambuc 			 krb5_crypto_iov *data,
1627*ebfedea0SLionel Sambuc 			 unsigned int num_data,
1628*ebfedea0SLionel Sambuc 			 krb5_cksumtype *type)
1629*ebfedea0SLionel Sambuc {
1630*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
1631*ebfedea0SLionel Sambuc     Checksum cksum;
1632*ebfedea0SLionel Sambuc     krb5_crypto_iov *civ;
1633*ebfedea0SLionel Sambuc     krb5_error_code ret;
1634*ebfedea0SLionel Sambuc     int i;
1635*ebfedea0SLionel Sambuc     size_t len;
1636*ebfedea0SLionel Sambuc     char *p, *q;
1637*ebfedea0SLionel Sambuc 
1638*ebfedea0SLionel Sambuc     if (num_data < 0) {
1639*ebfedea0SLionel Sambuc         krb5_clear_error_message(context);
1640*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1641*ebfedea0SLionel Sambuc     }
1642*ebfedea0SLionel Sambuc 
1643*ebfedea0SLionel Sambuc     if(!derived_crypto(context, crypto)) {
1644*ebfedea0SLionel Sambuc 	krb5_clear_error_message(context);
1645*ebfedea0SLionel Sambuc 	return KRB5_CRYPTO_INTERNAL;
1646*ebfedea0SLionel Sambuc     }
1647*ebfedea0SLionel Sambuc 
1648*ebfedea0SLionel Sambuc     civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
1649*ebfedea0SLionel Sambuc     if (civ == NULL)
1650*ebfedea0SLionel Sambuc 	return KRB5_BAD_MSIZE;
1651*ebfedea0SLionel Sambuc 
1652*ebfedea0SLionel Sambuc     len = 0;
1653*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1654*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1655*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1656*ebfedea0SLionel Sambuc 	    continue;
1657*ebfedea0SLionel Sambuc 	len += data[i].data.length;
1658*ebfedea0SLionel Sambuc     }
1659*ebfedea0SLionel Sambuc 
1660*ebfedea0SLionel Sambuc     p = q = malloc(len);
1661*ebfedea0SLionel Sambuc 
1662*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1663*ebfedea0SLionel Sambuc 	if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
1664*ebfedea0SLionel Sambuc 	    data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
1665*ebfedea0SLionel Sambuc 	    continue;
1666*ebfedea0SLionel Sambuc 	memcpy(q, data[i].data.data, data[i].data.length);
1667*ebfedea0SLionel Sambuc 	q += data[i].data.length;
1668*ebfedea0SLionel Sambuc     }
1669*ebfedea0SLionel Sambuc 
1670*ebfedea0SLionel Sambuc     cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
1671*ebfedea0SLionel Sambuc     cksum.checksum.length = civ->data.length;
1672*ebfedea0SLionel Sambuc     cksum.checksum.data = civ->data.data;
1673*ebfedea0SLionel Sambuc 
1674*ebfedea0SLionel Sambuc     ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
1675*ebfedea0SLionel Sambuc     free(p);
1676*ebfedea0SLionel Sambuc 
1677*ebfedea0SLionel Sambuc     if (ret == 0 && type)
1678*ebfedea0SLionel Sambuc 	*type = cksum.cksumtype;
1679*ebfedea0SLionel Sambuc 
1680*ebfedea0SLionel Sambuc     return ret;
1681*ebfedea0SLionel Sambuc }
1682*ebfedea0SLionel Sambuc 
1683*ebfedea0SLionel Sambuc 
1684*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1685*ebfedea0SLionel Sambuc krb5_crypto_length(krb5_context context,
1686*ebfedea0SLionel Sambuc 		   krb5_crypto crypto,
1687*ebfedea0SLionel Sambuc 		   int type,
1688*ebfedea0SLionel Sambuc 		   size_t *len)
1689*ebfedea0SLionel Sambuc {
1690*ebfedea0SLionel Sambuc     if (!derived_crypto(context, crypto)) {
1691*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, EINVAL, "not a derived crypto");
1692*ebfedea0SLionel Sambuc 	return EINVAL;
1693*ebfedea0SLionel Sambuc     }
1694*ebfedea0SLionel Sambuc 
1695*ebfedea0SLionel Sambuc     switch(type) {
1696*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_EMPTY:
1697*ebfedea0SLionel Sambuc 	*len = 0;
1698*ebfedea0SLionel Sambuc 	return 0;
1699*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_HEADER:
1700*ebfedea0SLionel Sambuc 	*len = crypto->et->blocksize;
1701*ebfedea0SLionel Sambuc 	return 0;
1702*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_DATA:
1703*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_SIGN_ONLY:
1704*ebfedea0SLionel Sambuc 	/* len must already been filled in */
1705*ebfedea0SLionel Sambuc 	return 0;
1706*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_PADDING:
1707*ebfedea0SLionel Sambuc 	if (crypto->et->padsize > 1)
1708*ebfedea0SLionel Sambuc 	    *len = crypto->et->padsize;
1709*ebfedea0SLionel Sambuc 	else
1710*ebfedea0SLionel Sambuc 	    *len = 0;
1711*ebfedea0SLionel Sambuc 	return 0;
1712*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_TRAILER:
1713*ebfedea0SLionel Sambuc 	*len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1714*ebfedea0SLionel Sambuc 	return 0;
1715*ebfedea0SLionel Sambuc     case KRB5_CRYPTO_TYPE_CHECKSUM:
1716*ebfedea0SLionel Sambuc 	if (crypto->et->keyed_checksum)
1717*ebfedea0SLionel Sambuc 	    *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
1718*ebfedea0SLionel Sambuc 	else
1719*ebfedea0SLionel Sambuc 	    *len = CHECKSUMSIZE(crypto->et->checksum);
1720*ebfedea0SLionel Sambuc 	return 0;
1721*ebfedea0SLionel Sambuc     }
1722*ebfedea0SLionel Sambuc     krb5_set_error_message(context, EINVAL,
1723*ebfedea0SLionel Sambuc 			   "%d not a supported type", type);
1724*ebfedea0SLionel Sambuc     return EINVAL;
1725*ebfedea0SLionel Sambuc }
1726*ebfedea0SLionel Sambuc 
1727*ebfedea0SLionel Sambuc 
1728*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1729*ebfedea0SLionel Sambuc krb5_crypto_length_iov(krb5_context context,
1730*ebfedea0SLionel Sambuc 		       krb5_crypto crypto,
1731*ebfedea0SLionel Sambuc 		       krb5_crypto_iov *data,
1732*ebfedea0SLionel Sambuc 		       unsigned int num_data)
1733*ebfedea0SLionel Sambuc {
1734*ebfedea0SLionel Sambuc     krb5_error_code ret;
1735*ebfedea0SLionel Sambuc     int i;
1736*ebfedea0SLionel Sambuc 
1737*ebfedea0SLionel Sambuc     for (i = 0; i < num_data; i++) {
1738*ebfedea0SLionel Sambuc 	ret = krb5_crypto_length(context, crypto,
1739*ebfedea0SLionel Sambuc 				 data[i].flags,
1740*ebfedea0SLionel Sambuc 				 &data[i].data.length);
1741*ebfedea0SLionel Sambuc 	if (ret)
1742*ebfedea0SLionel Sambuc 	    return ret;
1743*ebfedea0SLionel Sambuc     }
1744*ebfedea0SLionel Sambuc     return 0;
1745*ebfedea0SLionel Sambuc }
1746*ebfedea0SLionel Sambuc 
1747*ebfedea0SLionel Sambuc 
1748*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1749*ebfedea0SLionel Sambuc krb5_encrypt_ivec(krb5_context context,
1750*ebfedea0SLionel Sambuc 		  krb5_crypto crypto,
1751*ebfedea0SLionel Sambuc 		  unsigned usage,
1752*ebfedea0SLionel Sambuc 		  const void *data,
1753*ebfedea0SLionel Sambuc 		  size_t len,
1754*ebfedea0SLionel Sambuc 		  krb5_data *result,
1755*ebfedea0SLionel Sambuc 		  void *ivec)
1756*ebfedea0SLionel Sambuc {
1757*ebfedea0SLionel Sambuc     if(derived_crypto(context, crypto))
1758*ebfedea0SLionel Sambuc 	return encrypt_internal_derived(context, crypto, usage,
1759*ebfedea0SLionel Sambuc 					data, len, result, ivec);
1760*ebfedea0SLionel Sambuc     else if (special_crypto(context, crypto))
1761*ebfedea0SLionel Sambuc 	return encrypt_internal_special (context, crypto, usage,
1762*ebfedea0SLionel Sambuc 					 data, len, result, ivec);
1763*ebfedea0SLionel Sambuc     else
1764*ebfedea0SLionel Sambuc 	return encrypt_internal(context, crypto, data, len, result, ivec);
1765*ebfedea0SLionel Sambuc }
1766*ebfedea0SLionel Sambuc 
1767*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1768*ebfedea0SLionel Sambuc krb5_encrypt(krb5_context context,
1769*ebfedea0SLionel Sambuc 	     krb5_crypto crypto,
1770*ebfedea0SLionel Sambuc 	     unsigned usage,
1771*ebfedea0SLionel Sambuc 	     const void *data,
1772*ebfedea0SLionel Sambuc 	     size_t len,
1773*ebfedea0SLionel Sambuc 	     krb5_data *result)
1774*ebfedea0SLionel Sambuc {
1775*ebfedea0SLionel Sambuc     return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
1776*ebfedea0SLionel Sambuc }
1777*ebfedea0SLionel Sambuc 
1778*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1779*ebfedea0SLionel Sambuc krb5_encrypt_EncryptedData(krb5_context context,
1780*ebfedea0SLionel Sambuc 			   krb5_crypto crypto,
1781*ebfedea0SLionel Sambuc 			   unsigned usage,
1782*ebfedea0SLionel Sambuc 			   void *data,
1783*ebfedea0SLionel Sambuc 			   size_t len,
1784*ebfedea0SLionel Sambuc 			   int kvno,
1785*ebfedea0SLionel Sambuc 			   EncryptedData *result)
1786*ebfedea0SLionel Sambuc {
1787*ebfedea0SLionel Sambuc     result->etype = CRYPTO_ETYPE(crypto);
1788*ebfedea0SLionel Sambuc     if(kvno){
1789*ebfedea0SLionel Sambuc 	ALLOC(result->kvno, 1);
1790*ebfedea0SLionel Sambuc 	*result->kvno = kvno;
1791*ebfedea0SLionel Sambuc     }else
1792*ebfedea0SLionel Sambuc 	result->kvno = NULL;
1793*ebfedea0SLionel Sambuc     return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
1794*ebfedea0SLionel Sambuc }
1795*ebfedea0SLionel Sambuc 
1796*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1797*ebfedea0SLionel Sambuc krb5_decrypt_ivec(krb5_context context,
1798*ebfedea0SLionel Sambuc 		  krb5_crypto crypto,
1799*ebfedea0SLionel Sambuc 		  unsigned usage,
1800*ebfedea0SLionel Sambuc 		  void *data,
1801*ebfedea0SLionel Sambuc 		  size_t len,
1802*ebfedea0SLionel Sambuc 		  krb5_data *result,
1803*ebfedea0SLionel Sambuc 		  void *ivec)
1804*ebfedea0SLionel Sambuc {
1805*ebfedea0SLionel Sambuc     if(derived_crypto(context, crypto))
1806*ebfedea0SLionel Sambuc 	return decrypt_internal_derived(context, crypto, usage,
1807*ebfedea0SLionel Sambuc 					data, len, result, ivec);
1808*ebfedea0SLionel Sambuc     else if (special_crypto (context, crypto))
1809*ebfedea0SLionel Sambuc 	return decrypt_internal_special(context, crypto, usage,
1810*ebfedea0SLionel Sambuc 					data, len, result, ivec);
1811*ebfedea0SLionel Sambuc     else
1812*ebfedea0SLionel Sambuc 	return decrypt_internal(context, crypto, data, len, result, ivec);
1813*ebfedea0SLionel Sambuc }
1814*ebfedea0SLionel Sambuc 
1815*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1816*ebfedea0SLionel Sambuc krb5_decrypt(krb5_context context,
1817*ebfedea0SLionel Sambuc 	     krb5_crypto crypto,
1818*ebfedea0SLionel Sambuc 	     unsigned usage,
1819*ebfedea0SLionel Sambuc 	     void *data,
1820*ebfedea0SLionel Sambuc 	     size_t len,
1821*ebfedea0SLionel Sambuc 	     krb5_data *result)
1822*ebfedea0SLionel Sambuc {
1823*ebfedea0SLionel Sambuc     return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
1824*ebfedea0SLionel Sambuc 			      NULL);
1825*ebfedea0SLionel Sambuc }
1826*ebfedea0SLionel Sambuc 
1827*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1828*ebfedea0SLionel Sambuc krb5_decrypt_EncryptedData(krb5_context context,
1829*ebfedea0SLionel Sambuc 			   krb5_crypto crypto,
1830*ebfedea0SLionel Sambuc 			   unsigned usage,
1831*ebfedea0SLionel Sambuc 			   const EncryptedData *e,
1832*ebfedea0SLionel Sambuc 			   krb5_data *result)
1833*ebfedea0SLionel Sambuc {
1834*ebfedea0SLionel Sambuc     return krb5_decrypt(context, crypto, usage,
1835*ebfedea0SLionel Sambuc 			e->cipher.data, e->cipher.length, result);
1836*ebfedea0SLionel Sambuc }
1837*ebfedea0SLionel Sambuc 
1838*ebfedea0SLionel Sambuc /************************************************************
1839*ebfedea0SLionel Sambuc  *                                                          *
1840*ebfedea0SLionel Sambuc  ************************************************************/
1841*ebfedea0SLionel Sambuc 
1842*ebfedea0SLionel Sambuc krb5_error_code
1843*ebfedea0SLionel Sambuc _krb5_derive_key(krb5_context context,
1844*ebfedea0SLionel Sambuc 		 struct _krb5_encryption_type *et,
1845*ebfedea0SLionel Sambuc 		 struct _krb5_key_data *key,
1846*ebfedea0SLionel Sambuc 		 const void *constant,
1847*ebfedea0SLionel Sambuc 		 size_t len)
1848*ebfedea0SLionel Sambuc {
1849*ebfedea0SLionel Sambuc     unsigned char *k = NULL;
1850*ebfedea0SLionel Sambuc     unsigned int nblocks = 0, i;
1851*ebfedea0SLionel Sambuc     krb5_error_code ret = 0;
1852*ebfedea0SLionel Sambuc     struct _krb5_key_type *kt = et->keytype;
1853*ebfedea0SLionel Sambuc 
1854*ebfedea0SLionel Sambuc     ret = _key_schedule(context, key);
1855*ebfedea0SLionel Sambuc     if(ret)
1856*ebfedea0SLionel Sambuc 	return ret;
1857*ebfedea0SLionel Sambuc     if(et->blocksize * 8 < kt->bits || len != et->blocksize) {
1858*ebfedea0SLionel Sambuc 	nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
1859*ebfedea0SLionel Sambuc 	k = malloc(nblocks * et->blocksize);
1860*ebfedea0SLionel Sambuc 	if(k == NULL) {
1861*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
1862*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1863*ebfedea0SLionel Sambuc 	    goto out;
1864*ebfedea0SLionel Sambuc 	}
1865*ebfedea0SLionel Sambuc 	ret = _krb5_n_fold(constant, len, k, et->blocksize);
1866*ebfedea0SLionel Sambuc 	if (ret) {
1867*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1868*ebfedea0SLionel Sambuc 	    goto out;
1869*ebfedea0SLionel Sambuc 	}
1870*ebfedea0SLionel Sambuc 
1871*ebfedea0SLionel Sambuc 	for(i = 0; i < nblocks; i++) {
1872*ebfedea0SLionel Sambuc 	    if(i > 0)
1873*ebfedea0SLionel Sambuc 		memcpy(k + i * et->blocksize,
1874*ebfedea0SLionel Sambuc 		       k + (i - 1) * et->blocksize,
1875*ebfedea0SLionel Sambuc 		       et->blocksize);
1876*ebfedea0SLionel Sambuc 	    (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
1877*ebfedea0SLionel Sambuc 			   1, 0, NULL);
1878*ebfedea0SLionel Sambuc 	}
1879*ebfedea0SLionel Sambuc     } else {
1880*ebfedea0SLionel Sambuc 	/* this case is probably broken, but won't be run anyway */
1881*ebfedea0SLionel Sambuc 	void *c = malloc(len);
1882*ebfedea0SLionel Sambuc 	size_t res_len = (kt->bits + 7) / 8;
1883*ebfedea0SLionel Sambuc 
1884*ebfedea0SLionel Sambuc 	if(len != 0 && c == NULL) {
1885*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
1886*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1887*ebfedea0SLionel Sambuc 	    goto out;
1888*ebfedea0SLionel Sambuc 	}
1889*ebfedea0SLionel Sambuc 	memcpy(c, constant, len);
1890*ebfedea0SLionel Sambuc 	(*et->encrypt)(context, key, c, len, 1, 0, NULL);
1891*ebfedea0SLionel Sambuc 	k = malloc(res_len);
1892*ebfedea0SLionel Sambuc 	if(res_len != 0 && k == NULL) {
1893*ebfedea0SLionel Sambuc 	    free(c);
1894*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
1895*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1896*ebfedea0SLionel Sambuc 	    goto out;
1897*ebfedea0SLionel Sambuc 	}
1898*ebfedea0SLionel Sambuc 	ret = _krb5_n_fold(c, len, k, res_len);
1899*ebfedea0SLionel Sambuc 	free(c);
1900*ebfedea0SLionel Sambuc 	if (ret) {
1901*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
1902*ebfedea0SLionel Sambuc 	    goto out;
1903*ebfedea0SLionel Sambuc 	}
1904*ebfedea0SLionel Sambuc     }
1905*ebfedea0SLionel Sambuc 
1906*ebfedea0SLionel Sambuc     /* XXX keytype dependent post-processing */
1907*ebfedea0SLionel Sambuc     switch(kt->type) {
1908*ebfedea0SLionel Sambuc     case KEYTYPE_DES3:
1909*ebfedea0SLionel Sambuc 	_krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
1910*ebfedea0SLionel Sambuc 	break;
1911*ebfedea0SLionel Sambuc     case KEYTYPE_AES128:
1912*ebfedea0SLionel Sambuc     case KEYTYPE_AES256:
1913*ebfedea0SLionel Sambuc 	memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
1914*ebfedea0SLionel Sambuc 	break;
1915*ebfedea0SLionel Sambuc     default:
1916*ebfedea0SLionel Sambuc 	ret = KRB5_CRYPTO_INTERNAL;
1917*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ret,
1918*ebfedea0SLionel Sambuc 			       N_("derive_key() called with unknown keytype (%u)", ""),
1919*ebfedea0SLionel Sambuc 			       kt->type);
1920*ebfedea0SLionel Sambuc 	break;
1921*ebfedea0SLionel Sambuc     }
1922*ebfedea0SLionel Sambuc  out:
1923*ebfedea0SLionel Sambuc     if (key->schedule) {
1924*ebfedea0SLionel Sambuc 	free_key_schedule(context, key, et);
1925*ebfedea0SLionel Sambuc 	key->schedule = NULL;
1926*ebfedea0SLionel Sambuc     }
1927*ebfedea0SLionel Sambuc     if (k) {
1928*ebfedea0SLionel Sambuc 	memset(k, 0, nblocks * et->blocksize);
1929*ebfedea0SLionel Sambuc 	free(k);
1930*ebfedea0SLionel Sambuc     }
1931*ebfedea0SLionel Sambuc     return ret;
1932*ebfedea0SLionel Sambuc }
1933*ebfedea0SLionel Sambuc 
1934*ebfedea0SLionel Sambuc static struct _krb5_key_data *
1935*ebfedea0SLionel Sambuc _new_derived_key(krb5_crypto crypto, unsigned usage)
1936*ebfedea0SLionel Sambuc {
1937*ebfedea0SLionel Sambuc     struct _krb5_key_usage *d = crypto->key_usage;
1938*ebfedea0SLionel Sambuc     d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
1939*ebfedea0SLionel Sambuc     if(d == NULL)
1940*ebfedea0SLionel Sambuc 	return NULL;
1941*ebfedea0SLionel Sambuc     crypto->key_usage = d;
1942*ebfedea0SLionel Sambuc     d += crypto->num_key_usage++;
1943*ebfedea0SLionel Sambuc     memset(d, 0, sizeof(*d));
1944*ebfedea0SLionel Sambuc     d->usage = usage;
1945*ebfedea0SLionel Sambuc     return &d->key;
1946*ebfedea0SLionel Sambuc }
1947*ebfedea0SLionel Sambuc 
1948*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
1949*ebfedea0SLionel Sambuc krb5_derive_key(krb5_context context,
1950*ebfedea0SLionel Sambuc 		const krb5_keyblock *key,
1951*ebfedea0SLionel Sambuc 		krb5_enctype etype,
1952*ebfedea0SLionel Sambuc 		const void *constant,
1953*ebfedea0SLionel Sambuc 		size_t constant_len,
1954*ebfedea0SLionel Sambuc 		krb5_keyblock **derived_key)
1955*ebfedea0SLionel Sambuc {
1956*ebfedea0SLionel Sambuc     krb5_error_code ret;
1957*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et;
1958*ebfedea0SLionel Sambuc     struct _krb5_key_data d;
1959*ebfedea0SLionel Sambuc 
1960*ebfedea0SLionel Sambuc     *derived_key = NULL;
1961*ebfedea0SLionel Sambuc 
1962*ebfedea0SLionel Sambuc     et = _krb5_find_enctype (etype);
1963*ebfedea0SLionel Sambuc     if (et == NULL) {
1964*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
1965*ebfedea0SLionel Sambuc 			       N_("encryption type %d not supported", ""),
1966*ebfedea0SLionel Sambuc 			       etype);
1967*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
1968*ebfedea0SLionel Sambuc     }
1969*ebfedea0SLionel Sambuc 
1970*ebfedea0SLionel Sambuc     ret = krb5_copy_keyblock(context, key, &d.key);
1971*ebfedea0SLionel Sambuc     if (ret)
1972*ebfedea0SLionel Sambuc 	return ret;
1973*ebfedea0SLionel Sambuc 
1974*ebfedea0SLionel Sambuc     d.schedule = NULL;
1975*ebfedea0SLionel Sambuc     ret = _krb5_derive_key(context, et, &d, constant, constant_len);
1976*ebfedea0SLionel Sambuc     if (ret == 0)
1977*ebfedea0SLionel Sambuc 	ret = krb5_copy_keyblock(context, d.key, derived_key);
1978*ebfedea0SLionel Sambuc     _krb5_free_key_data(context, &d, et);
1979*ebfedea0SLionel Sambuc     return ret;
1980*ebfedea0SLionel Sambuc }
1981*ebfedea0SLionel Sambuc 
1982*ebfedea0SLionel Sambuc static krb5_error_code
1983*ebfedea0SLionel Sambuc _get_derived_key(krb5_context context,
1984*ebfedea0SLionel Sambuc 		 krb5_crypto crypto,
1985*ebfedea0SLionel Sambuc 		 unsigned usage,
1986*ebfedea0SLionel Sambuc 		 struct _krb5_key_data **key)
1987*ebfedea0SLionel Sambuc {
1988*ebfedea0SLionel Sambuc     int i;
1989*ebfedea0SLionel Sambuc     struct _krb5_key_data *d;
1990*ebfedea0SLionel Sambuc     unsigned char constant[5];
1991*ebfedea0SLionel Sambuc 
1992*ebfedea0SLionel Sambuc     for(i = 0; i < crypto->num_key_usage; i++)
1993*ebfedea0SLionel Sambuc 	if(crypto->key_usage[i].usage == usage) {
1994*ebfedea0SLionel Sambuc 	    *key = &crypto->key_usage[i].key;
1995*ebfedea0SLionel Sambuc 	    return 0;
1996*ebfedea0SLionel Sambuc 	}
1997*ebfedea0SLionel Sambuc     d = _new_derived_key(crypto, usage);
1998*ebfedea0SLionel Sambuc     if(d == NULL) {
1999*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2000*ebfedea0SLionel Sambuc 	return ENOMEM;
2001*ebfedea0SLionel Sambuc     }
2002*ebfedea0SLionel Sambuc     krb5_copy_keyblock(context, crypto->key.key, &d->key);
2003*ebfedea0SLionel Sambuc     _krb5_put_int(constant, usage, 5);
2004*ebfedea0SLionel Sambuc     _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant));
2005*ebfedea0SLionel Sambuc     *key = d;
2006*ebfedea0SLionel Sambuc     return 0;
2007*ebfedea0SLionel Sambuc }
2008*ebfedea0SLionel Sambuc 
2009*ebfedea0SLionel Sambuc /**
2010*ebfedea0SLionel Sambuc  * Create a crypto context used for all encryption and signature
2011*ebfedea0SLionel Sambuc  * operation. The encryption type to use is taken from the key, but
2012*ebfedea0SLionel Sambuc  * can be overridden with the enctype parameter.  This can be useful
2013*ebfedea0SLionel Sambuc  * for encryptions types which is compatiable (DES for example).
2014*ebfedea0SLionel Sambuc  *
2015*ebfedea0SLionel Sambuc  * To free the crypto context, use krb5_crypto_destroy().
2016*ebfedea0SLionel Sambuc  *
2017*ebfedea0SLionel Sambuc  * @param context Kerberos context
2018*ebfedea0SLionel Sambuc  * @param key the key block information with all key data
2019*ebfedea0SLionel Sambuc  * @param etype the encryption type
2020*ebfedea0SLionel Sambuc  * @param crypto the resulting crypto context
2021*ebfedea0SLionel Sambuc  *
2022*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2023*ebfedea0SLionel Sambuc  *
2024*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2025*ebfedea0SLionel Sambuc  */
2026*ebfedea0SLionel Sambuc 
2027*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2028*ebfedea0SLionel Sambuc krb5_crypto_init(krb5_context context,
2029*ebfedea0SLionel Sambuc 		 const krb5_keyblock *key,
2030*ebfedea0SLionel Sambuc 		 krb5_enctype etype,
2031*ebfedea0SLionel Sambuc 		 krb5_crypto *crypto)
2032*ebfedea0SLionel Sambuc {
2033*ebfedea0SLionel Sambuc     krb5_error_code ret;
2034*ebfedea0SLionel Sambuc     ALLOC(*crypto, 1);
2035*ebfedea0SLionel Sambuc     if(*crypto == NULL) {
2036*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
2037*ebfedea0SLionel Sambuc 	return ENOMEM;
2038*ebfedea0SLionel Sambuc     }
2039*ebfedea0SLionel Sambuc     if(etype == ETYPE_NULL)
2040*ebfedea0SLionel Sambuc 	etype = key->keytype;
2041*ebfedea0SLionel Sambuc     (*crypto)->et = _krb5_find_enctype(etype);
2042*ebfedea0SLionel Sambuc     if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
2043*ebfedea0SLionel Sambuc 	free(*crypto);
2044*ebfedea0SLionel Sambuc 	*crypto = NULL;
2045*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2046*ebfedea0SLionel Sambuc 				N_("encryption type %d not supported", ""),
2047*ebfedea0SLionel Sambuc 				etype);
2048*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2049*ebfedea0SLionel Sambuc     }
2050*ebfedea0SLionel Sambuc     if((*crypto)->et->keytype->size != key->keyvalue.length) {
2051*ebfedea0SLionel Sambuc 	free(*crypto);
2052*ebfedea0SLionel Sambuc 	*crypto = NULL;
2053*ebfedea0SLionel Sambuc 	krb5_set_error_message (context, KRB5_BAD_KEYSIZE,
2054*ebfedea0SLionel Sambuc 				"encryption key has bad length");
2055*ebfedea0SLionel Sambuc 	return KRB5_BAD_KEYSIZE;
2056*ebfedea0SLionel Sambuc     }
2057*ebfedea0SLionel Sambuc     ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
2058*ebfedea0SLionel Sambuc     if(ret) {
2059*ebfedea0SLionel Sambuc 	free(*crypto);
2060*ebfedea0SLionel Sambuc 	*crypto = NULL;
2061*ebfedea0SLionel Sambuc 	return ret;
2062*ebfedea0SLionel Sambuc     }
2063*ebfedea0SLionel Sambuc     (*crypto)->key.schedule = NULL;
2064*ebfedea0SLionel Sambuc     (*crypto)->num_key_usage = 0;
2065*ebfedea0SLionel Sambuc     (*crypto)->key_usage = NULL;
2066*ebfedea0SLionel Sambuc     return 0;
2067*ebfedea0SLionel Sambuc }
2068*ebfedea0SLionel Sambuc 
2069*ebfedea0SLionel Sambuc static void
2070*ebfedea0SLionel Sambuc free_key_schedule(krb5_context context,
2071*ebfedea0SLionel Sambuc 		  struct _krb5_key_data *key,
2072*ebfedea0SLionel Sambuc 		  struct _krb5_encryption_type *et)
2073*ebfedea0SLionel Sambuc {
2074*ebfedea0SLionel Sambuc     if (et->keytype->cleanup)
2075*ebfedea0SLionel Sambuc 	(*et->keytype->cleanup)(context, key);
2076*ebfedea0SLionel Sambuc     memset(key->schedule->data, 0, key->schedule->length);
2077*ebfedea0SLionel Sambuc     krb5_free_data(context, key->schedule);
2078*ebfedea0SLionel Sambuc }
2079*ebfedea0SLionel Sambuc 
2080*ebfedea0SLionel Sambuc void
2081*ebfedea0SLionel Sambuc _krb5_free_key_data(krb5_context context, struct _krb5_key_data *key,
2082*ebfedea0SLionel Sambuc 	      struct _krb5_encryption_type *et)
2083*ebfedea0SLionel Sambuc {
2084*ebfedea0SLionel Sambuc     krb5_free_keyblock(context, key->key);
2085*ebfedea0SLionel Sambuc     if(key->schedule) {
2086*ebfedea0SLionel Sambuc 	free_key_schedule(context, key, et);
2087*ebfedea0SLionel Sambuc 	key->schedule = NULL;
2088*ebfedea0SLionel Sambuc     }
2089*ebfedea0SLionel Sambuc }
2090*ebfedea0SLionel Sambuc 
2091*ebfedea0SLionel Sambuc static void
2092*ebfedea0SLionel Sambuc free_key_usage(krb5_context context, struct _krb5_key_usage *ku,
2093*ebfedea0SLionel Sambuc 	       struct _krb5_encryption_type *et)
2094*ebfedea0SLionel Sambuc {
2095*ebfedea0SLionel Sambuc     _krb5_free_key_data(context, &ku->key, et);
2096*ebfedea0SLionel Sambuc }
2097*ebfedea0SLionel Sambuc 
2098*ebfedea0SLionel Sambuc /**
2099*ebfedea0SLionel Sambuc  * Free a crypto context created by krb5_crypto_init().
2100*ebfedea0SLionel Sambuc  *
2101*ebfedea0SLionel Sambuc  * @param context Kerberos context
2102*ebfedea0SLionel Sambuc  * @param crypto crypto context to free
2103*ebfedea0SLionel Sambuc  *
2104*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2105*ebfedea0SLionel Sambuc  *
2106*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2107*ebfedea0SLionel Sambuc  */
2108*ebfedea0SLionel Sambuc 
2109*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2110*ebfedea0SLionel Sambuc krb5_crypto_destroy(krb5_context context,
2111*ebfedea0SLionel Sambuc 		    krb5_crypto crypto)
2112*ebfedea0SLionel Sambuc {
2113*ebfedea0SLionel Sambuc     int i;
2114*ebfedea0SLionel Sambuc 
2115*ebfedea0SLionel Sambuc     for(i = 0; i < crypto->num_key_usage; i++)
2116*ebfedea0SLionel Sambuc 	free_key_usage(context, &crypto->key_usage[i], crypto->et);
2117*ebfedea0SLionel Sambuc     free(crypto->key_usage);
2118*ebfedea0SLionel Sambuc     _krb5_free_key_data(context, &crypto->key, crypto->et);
2119*ebfedea0SLionel Sambuc     free (crypto);
2120*ebfedea0SLionel Sambuc     return 0;
2121*ebfedea0SLionel Sambuc }
2122*ebfedea0SLionel Sambuc 
2123*ebfedea0SLionel Sambuc /**
2124*ebfedea0SLionel Sambuc  * Return the blocksize used algorithm referenced by the crypto context
2125*ebfedea0SLionel Sambuc  *
2126*ebfedea0SLionel Sambuc  * @param context Kerberos context
2127*ebfedea0SLionel Sambuc  * @param crypto crypto context to query
2128*ebfedea0SLionel Sambuc  * @param blocksize the resulting blocksize
2129*ebfedea0SLionel Sambuc  *
2130*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2131*ebfedea0SLionel Sambuc  *
2132*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2133*ebfedea0SLionel Sambuc  */
2134*ebfedea0SLionel Sambuc 
2135*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2136*ebfedea0SLionel Sambuc krb5_crypto_getblocksize(krb5_context context,
2137*ebfedea0SLionel Sambuc 			 krb5_crypto crypto,
2138*ebfedea0SLionel Sambuc 			 size_t *blocksize)
2139*ebfedea0SLionel Sambuc {
2140*ebfedea0SLionel Sambuc     *blocksize = crypto->et->blocksize;
2141*ebfedea0SLionel Sambuc     return 0;
2142*ebfedea0SLionel Sambuc }
2143*ebfedea0SLionel Sambuc 
2144*ebfedea0SLionel Sambuc /**
2145*ebfedea0SLionel Sambuc  * Return the encryption type used by the crypto context
2146*ebfedea0SLionel Sambuc  *
2147*ebfedea0SLionel Sambuc  * @param context Kerberos context
2148*ebfedea0SLionel Sambuc  * @param crypto crypto context to query
2149*ebfedea0SLionel Sambuc  * @param enctype the resulting encryption type
2150*ebfedea0SLionel Sambuc  *
2151*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2152*ebfedea0SLionel Sambuc  *
2153*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2154*ebfedea0SLionel Sambuc  */
2155*ebfedea0SLionel Sambuc 
2156*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2157*ebfedea0SLionel Sambuc krb5_crypto_getenctype(krb5_context context,
2158*ebfedea0SLionel Sambuc 		       krb5_crypto crypto,
2159*ebfedea0SLionel Sambuc 		       krb5_enctype *enctype)
2160*ebfedea0SLionel Sambuc {
2161*ebfedea0SLionel Sambuc     *enctype = crypto->et->type;
2162*ebfedea0SLionel Sambuc     return 0;
2163*ebfedea0SLionel Sambuc }
2164*ebfedea0SLionel Sambuc 
2165*ebfedea0SLionel Sambuc /**
2166*ebfedea0SLionel Sambuc  * Return the padding size used by the crypto context
2167*ebfedea0SLionel Sambuc  *
2168*ebfedea0SLionel Sambuc  * @param context Kerberos context
2169*ebfedea0SLionel Sambuc  * @param crypto crypto context to query
2170*ebfedea0SLionel Sambuc  * @param padsize the return padding size
2171*ebfedea0SLionel Sambuc  *
2172*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2173*ebfedea0SLionel Sambuc  *
2174*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2175*ebfedea0SLionel Sambuc  */
2176*ebfedea0SLionel Sambuc 
2177*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2178*ebfedea0SLionel Sambuc krb5_crypto_getpadsize(krb5_context context,
2179*ebfedea0SLionel Sambuc                        krb5_crypto crypto,
2180*ebfedea0SLionel Sambuc                        size_t *padsize)
2181*ebfedea0SLionel Sambuc {
2182*ebfedea0SLionel Sambuc     *padsize = crypto->et->padsize;
2183*ebfedea0SLionel Sambuc     return 0;
2184*ebfedea0SLionel Sambuc }
2185*ebfedea0SLionel Sambuc 
2186*ebfedea0SLionel Sambuc /**
2187*ebfedea0SLionel Sambuc  * Return the confounder size used by the crypto context
2188*ebfedea0SLionel Sambuc  *
2189*ebfedea0SLionel Sambuc  * @param context Kerberos context
2190*ebfedea0SLionel Sambuc  * @param crypto crypto context to query
2191*ebfedea0SLionel Sambuc  * @param confoundersize the returned confounder size
2192*ebfedea0SLionel Sambuc  *
2193*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2194*ebfedea0SLionel Sambuc  *
2195*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2196*ebfedea0SLionel Sambuc  */
2197*ebfedea0SLionel Sambuc 
2198*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2199*ebfedea0SLionel Sambuc krb5_crypto_getconfoundersize(krb5_context context,
2200*ebfedea0SLionel Sambuc                               krb5_crypto crypto,
2201*ebfedea0SLionel Sambuc                               size_t *confoundersize)
2202*ebfedea0SLionel Sambuc {
2203*ebfedea0SLionel Sambuc     *confoundersize = crypto->et->confoundersize;
2204*ebfedea0SLionel Sambuc     return 0;
2205*ebfedea0SLionel Sambuc }
2206*ebfedea0SLionel Sambuc 
2207*ebfedea0SLionel Sambuc 
2208*ebfedea0SLionel Sambuc /**
2209*ebfedea0SLionel Sambuc  * Disable encryption type
2210*ebfedea0SLionel Sambuc  *
2211*ebfedea0SLionel Sambuc  * @param context Kerberos 5 context
2212*ebfedea0SLionel Sambuc  * @param enctype encryption type to disable
2213*ebfedea0SLionel Sambuc  *
2214*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2215*ebfedea0SLionel Sambuc  *
2216*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2217*ebfedea0SLionel Sambuc  */
2218*ebfedea0SLionel Sambuc 
2219*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2220*ebfedea0SLionel Sambuc krb5_enctype_disable(krb5_context context,
2221*ebfedea0SLionel Sambuc 		     krb5_enctype enctype)
2222*ebfedea0SLionel Sambuc {
2223*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2224*ebfedea0SLionel Sambuc     if(et == NULL) {
2225*ebfedea0SLionel Sambuc 	if (context)
2226*ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2227*ebfedea0SLionel Sambuc 				    N_("encryption type %d not supported", ""),
2228*ebfedea0SLionel Sambuc 				    enctype);
2229*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2230*ebfedea0SLionel Sambuc     }
2231*ebfedea0SLionel Sambuc     et->flags |= F_DISABLED;
2232*ebfedea0SLionel Sambuc     return 0;
2233*ebfedea0SLionel Sambuc }
2234*ebfedea0SLionel Sambuc 
2235*ebfedea0SLionel Sambuc /**
2236*ebfedea0SLionel Sambuc  * Enable encryption type
2237*ebfedea0SLionel Sambuc  *
2238*ebfedea0SLionel Sambuc  * @param context Kerberos 5 context
2239*ebfedea0SLionel Sambuc  * @param enctype encryption type to enable
2240*ebfedea0SLionel Sambuc  *
2241*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2242*ebfedea0SLionel Sambuc  *
2243*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2244*ebfedea0SLionel Sambuc  */
2245*ebfedea0SLionel Sambuc 
2246*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2247*ebfedea0SLionel Sambuc krb5_enctype_enable(krb5_context context,
2248*ebfedea0SLionel Sambuc 		    krb5_enctype enctype)
2249*ebfedea0SLionel Sambuc {
2250*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(enctype);
2251*ebfedea0SLionel Sambuc     if(et == NULL) {
2252*ebfedea0SLionel Sambuc 	if (context)
2253*ebfedea0SLionel Sambuc 	    krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
2254*ebfedea0SLionel Sambuc 				    N_("encryption type %d not supported", ""),
2255*ebfedea0SLionel Sambuc 				    enctype);
2256*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2257*ebfedea0SLionel Sambuc     }
2258*ebfedea0SLionel Sambuc     et->flags &= ~F_DISABLED;
2259*ebfedea0SLionel Sambuc     return 0;
2260*ebfedea0SLionel Sambuc }
2261*ebfedea0SLionel Sambuc 
2262*ebfedea0SLionel Sambuc /**
2263*ebfedea0SLionel Sambuc  * Enable or disable all weak encryption types
2264*ebfedea0SLionel Sambuc  *
2265*ebfedea0SLionel Sambuc  * @param context Kerberos 5 context
2266*ebfedea0SLionel Sambuc  * @param enable true to enable, false to disable
2267*ebfedea0SLionel Sambuc  *
2268*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2269*ebfedea0SLionel Sambuc  *
2270*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2271*ebfedea0SLionel Sambuc  */
2272*ebfedea0SLionel Sambuc 
2273*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2274*ebfedea0SLionel Sambuc krb5_allow_weak_crypto(krb5_context context,
2275*ebfedea0SLionel Sambuc 		       krb5_boolean enable)
2276*ebfedea0SLionel Sambuc {
2277*ebfedea0SLionel Sambuc     int i;
2278*ebfedea0SLionel Sambuc 
2279*ebfedea0SLionel Sambuc     for(i = 0; i < _krb5_num_etypes; i++)
2280*ebfedea0SLionel Sambuc 	if(_krb5_etypes[i]->flags & F_WEAK) {
2281*ebfedea0SLionel Sambuc 	    if(enable)
2282*ebfedea0SLionel Sambuc 		_krb5_etypes[i]->flags &= ~F_DISABLED;
2283*ebfedea0SLionel Sambuc 	    else
2284*ebfedea0SLionel Sambuc 		_krb5_etypes[i]->flags |= F_DISABLED;
2285*ebfedea0SLionel Sambuc 	}
2286*ebfedea0SLionel Sambuc     return 0;
2287*ebfedea0SLionel Sambuc }
2288*ebfedea0SLionel Sambuc 
2289*ebfedea0SLionel Sambuc static size_t
2290*ebfedea0SLionel Sambuc wrapped_length (krb5_context context,
2291*ebfedea0SLionel Sambuc 		krb5_crypto  crypto,
2292*ebfedea0SLionel Sambuc 		size_t       data_len)
2293*ebfedea0SLionel Sambuc {
2294*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
2295*ebfedea0SLionel Sambuc     size_t padsize = et->padsize;
2296*ebfedea0SLionel Sambuc     size_t checksumsize = CHECKSUMSIZE(et->checksum);
2297*ebfedea0SLionel Sambuc     size_t res;
2298*ebfedea0SLionel Sambuc 
2299*ebfedea0SLionel Sambuc     res =  et->confoundersize + checksumsize + data_len;
2300*ebfedea0SLionel Sambuc     res =  (res + padsize - 1) / padsize * padsize;
2301*ebfedea0SLionel Sambuc     return res;
2302*ebfedea0SLionel Sambuc }
2303*ebfedea0SLionel Sambuc 
2304*ebfedea0SLionel Sambuc static size_t
2305*ebfedea0SLionel Sambuc wrapped_length_dervied (krb5_context context,
2306*ebfedea0SLionel Sambuc 			krb5_crypto  crypto,
2307*ebfedea0SLionel Sambuc 			size_t       data_len)
2308*ebfedea0SLionel Sambuc {
2309*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
2310*ebfedea0SLionel Sambuc     size_t padsize = et->padsize;
2311*ebfedea0SLionel Sambuc     size_t res;
2312*ebfedea0SLionel Sambuc 
2313*ebfedea0SLionel Sambuc     res =  et->confoundersize + data_len;
2314*ebfedea0SLionel Sambuc     res =  (res + padsize - 1) / padsize * padsize;
2315*ebfedea0SLionel Sambuc     if (et->keyed_checksum)
2316*ebfedea0SLionel Sambuc 	res += et->keyed_checksum->checksumsize;
2317*ebfedea0SLionel Sambuc     else
2318*ebfedea0SLionel Sambuc 	res += et->checksum->checksumsize;
2319*ebfedea0SLionel Sambuc     return res;
2320*ebfedea0SLionel Sambuc }
2321*ebfedea0SLionel Sambuc 
2322*ebfedea0SLionel Sambuc /*
2323*ebfedea0SLionel Sambuc  * Return the size of an encrypted packet of length `data_len'
2324*ebfedea0SLionel Sambuc  */
2325*ebfedea0SLionel Sambuc 
2326*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2327*ebfedea0SLionel Sambuc krb5_get_wrapped_length (krb5_context context,
2328*ebfedea0SLionel Sambuc 			 krb5_crypto  crypto,
2329*ebfedea0SLionel Sambuc 			 size_t       data_len)
2330*ebfedea0SLionel Sambuc {
2331*ebfedea0SLionel Sambuc     if (derived_crypto (context, crypto))
2332*ebfedea0SLionel Sambuc 	return wrapped_length_dervied (context, crypto, data_len);
2333*ebfedea0SLionel Sambuc     else
2334*ebfedea0SLionel Sambuc 	return wrapped_length (context, crypto, data_len);
2335*ebfedea0SLionel Sambuc }
2336*ebfedea0SLionel Sambuc 
2337*ebfedea0SLionel Sambuc /*
2338*ebfedea0SLionel Sambuc  * Return the size of an encrypted packet of length `data_len'
2339*ebfedea0SLionel Sambuc  */
2340*ebfedea0SLionel Sambuc 
2341*ebfedea0SLionel Sambuc static size_t
2342*ebfedea0SLionel Sambuc crypto_overhead (krb5_context context,
2343*ebfedea0SLionel Sambuc 		 krb5_crypto  crypto)
2344*ebfedea0SLionel Sambuc {
2345*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
2346*ebfedea0SLionel Sambuc     size_t res;
2347*ebfedea0SLionel Sambuc 
2348*ebfedea0SLionel Sambuc     res = CHECKSUMSIZE(et->checksum);
2349*ebfedea0SLionel Sambuc     res += et->confoundersize;
2350*ebfedea0SLionel Sambuc     if (et->padsize > 1)
2351*ebfedea0SLionel Sambuc 	res += et->padsize;
2352*ebfedea0SLionel Sambuc     return res;
2353*ebfedea0SLionel Sambuc }
2354*ebfedea0SLionel Sambuc 
2355*ebfedea0SLionel Sambuc static size_t
2356*ebfedea0SLionel Sambuc crypto_overhead_dervied (krb5_context context,
2357*ebfedea0SLionel Sambuc 			 krb5_crypto  crypto)
2358*ebfedea0SLionel Sambuc {
2359*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
2360*ebfedea0SLionel Sambuc     size_t res;
2361*ebfedea0SLionel Sambuc 
2362*ebfedea0SLionel Sambuc     if (et->keyed_checksum)
2363*ebfedea0SLionel Sambuc 	res = CHECKSUMSIZE(et->keyed_checksum);
2364*ebfedea0SLionel Sambuc     else
2365*ebfedea0SLionel Sambuc 	res = CHECKSUMSIZE(et->checksum);
2366*ebfedea0SLionel Sambuc     res += et->confoundersize;
2367*ebfedea0SLionel Sambuc     if (et->padsize > 1)
2368*ebfedea0SLionel Sambuc 	res += et->padsize;
2369*ebfedea0SLionel Sambuc     return res;
2370*ebfedea0SLionel Sambuc }
2371*ebfedea0SLionel Sambuc 
2372*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL
2373*ebfedea0SLionel Sambuc krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
2374*ebfedea0SLionel Sambuc {
2375*ebfedea0SLionel Sambuc     if (derived_crypto (context, crypto))
2376*ebfedea0SLionel Sambuc 	return crypto_overhead_dervied (context, crypto);
2377*ebfedea0SLionel Sambuc     else
2378*ebfedea0SLionel Sambuc 	return crypto_overhead (context, crypto);
2379*ebfedea0SLionel Sambuc }
2380*ebfedea0SLionel Sambuc 
2381*ebfedea0SLionel Sambuc /**
2382*ebfedea0SLionel Sambuc  * Converts the random bytestring to a protocol key according to
2383*ebfedea0SLionel Sambuc  * Kerberos crypto frame work. It may be assumed that all the bits of
2384*ebfedea0SLionel Sambuc  * the input string are equally random, even though the entropy
2385*ebfedea0SLionel Sambuc  * present in the random source may be limited.
2386*ebfedea0SLionel Sambuc  *
2387*ebfedea0SLionel Sambuc  * @param context Kerberos 5 context
2388*ebfedea0SLionel Sambuc  * @param type the enctype resulting key will be of
2389*ebfedea0SLionel Sambuc  * @param data input random data to convert to a key
2390*ebfedea0SLionel Sambuc  * @param size size of input random data, at least krb5_enctype_keysize() long
2391*ebfedea0SLionel Sambuc  * @param key key, output key, free with krb5_free_keyblock_contents()
2392*ebfedea0SLionel Sambuc  *
2393*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2394*ebfedea0SLionel Sambuc  *
2395*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2396*ebfedea0SLionel Sambuc  */
2397*ebfedea0SLionel Sambuc 
2398*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2399*ebfedea0SLionel Sambuc krb5_random_to_key(krb5_context context,
2400*ebfedea0SLionel Sambuc 		   krb5_enctype type,
2401*ebfedea0SLionel Sambuc 		   const void *data,
2402*ebfedea0SLionel Sambuc 		   size_t size,
2403*ebfedea0SLionel Sambuc 		   krb5_keyblock *key)
2404*ebfedea0SLionel Sambuc {
2405*ebfedea0SLionel Sambuc     krb5_error_code ret;
2406*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2407*ebfedea0SLionel Sambuc     if(et == NULL) {
2408*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2409*ebfedea0SLionel Sambuc 			       N_("encryption type %d not supported", ""),
2410*ebfedea0SLionel Sambuc 			       type);
2411*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2412*ebfedea0SLionel Sambuc     }
2413*ebfedea0SLionel Sambuc     if ((et->keytype->bits + 7) / 8 > size) {
2414*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2415*ebfedea0SLionel Sambuc 			       N_("encryption key %s needs %d bytes "
2416*ebfedea0SLionel Sambuc 				  "of random to make an encryption key "
2417*ebfedea0SLionel Sambuc 				  "out of it", ""),
2418*ebfedea0SLionel Sambuc 			       et->name, (int)et->keytype->size);
2419*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2420*ebfedea0SLionel Sambuc     }
2421*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
2422*ebfedea0SLionel Sambuc     if(ret)
2423*ebfedea0SLionel Sambuc 	return ret;
2424*ebfedea0SLionel Sambuc     key->keytype = type;
2425*ebfedea0SLionel Sambuc     if (et->keytype->random_to_key)
2426*ebfedea0SLionel Sambuc  	(*et->keytype->random_to_key)(context, key, data, size);
2427*ebfedea0SLionel Sambuc     else
2428*ebfedea0SLionel Sambuc 	memcpy(key->keyvalue.data, data, et->keytype->size);
2429*ebfedea0SLionel Sambuc 
2430*ebfedea0SLionel Sambuc     return 0;
2431*ebfedea0SLionel Sambuc }
2432*ebfedea0SLionel Sambuc 
2433*ebfedea0SLionel Sambuc 
2434*ebfedea0SLionel Sambuc 
2435*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2436*ebfedea0SLionel Sambuc krb5_crypto_prf_length(krb5_context context,
2437*ebfedea0SLionel Sambuc 		       krb5_enctype type,
2438*ebfedea0SLionel Sambuc 		       size_t *length)
2439*ebfedea0SLionel Sambuc {
2440*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = _krb5_find_enctype(type);
2441*ebfedea0SLionel Sambuc 
2442*ebfedea0SLionel Sambuc     if(et == NULL || et->prf_length == 0) {
2443*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2444*ebfedea0SLionel Sambuc 			       N_("encryption type %d not supported", ""),
2445*ebfedea0SLionel Sambuc 			       type);
2446*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2447*ebfedea0SLionel Sambuc     }
2448*ebfedea0SLionel Sambuc 
2449*ebfedea0SLionel Sambuc     *length = et->prf_length;
2450*ebfedea0SLionel Sambuc     return 0;
2451*ebfedea0SLionel Sambuc }
2452*ebfedea0SLionel Sambuc 
2453*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2454*ebfedea0SLionel Sambuc krb5_crypto_prf(krb5_context context,
2455*ebfedea0SLionel Sambuc 		const krb5_crypto crypto,
2456*ebfedea0SLionel Sambuc 		const krb5_data *input,
2457*ebfedea0SLionel Sambuc 		krb5_data *output)
2458*ebfedea0SLionel Sambuc {
2459*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *et = crypto->et;
2460*ebfedea0SLionel Sambuc 
2461*ebfedea0SLionel Sambuc     krb5_data_zero(output);
2462*ebfedea0SLionel Sambuc 
2463*ebfedea0SLionel Sambuc     if(et->prf == NULL) {
2464*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
2465*ebfedea0SLionel Sambuc 			       "kerberos prf for %s not supported",
2466*ebfedea0SLionel Sambuc 			       et->name);
2467*ebfedea0SLionel Sambuc 	return KRB5_PROG_ETYPE_NOSUPP;
2468*ebfedea0SLionel Sambuc     }
2469*ebfedea0SLionel Sambuc 
2470*ebfedea0SLionel Sambuc     return (*et->prf)(context, crypto, input, output);
2471*ebfedea0SLionel Sambuc }
2472*ebfedea0SLionel Sambuc 
2473*ebfedea0SLionel Sambuc static krb5_error_code
2474*ebfedea0SLionel Sambuc krb5_crypto_prfplus(krb5_context context,
2475*ebfedea0SLionel Sambuc 		    const krb5_crypto crypto,
2476*ebfedea0SLionel Sambuc 		    const krb5_data *input,
2477*ebfedea0SLionel Sambuc 		    size_t length,
2478*ebfedea0SLionel Sambuc 		    krb5_data *output)
2479*ebfedea0SLionel Sambuc {
2480*ebfedea0SLionel Sambuc     krb5_error_code ret;
2481*ebfedea0SLionel Sambuc     krb5_data input2;
2482*ebfedea0SLionel Sambuc     unsigned char i = 1;
2483*ebfedea0SLionel Sambuc     unsigned char *p;
2484*ebfedea0SLionel Sambuc 
2485*ebfedea0SLionel Sambuc     krb5_data_zero(&input2);
2486*ebfedea0SLionel Sambuc     krb5_data_zero(output);
2487*ebfedea0SLionel Sambuc 
2488*ebfedea0SLionel Sambuc     krb5_clear_error_message(context);
2489*ebfedea0SLionel Sambuc 
2490*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(output, length);
2491*ebfedea0SLionel Sambuc     if (ret) goto out;
2492*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(&input2, input->length + 1);
2493*ebfedea0SLionel Sambuc     if (ret) goto out;
2494*ebfedea0SLionel Sambuc 
2495*ebfedea0SLionel Sambuc     krb5_clear_error_message(context);
2496*ebfedea0SLionel Sambuc 
2497*ebfedea0SLionel Sambuc     memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
2498*ebfedea0SLionel Sambuc 
2499*ebfedea0SLionel Sambuc     p = output->data;
2500*ebfedea0SLionel Sambuc 
2501*ebfedea0SLionel Sambuc     while (length) {
2502*ebfedea0SLionel Sambuc 	krb5_data block;
2503*ebfedea0SLionel Sambuc 
2504*ebfedea0SLionel Sambuc 	((unsigned char *)input2.data)[0] = i++;
2505*ebfedea0SLionel Sambuc 
2506*ebfedea0SLionel Sambuc 	ret = krb5_crypto_prf(context, crypto, &input2, &block);
2507*ebfedea0SLionel Sambuc 	if (ret)
2508*ebfedea0SLionel Sambuc 	    goto out;
2509*ebfedea0SLionel Sambuc 
2510*ebfedea0SLionel Sambuc 	if (block.length < length) {
2511*ebfedea0SLionel Sambuc 	    memcpy(p, block.data, block.length);
2512*ebfedea0SLionel Sambuc 	    length -= block.length;
2513*ebfedea0SLionel Sambuc 	} else {
2514*ebfedea0SLionel Sambuc 	    memcpy(p, block.data, length);
2515*ebfedea0SLionel Sambuc 	    length = 0;
2516*ebfedea0SLionel Sambuc 	}
2517*ebfedea0SLionel Sambuc 	p += block.length;
2518*ebfedea0SLionel Sambuc 	krb5_data_free(&block);
2519*ebfedea0SLionel Sambuc     }
2520*ebfedea0SLionel Sambuc 
2521*ebfedea0SLionel Sambuc  out:
2522*ebfedea0SLionel Sambuc     krb5_data_free(&input2);
2523*ebfedea0SLionel Sambuc     if (ret)
2524*ebfedea0SLionel Sambuc 	krb5_data_free(output);
2525*ebfedea0SLionel Sambuc     return 0;
2526*ebfedea0SLionel Sambuc }
2527*ebfedea0SLionel Sambuc 
2528*ebfedea0SLionel Sambuc /**
2529*ebfedea0SLionel Sambuc  * The FX-CF2 key derivation function, used in FAST and preauth framework.
2530*ebfedea0SLionel Sambuc  *
2531*ebfedea0SLionel Sambuc  * @param context Kerberos 5 context
2532*ebfedea0SLionel Sambuc  * @param crypto1 first key to combine
2533*ebfedea0SLionel Sambuc  * @param crypto2 second key to combine
2534*ebfedea0SLionel Sambuc  * @param pepper1 factor to combine with first key to garante uniqueness
2535*ebfedea0SLionel Sambuc  * @param pepper2 factor to combine with second key to garante uniqueness
2536*ebfedea0SLionel Sambuc  * @param enctype the encryption type of the resulting key
2537*ebfedea0SLionel Sambuc  * @param res allocated key, free with krb5_free_keyblock_contents()
2538*ebfedea0SLionel Sambuc  *
2539*ebfedea0SLionel Sambuc  * @return Return an error code or 0.
2540*ebfedea0SLionel Sambuc  *
2541*ebfedea0SLionel Sambuc  * @ingroup krb5_crypto
2542*ebfedea0SLionel Sambuc  */
2543*ebfedea0SLionel Sambuc 
2544*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2545*ebfedea0SLionel Sambuc krb5_crypto_fx_cf2(krb5_context context,
2546*ebfedea0SLionel Sambuc 		   const krb5_crypto crypto1,
2547*ebfedea0SLionel Sambuc 		   const krb5_crypto crypto2,
2548*ebfedea0SLionel Sambuc 		   krb5_data *pepper1,
2549*ebfedea0SLionel Sambuc 		   krb5_data *pepper2,
2550*ebfedea0SLionel Sambuc 		   krb5_enctype enctype,
2551*ebfedea0SLionel Sambuc 		   krb5_keyblock *res)
2552*ebfedea0SLionel Sambuc {
2553*ebfedea0SLionel Sambuc     krb5_error_code ret;
2554*ebfedea0SLionel Sambuc     krb5_data os1, os2;
2555*ebfedea0SLionel Sambuc     size_t i, keysize;
2556*ebfedea0SLionel Sambuc 
2557*ebfedea0SLionel Sambuc     memset(res, 0, sizeof(*res));
2558*ebfedea0SLionel Sambuc 
2559*ebfedea0SLionel Sambuc     ret = krb5_enctype_keysize(context, enctype, &keysize);
2560*ebfedea0SLionel Sambuc     if (ret)
2561*ebfedea0SLionel Sambuc 	return ret;
2562*ebfedea0SLionel Sambuc 
2563*ebfedea0SLionel Sambuc     ret = krb5_data_alloc(&res->keyvalue, keysize);
2564*ebfedea0SLionel Sambuc     if (ret)
2565*ebfedea0SLionel Sambuc 	goto out;
2566*ebfedea0SLionel Sambuc     ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
2567*ebfedea0SLionel Sambuc     if (ret)
2568*ebfedea0SLionel Sambuc 	goto out;
2569*ebfedea0SLionel Sambuc     ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
2570*ebfedea0SLionel Sambuc     if (ret)
2571*ebfedea0SLionel Sambuc 	goto out;
2572*ebfedea0SLionel Sambuc 
2573*ebfedea0SLionel Sambuc     res->keytype = enctype;
2574*ebfedea0SLionel Sambuc     {
2575*ebfedea0SLionel Sambuc 	unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
2576*ebfedea0SLionel Sambuc 	for (i = 0; i < keysize; i++)
2577*ebfedea0SLionel Sambuc 	    p3[i] = p1[i] ^ p2[i];
2578*ebfedea0SLionel Sambuc     }
2579*ebfedea0SLionel Sambuc  out:
2580*ebfedea0SLionel Sambuc     if (ret)
2581*ebfedea0SLionel Sambuc 	krb5_data_free(&res->keyvalue);
2582*ebfedea0SLionel Sambuc     krb5_data_free(&os1);
2583*ebfedea0SLionel Sambuc     krb5_data_free(&os2);
2584*ebfedea0SLionel Sambuc 
2585*ebfedea0SLionel Sambuc     return ret;
2586*ebfedea0SLionel Sambuc }
2587*ebfedea0SLionel Sambuc 
2588*ebfedea0SLionel Sambuc 
2589*ebfedea0SLionel Sambuc 
2590*ebfedea0SLionel Sambuc #ifndef HEIMDAL_SMALLER
2591*ebfedea0SLionel Sambuc 
2592*ebfedea0SLionel Sambuc /**
2593*ebfedea0SLionel Sambuc  * Deprecated: keytypes doesn't exists, they are really enctypes.
2594*ebfedea0SLionel Sambuc  *
2595*ebfedea0SLionel Sambuc  * @ingroup krb5_deprecated
2596*ebfedea0SLionel Sambuc  */
2597*ebfedea0SLionel Sambuc 
2598*ebfedea0SLionel Sambuc KRB5_DEPRECATED
2599*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
2600*ebfedea0SLionel Sambuc krb5_keytype_to_enctypes (krb5_context context,
2601*ebfedea0SLionel Sambuc 			  krb5_keytype keytype,
2602*ebfedea0SLionel Sambuc 			  unsigned *len,
2603*ebfedea0SLionel Sambuc 			  krb5_enctype **val)
2604*ebfedea0SLionel Sambuc {
2605*ebfedea0SLionel Sambuc     int i;
2606*ebfedea0SLionel Sambuc     unsigned n = 0;
2607*ebfedea0SLionel Sambuc     krb5_enctype *ret;
2608*ebfedea0SLionel Sambuc 
2609*ebfedea0SLionel Sambuc     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2610*ebfedea0SLionel Sambuc 	if (_krb5_etypes[i]->keytype->type == keytype
2611*ebfedea0SLionel Sambuc 	    && !(_krb5_etypes[i]->flags & F_PSEUDO)
2612*ebfedea0SLionel Sambuc 	    && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2613*ebfedea0SLionel Sambuc 	    ++n;
2614*ebfedea0SLionel Sambuc     }
2615*ebfedea0SLionel Sambuc     if (n == 0) {
2616*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
2617*ebfedea0SLionel Sambuc 			       "Keytype have no mapping");
2618*ebfedea0SLionel Sambuc 	return KRB5_PROG_KEYTYPE_NOSUPP;
2619*ebfedea0SLionel Sambuc     }
2620*ebfedea0SLionel Sambuc 
2621*ebfedea0SLionel Sambuc     ret = malloc(n * sizeof(*ret));
2622*ebfedea0SLionel Sambuc     if (ret == NULL && n != 0) {
2623*ebfedea0SLionel Sambuc 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
2624*ebfedea0SLionel Sambuc 	return ENOMEM;
2625*ebfedea0SLionel Sambuc     }
2626*ebfedea0SLionel Sambuc     n = 0;
2627*ebfedea0SLionel Sambuc     for (i = _krb5_num_etypes - 1; i >= 0; --i) {
2628*ebfedea0SLionel Sambuc 	if (_krb5_etypes[i]->keytype->type == keytype
2629*ebfedea0SLionel Sambuc 	    && !(_krb5_etypes[i]->flags & F_PSEUDO)
2630*ebfedea0SLionel Sambuc 	    && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0)
2631*ebfedea0SLionel Sambuc 	    ret[n++] = _krb5_etypes[i]->type;
2632*ebfedea0SLionel Sambuc     }
2633*ebfedea0SLionel Sambuc     *len = n;
2634*ebfedea0SLionel Sambuc     *val = ret;
2635*ebfedea0SLionel Sambuc     return 0;
2636*ebfedea0SLionel Sambuc }
2637*ebfedea0SLionel Sambuc 
2638*ebfedea0SLionel Sambuc /**
2639*ebfedea0SLionel Sambuc  * Deprecated: keytypes doesn't exists, they are really enctypes.
2640*ebfedea0SLionel Sambuc  *
2641*ebfedea0SLionel Sambuc  * @ingroup krb5_deprecated
2642*ebfedea0SLionel Sambuc  */
2643*ebfedea0SLionel Sambuc 
2644*ebfedea0SLionel Sambuc /* if two enctypes have compatible keys */
2645*ebfedea0SLionel Sambuc KRB5_DEPRECATED
2646*ebfedea0SLionel Sambuc KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL
2647*ebfedea0SLionel Sambuc krb5_enctypes_compatible_keys(krb5_context context,
2648*ebfedea0SLionel Sambuc 			      krb5_enctype etype1,
2649*ebfedea0SLionel Sambuc 			      krb5_enctype etype2)
2650*ebfedea0SLionel Sambuc {
2651*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1);
2652*ebfedea0SLionel Sambuc     struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2);
2653*ebfedea0SLionel Sambuc     return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
2654*ebfedea0SLionel Sambuc }
2655*ebfedea0SLionel Sambuc 
2656*ebfedea0SLionel Sambuc #endif /* HEIMDAL_SMALLER */
2657