1 /* $NetBSD: crypto-arcfour.c,v 1.1.1.1 2011/04/13 18:15:32 elric Exp $ */ 2 3 /* 4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* 37 * ARCFOUR 38 */ 39 40 #include "krb5_locl.h" 41 42 static struct _krb5_key_type keytype_arcfour = { 43 KEYTYPE_ARCFOUR, 44 "arcfour", 45 128, 46 16, 47 sizeof(struct _krb5_evp_schedule), 48 NULL, 49 _krb5_evp_schedule, 50 _krb5_arcfour_salt, 51 NULL, 52 _krb5_evp_cleanup, 53 EVP_rc4 54 }; 55 56 /* 57 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt 58 */ 59 60 krb5_error_code 61 _krb5_HMAC_MD5_checksum(krb5_context context, 62 struct _krb5_key_data *key, 63 const void *data, 64 size_t len, 65 unsigned usage, 66 Checksum *result) 67 { 68 EVP_MD_CTX *m; 69 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 70 const char signature[] = "signaturekey"; 71 Checksum ksign_c; 72 struct _krb5_key_data ksign; 73 krb5_keyblock kb; 74 unsigned char t[4]; 75 unsigned char tmp[16]; 76 unsigned char ksign_c_data[16]; 77 krb5_error_code ret; 78 79 m = EVP_MD_CTX_create(); 80 if (m == NULL) { 81 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 82 return ENOMEM; 83 } 84 ksign_c.checksum.length = sizeof(ksign_c_data); 85 ksign_c.checksum.data = ksign_c_data; 86 ret = _krb5_internal_hmac(context, c, signature, sizeof(signature), 87 0, key, &ksign_c); 88 if (ret) { 89 EVP_MD_CTX_destroy(m); 90 return ret; 91 } 92 ksign.key = &kb; 93 kb.keyvalue = ksign_c.checksum; 94 EVP_DigestInit_ex(m, EVP_md5(), NULL); 95 t[0] = (usage >> 0) & 0xFF; 96 t[1] = (usage >> 8) & 0xFF; 97 t[2] = (usage >> 16) & 0xFF; 98 t[3] = (usage >> 24) & 0xFF; 99 EVP_DigestUpdate(m, t, 4); 100 EVP_DigestUpdate(m, data, len); 101 EVP_DigestFinal_ex (m, tmp, NULL); 102 EVP_MD_CTX_destroy(m); 103 104 ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); 105 if (ret) 106 return ret; 107 return 0; 108 } 109 110 struct _krb5_checksum_type _krb5_checksum_hmac_md5 = { 111 CKSUMTYPE_HMAC_MD5, 112 "hmac-md5", 113 64, 114 16, 115 F_KEYED | F_CPROOF, 116 _krb5_HMAC_MD5_checksum, 117 NULL 118 }; 119 120 /* 121 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 122 * 123 * warning: not for small children 124 */ 125 126 static krb5_error_code 127 ARCFOUR_subencrypt(krb5_context context, 128 struct _krb5_key_data *key, 129 void *data, 130 size_t len, 131 unsigned usage, 132 void *ivec) 133 { 134 EVP_CIPHER_CTX ctx; 135 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 136 Checksum k1_c, k2_c, k3_c, cksum; 137 struct _krb5_key_data ke; 138 krb5_keyblock kb; 139 unsigned char t[4]; 140 unsigned char *cdata = data; 141 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 142 krb5_error_code ret; 143 144 t[0] = (usage >> 0) & 0xFF; 145 t[1] = (usage >> 8) & 0xFF; 146 t[2] = (usage >> 16) & 0xFF; 147 t[3] = (usage >> 24) & 0xFF; 148 149 k1_c.checksum.length = sizeof(k1_c_data); 150 k1_c.checksum.data = k1_c_data; 151 152 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 153 if (ret) 154 krb5_abortx(context, "hmac failed"); 155 156 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 157 158 k2_c.checksum.length = sizeof(k2_c_data); 159 k2_c.checksum.data = k2_c_data; 160 161 ke.key = &kb; 162 kb.keyvalue = k2_c.checksum; 163 164 cksum.checksum.length = 16; 165 cksum.checksum.data = data; 166 167 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 168 if (ret) 169 krb5_abortx(context, "hmac failed"); 170 171 ke.key = &kb; 172 kb.keyvalue = k1_c.checksum; 173 174 k3_c.checksum.length = sizeof(k3_c_data); 175 k3_c.checksum.data = k3_c_data; 176 177 ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c); 178 if (ret) 179 krb5_abortx(context, "hmac failed"); 180 181 EVP_CIPHER_CTX_init(&ctx); 182 183 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1); 184 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); 185 EVP_CIPHER_CTX_cleanup(&ctx); 186 187 memset (k1_c_data, 0, sizeof(k1_c_data)); 188 memset (k2_c_data, 0, sizeof(k2_c_data)); 189 memset (k3_c_data, 0, sizeof(k3_c_data)); 190 return 0; 191 } 192 193 static krb5_error_code 194 ARCFOUR_subdecrypt(krb5_context context, 195 struct _krb5_key_data *key, 196 void *data, 197 size_t len, 198 unsigned usage, 199 void *ivec) 200 { 201 EVP_CIPHER_CTX ctx; 202 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 203 Checksum k1_c, k2_c, k3_c, cksum; 204 struct _krb5_key_data ke; 205 krb5_keyblock kb; 206 unsigned char t[4]; 207 unsigned char *cdata = data; 208 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 209 unsigned char cksum_data[16]; 210 krb5_error_code ret; 211 212 t[0] = (usage >> 0) & 0xFF; 213 t[1] = (usage >> 8) & 0xFF; 214 t[2] = (usage >> 16) & 0xFF; 215 t[3] = (usage >> 24) & 0xFF; 216 217 k1_c.checksum.length = sizeof(k1_c_data); 218 k1_c.checksum.data = k1_c_data; 219 220 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 221 if (ret) 222 krb5_abortx(context, "hmac failed"); 223 224 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 225 226 k2_c.checksum.length = sizeof(k2_c_data); 227 k2_c.checksum.data = k2_c_data; 228 229 ke.key = &kb; 230 kb.keyvalue = k1_c.checksum; 231 232 k3_c.checksum.length = sizeof(k3_c_data); 233 k3_c.checksum.data = k3_c_data; 234 235 ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); 236 if (ret) 237 krb5_abortx(context, "hmac failed"); 238 239 EVP_CIPHER_CTX_init(&ctx); 240 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0); 241 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); 242 EVP_CIPHER_CTX_cleanup(&ctx); 243 244 ke.key = &kb; 245 kb.keyvalue = k2_c.checksum; 246 247 cksum.checksum.length = 16; 248 cksum.checksum.data = cksum_data; 249 250 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 251 if (ret) 252 krb5_abortx(context, "hmac failed"); 253 254 memset (k1_c_data, 0, sizeof(k1_c_data)); 255 memset (k2_c_data, 0, sizeof(k2_c_data)); 256 memset (k3_c_data, 0, sizeof(k3_c_data)); 257 258 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) { 259 krb5_clear_error_message (context); 260 return KRB5KRB_AP_ERR_BAD_INTEGRITY; 261 } else { 262 return 0; 263 } 264 } 265 266 /* 267 * convert the usage numbers used in 268 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in 269 * draft-brezak-win2k-krb-rc4-hmac-04.txt 270 */ 271 272 krb5_error_code 273 _krb5_usage2arcfour(krb5_context context, unsigned *usage) 274 { 275 switch (*usage) { 276 case KRB5_KU_AS_REP_ENC_PART : /* 3 */ 277 *usage = 8; 278 return 0; 279 case KRB5_KU_USAGE_SEAL : /* 22 */ 280 *usage = 13; 281 return 0; 282 case KRB5_KU_USAGE_SIGN : /* 23 */ 283 *usage = 15; 284 return 0; 285 case KRB5_KU_USAGE_SEQ: /* 24 */ 286 *usage = 0; 287 return 0; 288 default : 289 return 0; 290 } 291 } 292 293 static krb5_error_code 294 ARCFOUR_encrypt(krb5_context context, 295 struct _krb5_key_data *key, 296 void *data, 297 size_t len, 298 krb5_boolean encryptp, 299 int usage, 300 void *ivec) 301 { 302 krb5_error_code ret; 303 unsigned keyusage = usage; 304 305 if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0) 306 return ret; 307 308 if (encryptp) 309 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); 310 else 311 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); 312 } 313 314 struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = { 315 ETYPE_ARCFOUR_HMAC_MD5, 316 "arcfour-hmac-md5", 317 1, 318 1, 319 8, 320 &keytype_arcfour, 321 &_krb5_checksum_hmac_md5, 322 NULL, 323 F_SPECIAL, 324 ARCFOUR_encrypt, 325 0, 326 NULL 327 }; 328