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 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 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 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 119 krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock) 120 { 121 return(0); 122 } 123 124 krb5_error_code KRB5_CALLCONV 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 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 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 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 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 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 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 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 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 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 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 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 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