17c478bd9Sstevel@tonic-gate /* 2*505d05c7Sgtb * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gate /* 97c478bd9Sstevel@tonic-gate 107c478bd9Sstevel@tonic-gate ARCFOUR cipher (based on a cipher posted on the Usenet in Spring-95). 117c478bd9Sstevel@tonic-gate This cipher is widely believed and has been tested to be equivalent 127c478bd9Sstevel@tonic-gate with the RC4 cipher from RSA Data Security, Inc. (RC4 is a trademark 137c478bd9Sstevel@tonic-gate of RSA Data Security) 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate */ 167c478bd9Sstevel@tonic-gate #include <k5-int.h> 177c478bd9Sstevel@tonic-gate #include <arcfour.h> 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate /* salt string used for exportable ARCFOUR */ 207c478bd9Sstevel@tonic-gate static const char *l40 = "fortybits"; 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate void 237c478bd9Sstevel@tonic-gate krb5_arcfour_encrypt_length(enc, hash, inputlen, length) 247c478bd9Sstevel@tonic-gate const struct krb5_enc_provider *enc; 257c478bd9Sstevel@tonic-gate const struct krb5_hash_provider *hash; 267c478bd9Sstevel@tonic-gate size_t inputlen; 277c478bd9Sstevel@tonic-gate size_t *length; 287c478bd9Sstevel@tonic-gate { 297c478bd9Sstevel@tonic-gate size_t blocksize, hashsize; 307c478bd9Sstevel@tonic-gate 31*505d05c7Sgtb blocksize = enc->block_size; 32*505d05c7Sgtb hashsize = hash->hashsize; 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* checksum + (confounder + inputlen, in even blocksize) */ 357c478bd9Sstevel@tonic-gate *length = hashsize + krb5_roundup(8 + inputlen, blocksize); 367c478bd9Sstevel@tonic-gate } 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate krb5_keyusage 397c478bd9Sstevel@tonic-gate krb5int_arcfour_translate_usage(krb5_keyusage usage) 407c478bd9Sstevel@tonic-gate { 417c478bd9Sstevel@tonic-gate switch (usage) { 427c478bd9Sstevel@tonic-gate case 1: /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, */ 437c478bd9Sstevel@tonic-gate return 1; 447c478bd9Sstevel@tonic-gate case 2: /* ticket from kdc */ 457c478bd9Sstevel@tonic-gate return 2; 467c478bd9Sstevel@tonic-gate case 3: /* as-rep encrypted part */ 477c478bd9Sstevel@tonic-gate return 8; 487c478bd9Sstevel@tonic-gate case 4: /* tgs-req authz data */ 497c478bd9Sstevel@tonic-gate return 4; 507c478bd9Sstevel@tonic-gate case 5: /* tgs-req authz data in subkey */ 517c478bd9Sstevel@tonic-gate return 5; 527c478bd9Sstevel@tonic-gate case 6: /* tgs-req authenticator cksum */ 537c478bd9Sstevel@tonic-gate return 6; 547c478bd9Sstevel@tonic-gate case 7: /* tgs-req authenticator */ 557c478bd9Sstevel@tonic-gate return 7; 567c478bd9Sstevel@tonic-gate case 8: 577c478bd9Sstevel@tonic-gate return 8; 587c478bd9Sstevel@tonic-gate case 9: /* tgs-rep encrypted with subkey */ 597c478bd9Sstevel@tonic-gate return 8; 607c478bd9Sstevel@tonic-gate case 10: /* ap-rep authentication cksum */ 617c478bd9Sstevel@tonic-gate return 10; /* xxx Microsoft never uses this*/ 627c478bd9Sstevel@tonic-gate case 11: /* app-req authenticator */ 637c478bd9Sstevel@tonic-gate return 11; 647c478bd9Sstevel@tonic-gate case 12: /* app-rep encrypted part */ 657c478bd9Sstevel@tonic-gate return 12; 667c478bd9Sstevel@tonic-gate case 23: /* sign wrap token*/ 677c478bd9Sstevel@tonic-gate return 13; 687c478bd9Sstevel@tonic-gate default: 697c478bd9Sstevel@tonic-gate return usage; 707c478bd9Sstevel@tonic-gate } 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate krb5_error_code 747c478bd9Sstevel@tonic-gate krb5_arcfour_encrypt(context, enc, hash, key, usage, ivec, input, output) 757c478bd9Sstevel@tonic-gate krb5_context context; 767c478bd9Sstevel@tonic-gate const struct krb5_enc_provider *enc; 777c478bd9Sstevel@tonic-gate const struct krb5_hash_provider *hash; 787c478bd9Sstevel@tonic-gate const krb5_keyblock *key; 797c478bd9Sstevel@tonic-gate krb5_keyusage usage; 807c478bd9Sstevel@tonic-gate const krb5_data *ivec; 817c478bd9Sstevel@tonic-gate const krb5_data *input; 827c478bd9Sstevel@tonic-gate krb5_data *output; 837c478bd9Sstevel@tonic-gate { 847c478bd9Sstevel@tonic-gate krb5_keyblock k1, k2, k3; 857c478bd9Sstevel@tonic-gate krb5_keyblock *kptr; 867c478bd9Sstevel@tonic-gate krb5_data d1, d2, d3, salt, plaintext, checksum, ciphertext, confounder; 877c478bd9Sstevel@tonic-gate krb5_keyusage ms_usage; 88*505d05c7Sgtb size_t keybytes, blocksize, hashsize; 897c478bd9Sstevel@tonic-gate krb5_error_code ret = 0; 907c478bd9Sstevel@tonic-gate 91*505d05c7Sgtb blocksize = enc->block_size; 92*505d05c7Sgtb keybytes = enc->keybytes; 93*505d05c7Sgtb hashsize = hash->hashsize; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate bzero(&d2, sizeof(krb5_data)); 967c478bd9Sstevel@tonic-gate bzero(&k2, sizeof(krb5_keyblock)); 977c478bd9Sstevel@tonic-gate /* 987c478bd9Sstevel@tonic-gate * d1 is the contents buffer for key k1. 997c478bd9Sstevel@tonic-gate * k1 = HMAC(input_key, salt) 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate d1.length=keybytes; 1027c478bd9Sstevel@tonic-gate d1.data=MALLOC(d1.length); 1037c478bd9Sstevel@tonic-gate if (d1.data == NULL) 1047c478bd9Sstevel@tonic-gate return (ENOMEM); 1057c478bd9Sstevel@tonic-gate bcopy(key, &k1, sizeof (krb5_keyblock)); 1067c478bd9Sstevel@tonic-gate k1.length=d1.length; 1077c478bd9Sstevel@tonic-gate k1.contents= (void *) d1.data; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * d2 is the contents of key 'k2', which is used to generate the 1117c478bd9Sstevel@tonic-gate * checksum field. 'd2' == 'd1' when not using the exportable 1127c478bd9Sstevel@tonic-gate * enctype. This is only needed when using the exportable 1137c478bd9Sstevel@tonic-gate * enctype. 1147c478bd9Sstevel@tonic-gate */ 1157c478bd9Sstevel@tonic-gate if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 1167c478bd9Sstevel@tonic-gate d2.length=keybytes; 1177c478bd9Sstevel@tonic-gate d2.data=MALLOC(d2.length); 1187c478bd9Sstevel@tonic-gate if (d2.data == NULL) { 1197c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 1207c478bd9Sstevel@tonic-gate return (ENOMEM); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate bcopy(key, &k2, sizeof (krb5_keyblock)); 1237c478bd9Sstevel@tonic-gate k2.length=d2.length; 1247c478bd9Sstevel@tonic-gate k2.contents=(void *) d2.data; 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * d3 will hold the contents of the final key used for the 1297c478bd9Sstevel@tonic-gate * encryption step. 'k3' is the key structure that has 'd3' 1307c478bd9Sstevel@tonic-gate * as its 'contents' field. 1317c478bd9Sstevel@tonic-gate * k3 = HMAC(k1, checksum) 1327c478bd9Sstevel@tonic-gate */ 1337c478bd9Sstevel@tonic-gate d3.length=keybytes; 1347c478bd9Sstevel@tonic-gate d3.data=MALLOC(d3.length); 1357c478bd9Sstevel@tonic-gate if (d3.data == NULL) { 1367c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 1377c478bd9Sstevel@tonic-gate if (d2.data) 1387c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 1397c478bd9Sstevel@tonic-gate return (ENOMEM); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate bcopy(key, &k3, sizeof (krb5_keyblock)); 1427c478bd9Sstevel@tonic-gate k3.length=d3.length; 1437c478bd9Sstevel@tonic-gate k3.contents= (void *) d3.data; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate salt.length=14; 1467c478bd9Sstevel@tonic-gate salt.data=MALLOC(salt.length); 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (salt.data == NULL) { 1497c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 1507c478bd9Sstevel@tonic-gate if (d2.data) 1517c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 1527c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 1537c478bd9Sstevel@tonic-gate return (ENOMEM); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate 1567c478bd9Sstevel@tonic-gate /* is "input" already blocksize aligned? if it is, then we need this 1577c478bd9Sstevel@tonic-gate step, otherwise we do not */ 1587c478bd9Sstevel@tonic-gate plaintext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); 1597c478bd9Sstevel@tonic-gate plaintext.data=MALLOC(plaintext.length); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate if (plaintext.data == NULL) { 1627c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 1637c478bd9Sstevel@tonic-gate if (d2.data) 1647c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 1657c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 1667c478bd9Sstevel@tonic-gate FREE(salt.data, salt.length); 1677c478bd9Sstevel@tonic-gate return(ENOMEM); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate bzero(plaintext.data, plaintext.length); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* setup convienient pointers into the allocated data */ 1727c478bd9Sstevel@tonic-gate checksum.length=hashsize; 1737c478bd9Sstevel@tonic-gate checksum.data=output->data; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate ciphertext.length=krb5_roundup(input->length+CONFOUNDERLENGTH,blocksize); 1767c478bd9Sstevel@tonic-gate ciphertext.data=output->data+hashsize; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate confounder.length=CONFOUNDERLENGTH; 1797c478bd9Sstevel@tonic-gate confounder.data=plaintext.data; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate output->length = plaintext.length+hashsize; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* begin the encryption, computer K1 */ 1847c478bd9Sstevel@tonic-gate ms_usage=krb5int_arcfour_translate_usage(usage); 1857c478bd9Sstevel@tonic-gate if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 1867c478bd9Sstevel@tonic-gate (void) strncpy(salt.data, l40, salt.length); 1877c478bd9Sstevel@tonic-gate salt.data[10]=ms_usage & 0xff; 1887c478bd9Sstevel@tonic-gate salt.data[11]=(ms_usage >> 8) & 0xff; 1897c478bd9Sstevel@tonic-gate salt.data[12]=(ms_usage >> 16) & 0xff; 1907c478bd9Sstevel@tonic-gate salt.data[13]=(ms_usage >> 24) & 0xff; 1917c478bd9Sstevel@tonic-gate } else { 1927c478bd9Sstevel@tonic-gate salt.length=4; 1937c478bd9Sstevel@tonic-gate salt.data[0]=ms_usage & 0xff; 1947c478bd9Sstevel@tonic-gate salt.data[1]=(ms_usage >> 8) & 0xff; 1957c478bd9Sstevel@tonic-gate salt.data[2]=(ms_usage >> 16) & 0xff; 1967c478bd9Sstevel@tonic-gate salt.data[3]=(ms_usage >> 24) & 0xff; 1977c478bd9Sstevel@tonic-gate } 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate #ifdef _KERNEL 2007c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, key, &salt, &d1); 2017c478bd9Sstevel@tonic-gate #else 2027c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, hash, key, 1, &salt, &d1); 2037c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 2047c478bd9Sstevel@tonic-gate if (ret != 0) 2057c478bd9Sstevel@tonic-gate goto cleanup; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 2087c478bd9Sstevel@tonic-gate bcopy(k1.contents, k2.contents, k2.length); 2097c478bd9Sstevel@tonic-gate (void) memset(k1.contents+7, 0xab, 9); 2107c478bd9Sstevel@tonic-gate kptr = &k2; 2117c478bd9Sstevel@tonic-gate } else { 2127c478bd9Sstevel@tonic-gate kptr = &k1; 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate /* create a confounder block */ 2167c478bd9Sstevel@tonic-gate ret=krb5_c_random_make_octets(context, &confounder); 2177c478bd9Sstevel@tonic-gate bcopy(input->data, plaintext.data+confounder.length, input->length); 2187c478bd9Sstevel@tonic-gate if (ret) 2197c478bd9Sstevel@tonic-gate goto cleanup; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * Compute the HMAC checksum field. 2237c478bd9Sstevel@tonic-gate * checksum = HMAC(k1/k2, plaintext); 2247c478bd9Sstevel@tonic-gate * k2 used when key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate #ifdef _KERNEL 2277c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, kptr, &plaintext, &checksum); 2287c478bd9Sstevel@tonic-gate #else 2297c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &checksum); 2307c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 2317c478bd9Sstevel@tonic-gate if (ret) 2327c478bd9Sstevel@tonic-gate goto cleanup; 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * The final encryption key is the HMAC of the checksum 2367c478bd9Sstevel@tonic-gate * using k1 2377c478bd9Sstevel@tonic-gate * 2387c478bd9Sstevel@tonic-gate * k3 = HMAC(k1, checksum); 2397c478bd9Sstevel@tonic-gate * == or (in other terms) == 2407c478bd9Sstevel@tonic-gate * k3 = HMAC((HMAC(input_key,salt), HMAC(k1, plaintext)); 2417c478bd9Sstevel@tonic-gate */ 2427c478bd9Sstevel@tonic-gate #ifdef _KERNEL 2437c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, &k1, &checksum, &d3); 2447c478bd9Sstevel@tonic-gate #else 2457c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); 2467c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 2477c478bd9Sstevel@tonic-gate if (ret) 2487c478bd9Sstevel@tonic-gate goto cleanup; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate ret = (*(enc->encrypt))(context, &k3, ivec, &plaintext, &ciphertext); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate cleanup: 2537c478bd9Sstevel@tonic-gate bzero(d1.data, d1.length); 2547c478bd9Sstevel@tonic-gate if (d2.data) { 2557c478bd9Sstevel@tonic-gate bzero(d2.data, d2.length); 2567c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate bzero(d3.data, d3.length); 2597c478bd9Sstevel@tonic-gate bzero(salt.data, salt.length); 2607c478bd9Sstevel@tonic-gate bzero(plaintext.data, plaintext.length); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 2637c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 2647c478bd9Sstevel@tonic-gate FREE(salt.data, salt.length); 2657c478bd9Sstevel@tonic-gate FREE(plaintext.data, plaintext.length); 2667c478bd9Sstevel@tonic-gate return (ret); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* This is the arcfour-hmac decryption routine */ 2707c478bd9Sstevel@tonic-gate krb5_error_code 2717c478bd9Sstevel@tonic-gate krb5_arcfour_decrypt(context, enc, hash, key, usage, ivec, input, output) 2727c478bd9Sstevel@tonic-gate krb5_context context; 2737c478bd9Sstevel@tonic-gate const struct krb5_enc_provider *enc; 2747c478bd9Sstevel@tonic-gate const struct krb5_hash_provider *hash; 2757c478bd9Sstevel@tonic-gate const krb5_keyblock *key; 2767c478bd9Sstevel@tonic-gate krb5_keyusage usage; 2777c478bd9Sstevel@tonic-gate const krb5_data *ivec; 2787c478bd9Sstevel@tonic-gate const krb5_data *input; 2797c478bd9Sstevel@tonic-gate krb5_data *output; 2807c478bd9Sstevel@tonic-gate { 2817c478bd9Sstevel@tonic-gate krb5_keyblock k1,k2,k3, *kptr; 2827c478bd9Sstevel@tonic-gate krb5_data d1,d2,d3,salt,ciphertext,plaintext,checksum; 2837c478bd9Sstevel@tonic-gate krb5_keyusage ms_usage; 284*505d05c7Sgtb size_t keybytes, hashsize; 2857c478bd9Sstevel@tonic-gate krb5_error_code ret; 2867c478bd9Sstevel@tonic-gate 287*505d05c7Sgtb keybytes = enc->keybytes; 288*505d05c7Sgtb hashsize = hash->hashsize; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate bzero(&d2, sizeof(krb5_data)); 2917c478bd9Sstevel@tonic-gate bzero(&k2, sizeof(krb5_keyblock)); 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * d1 is the contents buffer for key k1. 2947c478bd9Sstevel@tonic-gate * k1 = HMAC(input_key, salt) 2957c478bd9Sstevel@tonic-gate */ 2967c478bd9Sstevel@tonic-gate d1.length=keybytes; 2977c478bd9Sstevel@tonic-gate d1.data=MALLOC(d1.length); 2987c478bd9Sstevel@tonic-gate if (d1.data == NULL) 2997c478bd9Sstevel@tonic-gate return (ENOMEM); 3007c478bd9Sstevel@tonic-gate (void) bcopy(key, &k1, sizeof (krb5_keyblock)); 3017c478bd9Sstevel@tonic-gate k1.length=d1.length; 3027c478bd9Sstevel@tonic-gate k1.contents= (void *) d1.data; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * d2 is the contents of key 'k2', which is used to generate the 3067c478bd9Sstevel@tonic-gate * checksum field. 'd2' == 'd1' when not using the exportable 3077c478bd9Sstevel@tonic-gate * enctype. This is only needed when using the exportable 3087c478bd9Sstevel@tonic-gate * enctype. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate if (key->enctype==ENCTYPE_ARCFOUR_HMAC_EXP) { 3117c478bd9Sstevel@tonic-gate d2.length=keybytes; 3127c478bd9Sstevel@tonic-gate d2.data=MALLOC(d2.length); 3137c478bd9Sstevel@tonic-gate if (d2.data == NULL) { 3147c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 3157c478bd9Sstevel@tonic-gate return (ENOMEM); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate (void) bcopy(key, &k2, sizeof(krb5_keyblock)); 3187c478bd9Sstevel@tonic-gate k2.length=d2.length; 3197c478bd9Sstevel@tonic-gate k2.contents= (void *) d2.data; 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * d3 will hold the contents of the final key used for the 3247c478bd9Sstevel@tonic-gate * encryption step. 'k3' is the key structure that has 'd3' 3257c478bd9Sstevel@tonic-gate * as its 'contents' field. 3267c478bd9Sstevel@tonic-gate * k3 = HMAC(k1, checksum) 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate d3.length=keybytes; 3297c478bd9Sstevel@tonic-gate d3.data=MALLOC(d3.length); 3307c478bd9Sstevel@tonic-gate if (d3.data == NULL) { 3317c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 3327c478bd9Sstevel@tonic-gate if (d2.data) 3337c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 3347c478bd9Sstevel@tonic-gate return (ENOMEM); 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate bcopy(key, &k3, sizeof(krb5_keyblock)); 3377c478bd9Sstevel@tonic-gate k3.length=d3.length; 3387c478bd9Sstevel@tonic-gate k3.contents= (void *) d3.data; 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate salt.length=14; 3417c478bd9Sstevel@tonic-gate salt.data=MALLOC(salt.length); 3427c478bd9Sstevel@tonic-gate if(salt.data==NULL) { 3437c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 3447c478bd9Sstevel@tonic-gate if (d2.data) 3457c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 3467c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 3477c478bd9Sstevel@tonic-gate return (ENOMEM); 3487c478bd9Sstevel@tonic-gate } 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate ciphertext.length=input->length-hashsize; 3517c478bd9Sstevel@tonic-gate ciphertext.data=input->data+hashsize; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate plaintext.length=ciphertext.length; 3547c478bd9Sstevel@tonic-gate plaintext.data=MALLOC(plaintext.length); 3557c478bd9Sstevel@tonic-gate if (plaintext.data == NULL) { 3567c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 3577c478bd9Sstevel@tonic-gate if (d2.data) 3587c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 3597c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 3607c478bd9Sstevel@tonic-gate FREE(salt.data, salt.length); 3617c478bd9Sstevel@tonic-gate return (ENOMEM); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate checksum.length=hashsize; 3657c478bd9Sstevel@tonic-gate checksum.data=input->data; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate /* compute the salt */ 3687c478bd9Sstevel@tonic-gate ms_usage=krb5int_arcfour_translate_usage(usage); 3697c478bd9Sstevel@tonic-gate if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 3707c478bd9Sstevel@tonic-gate (void) strncpy(salt.data, l40, salt.length); 3717c478bd9Sstevel@tonic-gate salt.data[10]=ms_usage & 0xff; 3727c478bd9Sstevel@tonic-gate salt.data[11]=(ms_usage>>8) & 0xff; 3737c478bd9Sstevel@tonic-gate salt.data[12]=(ms_usage>>16) & 0xff; 3747c478bd9Sstevel@tonic-gate salt.data[13]=(ms_usage>>24) & 0xff; 3757c478bd9Sstevel@tonic-gate } else { 3767c478bd9Sstevel@tonic-gate salt.length=4; 3777c478bd9Sstevel@tonic-gate salt.data[0]=ms_usage & 0xff; 3787c478bd9Sstevel@tonic-gate salt.data[1]=(ms_usage>>8) & 0xff; 3797c478bd9Sstevel@tonic-gate salt.data[2]=(ms_usage>>16) & 0xff; 3807c478bd9Sstevel@tonic-gate salt.data[3]=(ms_usage>>24) & 0xff; 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate #ifdef _KERNEL 3847c478bd9Sstevel@tonic-gate ret=krb5_hmac(context, key, &salt, &d1); 3857c478bd9Sstevel@tonic-gate #else 3867c478bd9Sstevel@tonic-gate ret=krb5_hmac(context, hash, key, 1, &salt, &d1); 3877c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 3887c478bd9Sstevel@tonic-gate if (ret) 3897c478bd9Sstevel@tonic-gate goto cleanup; 3907c478bd9Sstevel@tonic-gate 3917c478bd9Sstevel@tonic-gate if (key->enctype == ENCTYPE_ARCFOUR_HMAC_EXP) { 3927c478bd9Sstevel@tonic-gate bcopy(k1.contents, k2.contents, d1.length); 3937c478bd9Sstevel@tonic-gate (void) memset(k1.contents+7, 0xab, 9); 3947c478bd9Sstevel@tonic-gate kptr = &k2; 3957c478bd9Sstevel@tonic-gate } else { 3967c478bd9Sstevel@tonic-gate kptr = &k1; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate #ifdef _KERNEL 4007c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, &k1, &checksum, &d3); 4017c478bd9Sstevel@tonic-gate #else 4027c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, hash, &k1, 1, &checksum, &d3); 4037c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate if (ret) 4067c478bd9Sstevel@tonic-gate goto cleanup; 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate ret=(*(enc->decrypt))(context, &k3, ivec, &ciphertext, &plaintext); 4097c478bd9Sstevel@tonic-gate if (ret) 4107c478bd9Sstevel@tonic-gate goto cleanup; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate #ifdef _KERNEL 4137c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, kptr, &plaintext, &d1); 4147c478bd9Sstevel@tonic-gate #else 4157c478bd9Sstevel@tonic-gate ret = krb5_hmac(context, hash, kptr, 1, &plaintext, &d1); 4167c478bd9Sstevel@tonic-gate #endif /* _KERNEL */ 4177c478bd9Sstevel@tonic-gate 4187c478bd9Sstevel@tonic-gate if (ret) 4197c478bd9Sstevel@tonic-gate goto cleanup; 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (bcmp(checksum.data, d1.data, hashsize) != 0) { 4227c478bd9Sstevel@tonic-gate ret=KRB5KRB_AP_ERR_BAD_INTEGRITY; 4237c478bd9Sstevel@tonic-gate goto cleanup; 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate bcopy(plaintext.data+CONFOUNDERLENGTH, output->data, 4277c478bd9Sstevel@tonic-gate (plaintext.length-CONFOUNDERLENGTH)); 4287c478bd9Sstevel@tonic-gate output->length=plaintext.length-CONFOUNDERLENGTH; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate cleanup: 4317c478bd9Sstevel@tonic-gate bzero(d1.data, d1.length); 4327c478bd9Sstevel@tonic-gate if (d2.data) { 4337c478bd9Sstevel@tonic-gate bzero(d2.data, d2.length); 4347c478bd9Sstevel@tonic-gate FREE(d2.data, d2.length); 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate bzero(d3.data, d2.length); 4377c478bd9Sstevel@tonic-gate bzero(salt.data, salt.length); 4387c478bd9Sstevel@tonic-gate bzero(plaintext.data, plaintext.length); 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate FREE(d1.data, d1.length); 4417c478bd9Sstevel@tonic-gate FREE(d3.data, d3.length); 4427c478bd9Sstevel@tonic-gate FREE(salt.data, salt.length); 4437c478bd9Sstevel@tonic-gate FREE(plaintext.data, plaintext.length); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate return (ret); 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 448