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