1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * Copyright 1993 by OpenVision Technologies, Inc. 10 * 11 * Permission to use, copy, modify, distribute, and sell this software 12 * and its documentation for any purpose is hereby granted without fee, 13 * provided that the above copyright notice appears in all copies and 14 * that both that copyright notice and this permission notice appear in 15 * supporting documentation, and that the name of OpenVision not be used 16 * in advertising or publicity pertaining to distribution of the software 17 * without specific, written prior permission. OpenVision makes no 18 * representations about the suitability of this software for any 19 * purpose. It is provided "as is" without express or implied warranty. 20 * 21 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 22 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 23 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 25 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 26 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 27 * PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 /* 31 * Copyright (C) 1998 by the FundsXpress, INC. 32 * 33 * All rights reserved. 34 * 35 * Export of this software from the United States of America may require 36 * a specific license from the United States Government. It is the 37 * responsibility of any person or organization contemplating export to 38 * obtain such a license before exporting. 39 * 40 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 41 * distribute this software and its documentation for any purpose and 42 * without fee is hereby granted, provided that the above copyright 43 * notice appear in all copies and that both that copyright notice and 44 * this permission notice appear in supporting documentation, and that 45 * the name of FundsXpress. not be used in advertising or publicity pertaining 46 * to distribution of the software without specific, written prior 47 * permission. FundsXpress makes no representations about the suitability of 48 * this software for any purpose. It is provided "as is" without express 49 * or implied warranty. 50 * 51 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 52 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 53 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 54 */ 55 56 /* Solaris Kerberos: order is important here. include gssapiP_krb5.h 57 * before all others, otherwise we get a LINT error from MALLOC macro 58 * being redefined in mechglueP.h */ 59 #include <gssapiP_krb5.h> 60 #include <k5-int.h> 61 62 /* Solaris Kerberos defines memory management macros in <krb5.h> */ 63 /* #include <memory.h> */ 64 65 /* 66 * $Id: util_crypt.c,v 1.11.6.3 2000/06/03 06:09:45 tlyu Exp $ 67 */ 68 69 int 70 kg_confounder_size(context, key) 71 krb5_context context; 72 krb5_keyblock *key; 73 { 74 size_t blocksize; 75 /* We special case rc4*/ 76 if (key->enctype == ENCTYPE_ARCFOUR_HMAC) 77 return 8; 78 if (krb5_c_block_size(context, key->enctype, &blocksize) != 0) 79 return(-1); /* XXX */ 80 81 return(blocksize); 82 } 83 84 krb5_error_code 85 kg_make_confounder(context, key, buf) 86 krb5_context context; 87 krb5_keyblock *key; 88 unsigned char *buf; 89 { 90 krb5_error_code code; 91 size_t blocksize; 92 krb5_data random; 93 94 if (code = krb5_c_block_size(context, key->enctype, &blocksize)) 95 return(code); 96 97 random.length = blocksize; 98 random.data = (char *) buf; 99 100 return(krb5_c_random_make_octets(context, &random)); 101 } 102 103 int 104 kg_encrypt_size(context, key, n) 105 krb5_context context; 106 krb5_keyblock *key; 107 int n; 108 { 109 size_t enclen; 110 111 if (krb5_c_encrypt_length(context, key->enctype, n, &enclen) != 0) 112 return(-1); /* XXX */ 113 114 return(enclen); 115 } 116 117 krb5_error_code 118 kg_encrypt(context, key, usage, iv, in, out, length) 119 krb5_context context; 120 krb5_keyblock *key; 121 int usage; 122 krb5_pointer iv; 123 krb5_pointer in; 124 krb5_pointer out; 125 unsigned int length; 126 { 127 krb5_error_code code; 128 size_t blocksize; 129 krb5_data ivd, *pivd, inputd; 130 krb5_enc_data outputd; 131 132 KRB5_LOG0(KRB5_INFO, "kg_encrypt() start."); 133 134 if (iv) { 135 if (code = krb5_c_block_size(context, key->enctype, &blocksize)) 136 return(code); 137 138 ivd.length = blocksize; 139 ivd.data = MALLOC(ivd.length); 140 if (ivd.data == NULL) 141 return ENOMEM; 142 (void) memcpy(ivd.data, iv, ivd.length); 143 pivd = &ivd; 144 } else { 145 pivd = NULL; 146 } 147 148 inputd.length = length; 149 inputd.data = in; 150 151 outputd.ciphertext.length = length; 152 outputd.ciphertext.data = out; 153 154 code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd); 155 if (pivd != NULL) 156 krb5_free_data_contents(context, pivd); 157 158 KRB5_LOG(KRB5_INFO, "kg_encrypt() end. code = %d", code); 159 return code; 160 } 161 162 /* length is the length of the cleartext. */ 163 164 krb5_error_code 165 kg_decrypt(context, key, usage, iv, in, out, length) 166 krb5_context context; 167 krb5_keyblock *key; 168 int usage; 169 krb5_pointer iv; 170 krb5_pointer in; 171 krb5_pointer out; 172 unsigned int length; 173 { 174 krb5_error_code code; 175 size_t blocksize; 176 krb5_data ivd, *pivd, outputd; 177 krb5_enc_data inputd; 178 KRB5_LOG0(KRB5_INFO, "kg_decrypt() start."); 179 180 if (iv) { 181 if (code = krb5_c_block_size(context, key->enctype, &blocksize)) 182 return(code); 183 184 ivd.length = blocksize; 185 ivd.data = MALLOC(ivd.length); 186 if (ivd.data == NULL) 187 return ENOMEM; 188 (void) memcpy(ivd.data, iv, ivd.length); 189 pivd = &ivd; 190 } else { 191 pivd = NULL; 192 } 193 194 inputd.enctype = ENCTYPE_UNKNOWN; 195 inputd.ciphertext.length = length; 196 inputd.ciphertext.data = in; 197 198 outputd.length = length; 199 outputd.data = out; 200 201 code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd); 202 if (pivd != NULL) 203 krb5_free_data_contents(context, pivd); 204 205 KRB5_LOG(KRB5_INFO, "kg_decrypt() end. code = %d", code); 206 return code; 207 } 208 209 krb5_error_code 210 kg_arcfour_docrypt (krb5_context context, 211 const krb5_keyblock *longterm_key , int ms_usage, 212 const unsigned char *kd_data, size_t kd_data_len, 213 const unsigned char *input_buf, size_t input_len, 214 unsigned char *output_buf) 215 { 216 krb5_error_code code; 217 krb5_data input, output; 218 krb5_keyblock seq_enc_key, usage_key; 219 unsigned char t[4]; 220 221 KRB5_LOG0(KRB5_INFO, "kg_arcfour_docrypt() start"); 222 223 bzero(&usage_key, sizeof(krb5_keyblock)); 224 bzero(&seq_enc_key, sizeof(krb5_keyblock)); 225 226 usage_key.length = longterm_key->length; 227 usage_key.contents = MALLOC(usage_key.length); 228 usage_key.enctype = longterm_key->enctype; 229 usage_key.dk_list = NULL; 230 #ifdef _KERNEL 231 232 usage_key.kef_mt = longterm_key->kef_mt; 233 code = init_key_kef(longterm_key->kef_mt, &usage_key); 234 if (code) 235 return (code); 236 #endif /* _KERNEL */ 237 if (usage_key.contents == NULL) 238 return (ENOMEM); 239 seq_enc_key.length = longterm_key->length; 240 seq_enc_key.contents = MALLOC(seq_enc_key.length); 241 seq_enc_key.enctype = longterm_key->enctype; 242 seq_enc_key.dk_list = NULL; 243 #ifdef _KERNEL 244 seq_enc_key.kef_mt = longterm_key->kef_mt; 245 code = init_key_kef(longterm_key->kef_mt, &seq_enc_key); 246 if (code) 247 return (code); 248 #endif /* _KERNEL */ 249 if (seq_enc_key.contents == NULL) { 250 FREE ((void *) usage_key.contents, usage_key.length); 251 return (ENOMEM); 252 } 253 254 t[0] = ms_usage &0xff; 255 t[1] = (ms_usage>>8) & 0xff; 256 t[2] = (ms_usage>>16) & 0xff; 257 t[3] = (ms_usage>>24) & 0xff; 258 input.data = (void *) &t; 259 input.length = 4; 260 output.data = (void *) usage_key.contents; 261 output.length = usage_key.length; 262 #ifdef _KERNEL 263 code = krb5_hmac(context, longterm_key, &input, &output); 264 #else 265 code = krb5_hmac(context, &krb5int_hash_md5, 266 longterm_key, 1, &input, &output); 267 #endif /* _KERNEL */ 268 if (code) 269 goto cleanup_arcfour; 270 271 input.data = ( void *) kd_data; 272 input.length = kd_data_len; 273 output.data = (void *) seq_enc_key.contents; 274 #ifdef _KERNEL 275 code = krb5_hmac(context, &usage_key, &input, &output); 276 #else 277 code = krb5_hmac(context, &krb5int_hash_md5, 278 &usage_key, 1, &input, &output); 279 #endif /* _KERNEL */ 280 281 if (code) 282 goto cleanup_arcfour; 283 284 input.data = ( void * ) input_buf; 285 input.length = input_len; 286 287 output.data = (char *)output_buf; 288 output.length = input_len; 289 290 /* 291 * Call the arcfour encryption method directly here, we cannot 292 * use the standard "krb5_c_encrypt" interface because we just 293 * want the arcfour algorithm applied and not the additional MD5-HMAC 294 * which are applied when using the standard interface. 295 */ 296 code = krb5int_enc_arcfour.encrypt(context, &seq_enc_key, 0, &input, &output); 297 298 cleanup_arcfour: 299 bzero ((void *) seq_enc_key.contents, seq_enc_key.length); 300 bzero ((void *) usage_key.contents, usage_key.length); 301 FREE ((void *) usage_key.contents, usage_key.length); 302 FREE ((void *) seq_enc_key.contents, seq_enc_key.length); 303 304 KRB5_LOG(KRB5_INFO, "kg_arcfour_docrypt() end code = %d", code); 305 return (code); 306 } 307