1226031Sstas/* 2226031Sstas * Copyright (c) 1997 - 2008 Kungliga Tekniska H��gskolan 3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4226031Sstas * All rights reserved. 5226031Sstas * 6226031Sstas * Redistribution and use in source and binary forms, with or without 7226031Sstas * modification, are permitted provided that the following conditions 8226031Sstas * are met: 9226031Sstas * 10226031Sstas * 1. Redistributions of source code must retain the above copyright 11226031Sstas * notice, this list of conditions and the following disclaimer. 12226031Sstas * 13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 14226031Sstas * notice, this list of conditions and the following disclaimer in the 15226031Sstas * documentation and/or other materials provided with the distribution. 16226031Sstas * 17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors 18226031Sstas * may be used to endorse or promote products derived from this software 19226031Sstas * without specific prior written permission. 20226031Sstas * 21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31226031Sstas * SUCH DAMAGE. 32226031Sstas */ 33226031Sstas 34226031Sstas/* 35226031Sstas * ARCFOUR 36226031Sstas */ 37226031Sstas 38226031Sstas#include "krb5_locl.h" 39226031Sstas 40226031Sstasstatic struct _krb5_key_type keytype_arcfour = { 41226031Sstas ENCTYPE_ARCFOUR_HMAC_MD5, 42226031Sstas "arcfour", 43226031Sstas 128, 44226031Sstas 16, 45226031Sstas sizeof(struct _krb5_evp_schedule), 46226031Sstas NULL, 47226031Sstas _krb5_evp_schedule, 48226031Sstas _krb5_arcfour_salt, 49226031Sstas NULL, 50226031Sstas _krb5_evp_cleanup, 51226031Sstas EVP_rc4 52226031Sstas}; 53226031Sstas 54226031Sstas/* 55226031Sstas * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt 56226031Sstas */ 57226031Sstas 58226031Sstaskrb5_error_code 59226031Sstas_krb5_HMAC_MD5_checksum(krb5_context context, 60226031Sstas struct _krb5_key_data *key, 61226031Sstas const void *data, 62226031Sstas size_t len, 63226031Sstas unsigned usage, 64226031Sstas Checksum *result) 65226031Sstas{ 66226031Sstas EVP_MD_CTX *m; 67226031Sstas struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 68226031Sstas const char signature[] = "signaturekey"; 69226031Sstas Checksum ksign_c; 70226031Sstas struct _krb5_key_data ksign; 71226031Sstas krb5_keyblock kb; 72226031Sstas unsigned char t[4]; 73226031Sstas unsigned char tmp[16]; 74226031Sstas unsigned char ksign_c_data[16]; 75226031Sstas krb5_error_code ret; 76226031Sstas 77226031Sstas m = EVP_MD_CTX_create(); 78226031Sstas if (m == NULL) { 79226031Sstas krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); 80226031Sstas return ENOMEM; 81226031Sstas } 82226031Sstas ksign_c.checksum.length = sizeof(ksign_c_data); 83226031Sstas ksign_c.checksum.data = ksign_c_data; 84226031Sstas ret = _krb5_internal_hmac(context, c, signature, sizeof(signature), 85226031Sstas 0, key, &ksign_c); 86226031Sstas if (ret) { 87226031Sstas EVP_MD_CTX_destroy(m); 88226031Sstas return ret; 89226031Sstas } 90226031Sstas ksign.key = &kb; 91226031Sstas kb.keyvalue = ksign_c.checksum; 92226031Sstas EVP_DigestInit_ex(m, EVP_md5(), NULL); 93226031Sstas t[0] = (usage >> 0) & 0xFF; 94226031Sstas t[1] = (usage >> 8) & 0xFF; 95226031Sstas t[2] = (usage >> 16) & 0xFF; 96226031Sstas t[3] = (usage >> 24) & 0xFF; 97226031Sstas EVP_DigestUpdate(m, t, 4); 98226031Sstas EVP_DigestUpdate(m, data, len); 99226031Sstas EVP_DigestFinal_ex (m, tmp, NULL); 100226031Sstas EVP_MD_CTX_destroy(m); 101226031Sstas 102226031Sstas ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); 103226031Sstas if (ret) 104226031Sstas return ret; 105226031Sstas return 0; 106226031Sstas} 107226031Sstas 108226031Sstasstruct _krb5_checksum_type _krb5_checksum_hmac_md5 = { 109226031Sstas CKSUMTYPE_HMAC_MD5, 110226031Sstas "hmac-md5", 111226031Sstas 64, 112226031Sstas 16, 113226031Sstas F_KEYED | F_CPROOF, 114226031Sstas _krb5_HMAC_MD5_checksum, 115226031Sstas NULL 116226031Sstas}; 117226031Sstas 118226031Sstas/* 119226031Sstas * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 120226031Sstas * 121226031Sstas * warning: not for small children 122226031Sstas */ 123226031Sstas 124226031Sstasstatic krb5_error_code 125226031SstasARCFOUR_subencrypt(krb5_context context, 126226031Sstas struct _krb5_key_data *key, 127226031Sstas void *data, 128226031Sstas size_t len, 129226031Sstas unsigned usage, 130226031Sstas void *ivec) 131226031Sstas{ 132226031Sstas EVP_CIPHER_CTX ctx; 133226031Sstas struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 134226031Sstas Checksum k1_c, k2_c, k3_c, cksum; 135226031Sstas struct _krb5_key_data ke; 136226031Sstas krb5_keyblock kb; 137226031Sstas unsigned char t[4]; 138226031Sstas unsigned char *cdata = data; 139226031Sstas unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 140226031Sstas krb5_error_code ret; 141226031Sstas 142226031Sstas t[0] = (usage >> 0) & 0xFF; 143226031Sstas t[1] = (usage >> 8) & 0xFF; 144226031Sstas t[2] = (usage >> 16) & 0xFF; 145226031Sstas t[3] = (usage >> 24) & 0xFF; 146226031Sstas 147226031Sstas k1_c.checksum.length = sizeof(k1_c_data); 148226031Sstas k1_c.checksum.data = k1_c_data; 149226031Sstas 150226031Sstas ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 151226031Sstas if (ret) 152226031Sstas krb5_abortx(context, "hmac failed"); 153226031Sstas 154226031Sstas memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 155226031Sstas 156226031Sstas k2_c.checksum.length = sizeof(k2_c_data); 157226031Sstas k2_c.checksum.data = k2_c_data; 158226031Sstas 159226031Sstas ke.key = &kb; 160226031Sstas kb.keyvalue = k2_c.checksum; 161226031Sstas 162226031Sstas cksum.checksum.length = 16; 163226031Sstas cksum.checksum.data = data; 164226031Sstas 165226031Sstas ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 166226031Sstas if (ret) 167226031Sstas krb5_abortx(context, "hmac failed"); 168226031Sstas 169226031Sstas ke.key = &kb; 170226031Sstas kb.keyvalue = k1_c.checksum; 171226031Sstas 172226031Sstas k3_c.checksum.length = sizeof(k3_c_data); 173226031Sstas k3_c.checksum.data = k3_c_data; 174226031Sstas 175226031Sstas ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c); 176226031Sstas if (ret) 177226031Sstas krb5_abortx(context, "hmac failed"); 178226031Sstas 179226031Sstas EVP_CIPHER_CTX_init(&ctx); 180226031Sstas 181226031Sstas EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1); 182226031Sstas EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); 183226031Sstas EVP_CIPHER_CTX_cleanup(&ctx); 184226031Sstas 185226031Sstas memset (k1_c_data, 0, sizeof(k1_c_data)); 186226031Sstas memset (k2_c_data, 0, sizeof(k2_c_data)); 187226031Sstas memset (k3_c_data, 0, sizeof(k3_c_data)); 188226031Sstas return 0; 189226031Sstas} 190226031Sstas 191226031Sstasstatic krb5_error_code 192226031SstasARCFOUR_subdecrypt(krb5_context context, 193226031Sstas struct _krb5_key_data *key, 194226031Sstas void *data, 195226031Sstas size_t len, 196226031Sstas unsigned usage, 197226031Sstas void *ivec) 198226031Sstas{ 199226031Sstas EVP_CIPHER_CTX ctx; 200226031Sstas struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); 201226031Sstas Checksum k1_c, k2_c, k3_c, cksum; 202226031Sstas struct _krb5_key_data ke; 203226031Sstas krb5_keyblock kb; 204226031Sstas unsigned char t[4]; 205226031Sstas unsigned char *cdata = data; 206226031Sstas unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; 207226031Sstas unsigned char cksum_data[16]; 208226031Sstas krb5_error_code ret; 209226031Sstas 210226031Sstas t[0] = (usage >> 0) & 0xFF; 211226031Sstas t[1] = (usage >> 8) & 0xFF; 212226031Sstas t[2] = (usage >> 16) & 0xFF; 213226031Sstas t[3] = (usage >> 24) & 0xFF; 214226031Sstas 215226031Sstas k1_c.checksum.length = sizeof(k1_c_data); 216226031Sstas k1_c.checksum.data = k1_c_data; 217226031Sstas 218226031Sstas ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); 219226031Sstas if (ret) 220226031Sstas krb5_abortx(context, "hmac failed"); 221226031Sstas 222226031Sstas memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); 223226031Sstas 224226031Sstas k2_c.checksum.length = sizeof(k2_c_data); 225226031Sstas k2_c.checksum.data = k2_c_data; 226226031Sstas 227226031Sstas ke.key = &kb; 228226031Sstas kb.keyvalue = k1_c.checksum; 229226031Sstas 230226031Sstas k3_c.checksum.length = sizeof(k3_c_data); 231226031Sstas k3_c.checksum.data = k3_c_data; 232226031Sstas 233226031Sstas ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); 234226031Sstas if (ret) 235226031Sstas krb5_abortx(context, "hmac failed"); 236226031Sstas 237226031Sstas EVP_CIPHER_CTX_init(&ctx); 238226031Sstas EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0); 239226031Sstas EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); 240226031Sstas EVP_CIPHER_CTX_cleanup(&ctx); 241226031Sstas 242226031Sstas ke.key = &kb; 243226031Sstas kb.keyvalue = k2_c.checksum; 244226031Sstas 245226031Sstas cksum.checksum.length = 16; 246226031Sstas cksum.checksum.data = cksum_data; 247226031Sstas 248226031Sstas ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); 249226031Sstas if (ret) 250226031Sstas krb5_abortx(context, "hmac failed"); 251226031Sstas 252226031Sstas memset (k1_c_data, 0, sizeof(k1_c_data)); 253226031Sstas memset (k2_c_data, 0, sizeof(k2_c_data)); 254226031Sstas memset (k3_c_data, 0, sizeof(k3_c_data)); 255226031Sstas 256226031Sstas if (ct_memcmp (cksum.checksum.data, data, 16) != 0) { 257226031Sstas krb5_clear_error_message (context); 258226031Sstas return KRB5KRB_AP_ERR_BAD_INTEGRITY; 259226031Sstas } else { 260226031Sstas return 0; 261226031Sstas } 262226031Sstas} 263226031Sstas 264226031Sstas/* 265226031Sstas * convert the usage numbers used in 266226031Sstas * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in 267226031Sstas * draft-brezak-win2k-krb-rc4-hmac-04.txt 268226031Sstas */ 269226031Sstas 270226031Sstaskrb5_error_code 271226031Sstas_krb5_usage2arcfour(krb5_context context, unsigned *usage) 272226031Sstas{ 273226031Sstas switch (*usage) { 274226031Sstas case KRB5_KU_AS_REP_ENC_PART : /* 3 */ 275226031Sstas *usage = 8; 276226031Sstas return 0; 277226031Sstas case KRB5_KU_USAGE_SEAL : /* 22 */ 278226031Sstas *usage = 13; 279226031Sstas return 0; 280226031Sstas case KRB5_KU_USAGE_SIGN : /* 23 */ 281226031Sstas *usage = 15; 282226031Sstas return 0; 283226031Sstas case KRB5_KU_USAGE_SEQ: /* 24 */ 284226031Sstas *usage = 0; 285226031Sstas return 0; 286226031Sstas default : 287226031Sstas return 0; 288226031Sstas } 289226031Sstas} 290226031Sstas 291226031Sstasstatic krb5_error_code 292226031SstasARCFOUR_encrypt(krb5_context context, 293226031Sstas struct _krb5_key_data *key, 294226031Sstas void *data, 295226031Sstas size_t len, 296226031Sstas krb5_boolean encryptp, 297226031Sstas int usage, 298226031Sstas void *ivec) 299226031Sstas{ 300226031Sstas krb5_error_code ret; 301226031Sstas unsigned keyusage = usage; 302226031Sstas 303226031Sstas if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0) 304226031Sstas return ret; 305226031Sstas 306226031Sstas if (encryptp) 307226031Sstas return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); 308226031Sstas else 309226031Sstas return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); 310226031Sstas} 311226031Sstas 312226031Sstasstruct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = { 313226031Sstas ETYPE_ARCFOUR_HMAC_MD5, 314226031Sstas "arcfour-hmac-md5", 315226031Sstas 1, 316226031Sstas 1, 317226031Sstas 8, 318226031Sstas &keytype_arcfour, 319226031Sstas &_krb5_checksum_hmac_md5, 320234027Sstas &_krb5_checksum_hmac_md5, 321226031Sstas F_SPECIAL, 322226031Sstas ARCFOUR_encrypt, 323226031Sstas 0, 324226031Sstas NULL 325226031Sstas}; 326