1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 
7 /*
8  * Copyright (C) 1998 by the FundsXpress, INC.
9  *
10  * All rights reserved.
11  *
12  * Export of this software from the United States of America may require
13  * a specific license from the United States Government.  It is the
14  * responsibility of any person or organization contemplating export to
15  * obtain such a license before exporting.
16  *
17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18  * distribute this software and its documentation for any purpose and
19  * without fee is hereby granted, provided that the above copyright
20  * notice appear in all copies and that both that copyright notice and
21  * this permission notice appear in supporting documentation, and that
22  * the name of FundsXpress. not be used in advertising or publicity pertaining
23  * to distribution of the software without specific, written prior
24  * permission.  FundsXpress makes no representations about the suitability of
25  * this software for any purpose.  It is provided "as is" without express
26  * or implied warranty.
27  *
28  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31  */
32 
33 #include "k5-int.h"
34 
35 /*
36  * Solaris Kerberos
37  * krb5_string_to_key/krb5_use_enctype are needed by Samba
38  */
39 
40 krb5_error_code KRB5_CALLCONV
krb5_encrypt(krb5_context context,krb5_const_pointer inptr,krb5_pointer outptr,size_t size,krb5_encrypt_block * eblock,krb5_pointer ivec)41 krb5_encrypt(krb5_context context, krb5_const_pointer inptr,
42 	     krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
43 	     krb5_pointer ivec)
44 {
45     krb5_data inputd, ivecd;
46     krb5_enc_data outputd;
47     size_t blocksize, outlen;
48     krb5_error_code ret;
49 
50     if (ivec) {
51 	if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
52 	    return(ret);
53 
54 	ivecd.length = blocksize;
55 	ivecd.data = ivec;
56     }
57 
58     /* size is the length of the input cleartext data */
59     inputd.length = size;
60     inputd.data = (char*)inptr;
61 
62     /* The size of the output buffer isn't part of the old api.  Not too
63        safe.  So, we assume here that it's big enough. */
64     if ((ret = krb5_c_encrypt_length(context, eblock->key->enctype, size,
65 				     &outlen)))
66 	return(ret);
67 
68     outputd.ciphertext.length = outlen;
69     outputd.ciphertext.data = outptr;
70 
71     return(krb5_c_encrypt(context, eblock->key, 0, ivec?&ivecd:0,
72 			  &inputd, &outputd));
73 }
74 
75 krb5_error_code KRB5_CALLCONV
krb5_decrypt(krb5_context context,krb5_const_pointer inptr,krb5_pointer outptr,size_t size,krb5_encrypt_block * eblock,krb5_pointer ivec)76 krb5_decrypt(krb5_context context, krb5_const_pointer inptr,
77 	     krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
78 	     krb5_pointer ivec)
79 {
80     krb5_enc_data inputd;
81     krb5_data outputd, ivecd;
82     size_t blocksize;
83     krb5_error_code ret;
84 
85     if (ivec) {
86 	if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
87 	    return(ret);
88 
89 	ivecd.length = blocksize;
90 	ivecd.data = ivec;
91     }
92 
93     /* size is the length of the input ciphertext data */
94     inputd.enctype = eblock->key->enctype;
95     inputd.ciphertext.length = size;
96     /* Solaris Kerberos */
97     inputd.ciphertext.data = (char*)inptr;
98 
99     /* we don't really know how big this is, but the code tends to assume
100        that the output buffer size should be the same as the input
101        buffer size */
102     outputd.length = size;
103     outputd.data = outptr;
104 
105     return(krb5_c_decrypt(context, eblock->key, 0, ivec?&ivecd:0,
106 			  &inputd, &outputd));
107 }
108 
109 krb5_error_code KRB5_CALLCONV
krb5_process_key(krb5_context context,krb5_encrypt_block * eblock,const krb5_keyblock * key)110 krb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
111 		 const krb5_keyblock *key)
112 {
113     eblock->key = (krb5_keyblock *) key;
114 
115     return(0);
116 }
117 
118 krb5_error_code KRB5_CALLCONV
krb5_finish_key(krb5_context context,krb5_encrypt_block * eblock)119 krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
120 {
121     return(0);
122 }
123 
124 krb5_error_code KRB5_CALLCONV
krb5_string_to_key(krb5_context context,const krb5_encrypt_block * eblock,krb5_keyblock * keyblock,const krb5_data * data,const krb5_data * salt)125 krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
126 		   krb5_keyblock *keyblock, const krb5_data *data,
127 		   const krb5_data *salt)
128 {
129     return(krb5_c_string_to_key(context, eblock->crypto_entry, data, salt,
130 				keyblock));
131 }
132 
133 krb5_error_code KRB5_CALLCONV
krb5_init_random_key(krb5_context context,const krb5_encrypt_block * eblock,const krb5_keyblock * keyblock,krb5_pointer * ptr)134 krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
135 		     const krb5_keyblock *keyblock, krb5_pointer *ptr)
136 {
137     krb5_data data;
138 
139     data.length = keyblock->length;
140     data.data = (char *) keyblock->contents;
141 
142     return(krb5_c_random_seed(context, &data));
143 }
144 
145 krb5_error_code KRB5_CALLCONV
krb5_finish_random_key(krb5_context context,const krb5_encrypt_block * eblock,krb5_pointer * ptr)146 krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
147 		       krb5_pointer *ptr)
148 {
149     return(0);
150 }
151 
152 krb5_error_code KRB5_CALLCONV
krb5_random_key(krb5_context context,const krb5_encrypt_block * eblock,krb5_pointer ptr,krb5_keyblock ** keyblock)153 krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
154 		krb5_pointer ptr, krb5_keyblock **keyblock)
155 {
156     krb5_keyblock *key;
157     krb5_error_code ret;
158 
159     if ((key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
160 	return(ENOMEM);
161 
162     if ((ret = krb5_c_make_random_key(context, eblock->crypto_entry, key)))
163 	free(key);
164 
165     *keyblock = key;
166 
167     return(ret);
168 }
169 
170 krb5_enctype KRB5_CALLCONV
krb5_eblock_enctype(krb5_context context,const krb5_encrypt_block * eblock)171 krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
172 {
173     return(eblock->crypto_entry);
174 }
175 
176 krb5_error_code KRB5_CALLCONV
krb5_use_enctype(krb5_context context,krb5_encrypt_block * eblock,krb5_enctype enctype)177 krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
178 		 krb5_enctype enctype)
179 {
180     eblock->crypto_entry = enctype;
181 
182     return(0);
183 }
184 
185 size_t KRB5_CALLCONV
krb5_encrypt_size(size_t length,krb5_enctype crypto)186 krb5_encrypt_size(size_t length, krb5_enctype crypto)
187 {
188     size_t ret;
189 
190     if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
191 	return(-1); /* XXX */
192 
193     return(ret);
194 }
195 
196 size_t KRB5_CALLCONV
krb5_checksum_size(krb5_context context,krb5_cksumtype ctype)197 krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
198 {
199     size_t ret;
200 
201     if (krb5_c_checksum_length(context, ctype, &ret))
202 	return(-1); /* XXX */
203 
204     return(ret);
205 }
206 
207 krb5_error_code KRB5_CALLCONV
krb5_calculate_checksum(krb5_context context,krb5_cksumtype ctype,krb5_const_pointer in,size_t in_length,krb5_const_pointer seed,size_t seed_length,krb5_checksum * outcksum)208 krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
209 			krb5_const_pointer in, size_t in_length,
210 			krb5_const_pointer seed, size_t seed_length,
211 			krb5_checksum *outcksum)
212 {
213     krb5_data input;
214     krb5_keyblock key;
215     krb5_error_code ret;
216     krb5_checksum cksum;
217 
218     /* Solaris Kerberos */
219     input.data = (char*)in;
220     input.length = in_length;
221 
222     key.length = seed_length;
223     /* Solaris Kerberos */
224     key.contents = (unsigned char*)seed;
225 
226     if ((ret = krb5_c_make_checksum(context, ctype, &key, 0, &input, &cksum)))
227 	return(ret);
228 
229     if (outcksum->length < cksum.length) {
230 	memset(cksum.contents, 0, cksum.length);
231 	free(cksum.contents);
232 	return(KRB5_BAD_MSIZE);
233     }
234 
235     outcksum->magic = cksum.magic;
236     outcksum->checksum_type = cksum.checksum_type;
237     memcpy(outcksum->contents, cksum.contents, cksum.length);
238     outcksum->length = cksum.length;
239 
240     free(cksum.contents);
241 
242     return(0);
243 }
244 
245 krb5_error_code KRB5_CALLCONV
krb5_verify_checksum(krb5_context context,krb5_cksumtype ctype,const krb5_checksum * cksum,krb5_const_pointer in,size_t in_length,krb5_const_pointer seed,size_t seed_length)246 krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
247 		     const krb5_checksum *cksum, krb5_const_pointer in,
248 		     size_t in_length, krb5_const_pointer seed,
249 		     size_t seed_length)
250 {
251     krb5_data input;
252     krb5_keyblock key;
253     krb5_error_code ret;
254     krb5_boolean valid;
255 
256     /* Solaris Kerberos */
257     input.data = (char*)in;
258     input.length = in_length;
259 
260     key.length = seed_length;
261     /* Solaris Kerberos */
262     key.contents = (unsigned char*)seed;
263 
264     if ((ret = krb5_c_verify_checksum(context, &key, 0, &input, cksum,
265 				      &valid)))
266 	return(ret);
267 
268     if (!valid)
269 	return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
270 
271     return(0);
272 }
273 
274 krb5_error_code KRB5_CALLCONV
krb5_random_confounder(size_t size,krb5_pointer ptr)275 krb5_random_confounder(size_t size, krb5_pointer ptr)
276 {
277     krb5_data random_data;
278 
279     random_data.length = size;
280     random_data.data = ptr;
281 
282     return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
283 }
284 
krb5_encrypt_data(krb5_context context,krb5_keyblock * key,krb5_pointer ivec,krb5_data * data,krb5_enc_data * enc_data)285 krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
286 				  krb5_pointer ivec, krb5_data *data,
287 				  krb5_enc_data *enc_data)
288 {
289     krb5_error_code ret;
290     size_t enclen, blocksize;
291     krb5_data ivecd;
292 
293     if ((ret = krb5_c_encrypt_length(context, key->enctype, data->length,
294 				     &enclen)))
295 	return(ret);
296 
297     if (ivec) {
298 	if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
299 	    return(ret);
300 
301 	ivecd.length = blocksize;
302 	ivecd.data = ivec;
303     }
304 
305     enc_data->magic = KV5M_ENC_DATA;
306     enc_data->kvno = 0;
307     enc_data->enctype = key->enctype;
308     enc_data->ciphertext.length = enclen;
309     if ((enc_data->ciphertext.data = malloc(enclen)) == NULL)
310 	return(ENOMEM);
311 
312     if ((ret = krb5_c_encrypt(context, key, 0, ivec?&ivecd:0, data, enc_data)))
313 	free(enc_data->ciphertext.data);
314 
315     return(ret);
316 }
317 
krb5_decrypt_data(krb5_context context,krb5_keyblock * key,krb5_pointer ivec,krb5_enc_data * enc_data,krb5_data * data)318 krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
319 				  krb5_pointer ivec, krb5_enc_data *enc_data,
320 				  krb5_data *data)
321 {
322     krb5_error_code ret;
323     krb5_data ivecd;
324     size_t blocksize;
325 
326     if (ivec) {
327 	if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
328 	    return(ret);
329 
330 	ivecd.length = blocksize;
331 	ivecd.data = ivec;
332     }
333 
334     data->length = enc_data->ciphertext.length;
335     if ((data->data = (char *) malloc(data->length)) == NULL)
336 	return(ENOMEM);
337 
338     if ((ret = krb5_c_decrypt(context, key, 0, ivec?&ivecd:0, enc_data, data)))
339 	free(data->data);
340 
341     /* Solaris Kerberos */
342     return(ret);
343 }
344