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 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 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 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 124 krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock) 125 { 126 return 0; 127 } 128 129 krb5_error_code KRB5_CALLCONV 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 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 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 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 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 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 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 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 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 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 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 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 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 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 369 valid_cksumtype(krb5_cksumtype ctype) 370 { 371 return krb5_c_valid_cksumtype(ctype); 372 } 373 374 krb5_boolean KRB5_CALLCONV 375 is_keyed_cksum(krb5_cksumtype ctype) 376 { 377 return krb5_c_is_keyed_cksum(ctype); 378 } 379 380 krb5_boolean KRB5_CALLCONV 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 387 valid_enctype(krb5_enctype etype) 388 { 389 return krb5_c_valid_enctype(etype); 390 } 391