1 /* 2 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 8 ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). 9 This cipher is widely believed and has been tested to be equivalent 10 with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark 11 of RSA Data Security) 12 13 */ 14 #include <k5-int.h> 15 #include <arcfour.h> 16 17 /* salt string used for exportable ARCFOUR */ 18 static const char *l40 = "fortybits"; 19 20 void 21 krb5_arcfour_encrypt_length(enc, hash, inputlen, length) 22 const struct krb5_enc_provider *enc; 23 const struct krb5_hash_provider *hash; 24 size_t inputlen; 25 size_t *length; 26 { 27 size_t blocksize, hashsize; 28 29 blocksize = enc->block_size; 30 hashsize = hash->hashsize; 31 32 /* checksum + (confounder + inputlen, in even blocksize) */ 33 *length = hashsize + krb5_roundup(8 + inputlen, blocksize); 34 } 35 36 krb5_keyusage 37 krb5int_arcfour_translate_usage(krb5_keyusage usage) 38 { 39 switch (usage) { 40 case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ 41 return 1; 42 case 2: /* ticket from kdc */ 43 return 2; 44 case 3: /* as-rep encrypted part */ 45 return 8; 46 case 4: /* tgs-req authz data */ 47 return 4; 48 case 5: /* tgs-req authz data in subkey */ 49 return 5; 50 case 6: /* tgs-req authenticator cksum */ 51 return 6; 52 case 7: /* tgs-req authenticator */ 53 return 7; 54 case 8: 55 return 8; 56 case 9: /* tgs-rep encrypted with subkey */ 57 return 8; 58 case 10: /* ap-rep authentication cksum */ 59 return 10; /* xxx Microsoft never uses this*/ 60 case 11: /* app-req authenticator */ 61 return 11; 62 case 12: /* app-rep encrypted part */ 63 return 12; 64 case 23: /* sign wrap token*/ 65 return 13; 66 default: 67 return usage; 68 } 69 } 70 71 krb5_error_code 72 krb5_arcfour_encrypt(context, enc, hash, key, usage, ivec, input, output) 73 krb5_context context; 74 const struct krb5_enc_provider *enc; 75 const struct krb5_hash_provider *hash; 76 const krb5_keyblock *key; 77 krb5_keyusage usage; 78 const krb5_data *ivec; 79 const krb5_data *input; 80 krb5_data *output; 81 { 82 krb5_keyblock k1, k2, k3; 83 krb5_keyblock *kptr; 84 krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; 85 krb5_keyusage ms_usage; 86 size_t keybytes, blocksize, hashsize; 87 krb5_error_code ret = 0; 88 89 blocksize = enc->block_size; 90 keybytes = enc->keybytes; 91 hashsize = hash->hashsize; 92 93 bzero(&d2, sizeof(krb5_data)); 94 bzero(&k2, sizeof(krb5_keyblock)); 95 /* 96 * d1 is the contents buffer for key k1. 97 * k1 = HMAC(input_key, salt) 98 */ 99 d1.length=keybytes; 100 d1.data=MALLOC(d1.length); 101 if (d1.data == NULL) 102 return (ENOMEM); 103 bcopy(key, &k1, sizeof (krb5_keyblock)); 104 k1.length=d1.length; 105 k1.contents= (void *) d1.data; 106 107 /* 108 * d2 is the contents of key 'k2', which is used to generate the 109 * checksum field. 'd2' == 'd1' when not using the exportable 110 * enctype. This is only needed when using the exportable 111 * enctype. 112 */ 113 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 114 d2.length=keybytes; 115 d2.data=MALLOC(d2.length); 116 if (d2.data == NULL) { 117 FREE(d1.data, d1.length); 118 return (ENOMEM); 119 } 120 bcopy(key, &k2, sizeof (krb5_keyblock)); 121 k2.length=d2.length; 122 k2.contents=(void *) d2.data; 123 } 124 125 /* 126 * d3 will hold the contents of the final key used for the 127 * encryption step. 'k3' is the key structure that has 'd3' 128 * as its 'contents' field. 129 * k3 = HMAC(k1, checksum) 130 */ 131 d3.length=keybytes; 132 d3.data=MALLOC(d3.length); 133 if (d3.data == NULL) { 134 FREE(d1.data, d1.length); 135 if (d2.data) 136 FREE(d2.data, d2.length); 137 return (ENOMEM); 138 } 139 bcopy(key, &k3, sizeof (krb5_keyblock)); 140 k3.length=d3.length; 141 k3.contents= (void *) d3.data; 142 143 salt.length=14; 144 salt.data=MALLOC(salt.length); 145 146 if (salt.data == NULL) { 147 FREE(d1.data, d1.length); 148 if (d2.data) 149 FREE(d2.data, d2.length); 150 FREE(d3.data, d3.length); 151 return (ENOMEM); 152 } 153 154 /* is "input" already blocksize aligned? if it is, then we need this 155 step, otherwise we do not */ 156 plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); 157 plaintext.data=MALLOC(plaintext.length); 158 159 if (plaintext.data == NULL) { 160 FREE(d1.data, d1.length); 161 if (d2.data) 162 FREE(d2.data, d2.length); 163 FREE(d3.data, d3.length); 164 FREE(salt.data, salt.length); 165 return(ENOMEM); 166 } 167 bzero(plaintext.data, plaintext.length); 168 169 /* setup convienient pointers into the allocated data */ 170 checksum.length=hashsize; 171 checksum.data=output->data; 172 173 ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); 174 ciphertext.data=output->data+hashsize; 175 176 confounder.length=CONFOUNDERLENGTH; 177 confounder.data=plaintext.data; 178 179 output->length = plaintext.length+hashsize; 180 181 /* begin the encryption, computer K1 */ 182 ms_usage=krb5int_arcfour_translate_usage(usage); 183 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 184 (void) strncpy(salt.data, l40, salt.length); 185 salt.data[10]=ms_usage & 0xff; 186 salt.data[11]=(ms_usage >> 8) & 0xff; 187 salt.data[12]=(ms_usage >> 16) & 0xff; 188 salt.data[13]=(ms_usage >> 24) & 0xff; 189 } else { 190 salt.length=4; 191 salt.data[0]=ms_usage & 0xff; 192 salt.data[1]=(ms_usage >> 8) & 0xff; 193 salt.data[2]=(ms_usage >> 16) & 0xff; 194 salt.data[3]=(ms_usage >> 24) & 0xff; 195 } 196 197 #ifdef _KERNEL 198 ret = krb5_hmac(context, key, &salt, &d1); 199 #else 200 ret = krb5_hmac(context, hash, key, 1, &salt, &d1); 201 #endif /* _KERNEL */ 202 if (ret != 0) 203 goto cleanup; 204 205 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 206 bcopy(k1.contents, k2.contents, k2.length); 207 (void) memset(k1.contents+7, 0xab, 9); 208 kptr = &k2; 209 } else { 210 kptr = &k1; 211 } 212 213 /* create a confounder block */ 214 ret=krb5_c_random_make_octets(context, &confounder); 215 bcopy(input->data, plaintext.data+confounder.length, input->length); 216 if (ret) 217 goto cleanup; 218 219 /* 220 * Compute the HMAC checksum field. 221 * checksum = HMAC(k1/k2, plaintext); 222 * k2 used when key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP 223 */ 224 #ifdef _KERNEL 225 ret = krb5_hmac(context, kptr, &plaintext, &checksum); 226 #else 227 ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &checksum); 228 #endif /* _KERNEL */ 229 if (ret) 230 goto cleanup; 231 232 /* 233 * The final encryption key is the HMAC of the checksum 234 * using k1 235 * 236 * k3 = HMAC(k1, checksum); 237 * == or (in other terms) == 238 * k3 = HMAC((HMAC(input_key,salt), HMAC(k1, plaintext)); 239 */ 240 #ifdef _KERNEL 241 ret = krb5_hmac(context, &k1, &checksum, &d3); 242 #else 243 ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); 244 #endif /* _KERNEL */ 245 if (ret) 246 goto cleanup; 247 248 ret = (*(enc->encrypt))(context, &k3, ivec, &plaintext, &ciphertext); 249 250 cleanup: 251 bzero(d1.data, d1.length); 252 if (d2.data) { 253 bzero(d2.data, d2.length); 254 FREE(d2.data, d2.length); 255 } 256 bzero(d3.data, d3.length); 257 bzero(salt.data, salt.length); 258 bzero(plaintext.data, plaintext.length); 259 260 FREE(d1.data, d1.length); 261 FREE(d3.data, d3.length); 262 FREE(salt.data, salt.length); 263 FREE(plaintext.data, plaintext.length); 264 return (ret); 265 } 266 267 /* This is the arcfour-hmac decryption routine */ 268 krb5_error_code 269 krb5_arcfour_decrypt(context, enc, hash, key, usage, ivec, input, output) 270 krb5_context context; 271 const struct krb5_enc_provider *enc; 272 const struct krb5_hash_provider *hash; 273 const krb5_keyblock *key; 274 krb5_keyusage usage; 275 const krb5_data *ivec; 276 const krb5_data *input; 277 krb5_data *output; 278 { 279 krb5_keyblock k1,k2,k3, *kptr; 280 krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; 281 krb5_keyusage ms_usage; 282 size_t keybytes, hashsize; 283 krb5_error_code ret; 284 285 keybytes = enc->keybytes; 286 hashsize = hash->hashsize; 287 288 /* Verify input and output lengths. */ 289 if (input->length < hashsize + CONFOUNDERLENGTH) 290 return KRB5_BAD_MSIZE; 291 if (output->length < input->length - hashsize - CONFOUNDERLENGTH) 292 return KRB5_BAD_MSIZE; 293 294 bzero(&d2, sizeof(krb5_data)); 295 bzero(&k2, sizeof(krb5_keyblock)); 296 /* 297 * d1 is the contents buffer for key k1. 298 * k1 = HMAC(input_key, salt) 299 */ 300 d1.length=keybytes; 301 d1.data=MALLOC(d1.length); 302 if (d1.data == NULL) 303 return (ENOMEM); 304 (void) bcopy(key, &k1, sizeof (krb5_keyblock)); 305 k1.length=d1.length; 306 k1.contents= (void *) d1.data; 307 308 /* 309 * d2 is the contents of key 'k2', which is used to generate the 310 * checksum field. 'd2' == 'd1' when not using the exportable 311 * enctype. This is only needed when using the exportable 312 * enctype. 313 */ 314 if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 315 d2.length=keybytes; 316 d2.data=MALLOC(d2.length); 317 if (d2.data == NULL) { 318 FREE(d1.data, d1.length); 319 return (ENOMEM); 320 } 321 (void) bcopy(key, &k2, sizeof(krb5_keyblock)); 322 k2.length=d2.length; 323 k2.contents= (void *) d2.data; 324 } 325 326 /* 327 * d3 will hold the contents of the final key used for the 328 * encryption step. 'k3' is the key structure that has 'd3' 329 * as its 'contents' field. 330 * k3 = HMAC(k1, checksum) 331 */ 332 d3.length=keybytes; 333 d3.data=MALLOC(d3.length); 334 if (d3.data == NULL) { 335 FREE(d1.data, d1.length); 336 if (d2.data) 337 FREE(d2.data, d2.length); 338 return (ENOMEM); 339 } 340 bcopy(key, &k3, sizeof(krb5_keyblock)); 341 k3.length=d3.length; 342 k3.contents= (void *) d3.data; 343 344 salt.length=14; 345 salt.data=MALLOC(salt.length); 346 if(salt.data==NULL) { 347 FREE(d1.data, d1.length); 348 if (d2.data) 349 FREE(d2.data, d2.length); 350 FREE(d3.data, d3.length); 351 return (ENOMEM); 352 } 353 354 ciphertext.length=input->length-hashsize; 355 ciphertext.data=input->data+hashsize; 356 357 plaintext.length=ciphertext.length; 358 plaintext.data=MALLOC(plaintext.length); 359 if (plaintext.data == NULL) { 360 FREE(d1.data, d1.length); 361 if (d2.data) 362 FREE(d2.data, d2.length); 363 FREE(d3.data, d3.length); 364 FREE(salt.data, salt.length); 365 return (ENOMEM); 366 } 367 368 checksum.length=hashsize; 369 checksum.data=input->data; 370 371 /* compute the salt */ 372 ms_usage=krb5int_arcfour_translate_usage(usage); 373 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 374 (void) strncpy(salt.data, l40, salt.length); 375 salt.data[10]=ms_usage & 0xff; 376 salt.data[11]=(ms_usage>>8) & 0xff; 377 salt.data[12]=(ms_usage>>16) & 0xff; 378 salt.data[13]=(ms_usage>>24) & 0xff; 379 } else { 380 salt.length=4; 381 salt.data[0]=ms_usage & 0xff; 382 salt.data[1]=(ms_usage>>8) & 0xff; 383 salt.data[2]=(ms_usage>>16) & 0xff; 384 salt.data[3]=(ms_usage>>24) & 0xff; 385 } 386 387 #ifdef _KERNEL 388 ret=krb5_hmac(context, key, &salt, &d1); 389 #else 390 ret=krb5_hmac(context, hash, key, 1, &salt, &d1); 391 #endif /* _KERNEL */ 392 if (ret) 393 goto cleanup; 394 395 if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 396 bcopy(k1.contents, k2.contents, d1.length); 397 (void) memset(k1.contents+7, 0xab, 9); 398 kptr = &k2; 399 } else { 400 kptr = &k1; 401 } 402 403 #ifdef _KERNEL 404 ret = krb5_hmac(context, &k1, &checksum, &d3); 405 #else 406 ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); 407 #endif /* _KERNEL */ 408 409 if (ret) 410 goto cleanup; 411 412 ret=(*(enc->decrypt))(context, &k3, ivec, &ciphertext, &plaintext); 413 if (ret) 414 goto cleanup; 415 416 #ifdef _KERNEL 417 ret = krb5_hmac(context, kptr, &plaintext, &d1); 418 #else 419 ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &d1); 420 #endif /* _KERNEL */ 421 422 if (ret) 423 goto cleanup; 424 425 if (bcmp(checksum.data, d1.data, hashsize) != 0) { 426 ret=KRB5KRB_AP_ERR_BAD_INTEGRITY; 427 goto cleanup; 428 } 429 430 bcopy(plaintext.data+CONFOUNDERLENGTH, output->data, 431 (plaintext.length-CONFOUNDERLENGTH)); 432 output->length=plaintext.length-CONFOUNDERLENGTH; 433 434 cleanup: 435 bzero(d1.data, d1.length); 436 if (d2.data) { 437 bzero(d2.data, d2.length); 438 FREE(d2.data, d2.length); 439 } 440 bzero(d3.data, d2.length); 441 bzero(salt.data, salt.length); 442 bzero(plaintext.data, plaintext.length); 443 444 FREE(d1.data, d1.length); 445 FREE(d3.data, d3.length); 446 FREE(salt.data, salt.length); 447 FREE(plaintext.data, plaintext.length); 448 449 return (ret); 450 } 451 452