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