Path: blob/main/crypto/heimdal/lib/krb5/crypto-arcfour.c
34878 views
/*1* Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233/*34* ARCFOUR35*/3637#include "krb5_locl.h"3839static struct _krb5_key_type keytype_arcfour = {40ENCTYPE_ARCFOUR_HMAC_MD5,41"arcfour",42128,4316,44sizeof(struct _krb5_evp_schedule),45NULL,46_krb5_evp_schedule,47_krb5_arcfour_salt,48NULL,49_krb5_evp_cleanup,50EVP_rc451};5253/*54* checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt55*/5657krb5_error_code58_krb5_HMAC_MD5_checksum(krb5_context context,59struct _krb5_key_data *key,60const void *data,61size_t len,62unsigned usage,63Checksum *result)64{65EVP_MD_CTX *m;66struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);67const char signature[] = "signaturekey";68Checksum ksign_c;69struct _krb5_key_data ksign;70krb5_keyblock kb;71unsigned char t[4];72unsigned char tmp[16];73unsigned char ksign_c_data[16];74krb5_error_code ret;7576m = EVP_MD_CTX_create();77if (m == NULL) {78krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));79return ENOMEM;80}81ksign_c.checksum.length = sizeof(ksign_c_data);82ksign_c.checksum.data = ksign_c_data;83ret = _krb5_internal_hmac(context, c, signature, sizeof(signature),840, key, &ksign_c);85if (ret) {86EVP_MD_CTX_destroy(m);87return ret;88}89ksign.key = &kb;90kb.keyvalue = ksign_c.checksum;91EVP_DigestInit_ex(m, EVP_md5(), NULL);92t[0] = (usage >> 0) & 0xFF;93t[1] = (usage >> 8) & 0xFF;94t[2] = (usage >> 16) & 0xFF;95t[3] = (usage >> 24) & 0xFF;96EVP_DigestUpdate(m, t, 4);97EVP_DigestUpdate(m, data, len);98EVP_DigestFinal_ex (m, tmp, NULL);99EVP_MD_CTX_destroy(m);100101ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);102if (ret)103return ret;104return 0;105}106107struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {108CKSUMTYPE_HMAC_MD5,109"hmac-md5",11064,11116,112F_KEYED | F_CPROOF,113_krb5_HMAC_MD5_checksum,114NULL115};116117/*118* section 6 of draft-brezak-win2k-krb-rc4-hmac-03119*120* warning: not for small children121*/122123static krb5_error_code124ARCFOUR_subencrypt(krb5_context context,125struct _krb5_key_data *key,126void *data,127size_t len,128unsigned usage,129void *ivec)130{131EVP_CIPHER_CTX *ctx;132struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);133Checksum k1_c, k2_c, k3_c, cksum;134struct _krb5_key_data ke;135krb5_keyblock kb;136unsigned char t[4];137unsigned char *cdata = data;138unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];139krb5_error_code ret;140141t[0] = (usage >> 0) & 0xFF;142t[1] = (usage >> 8) & 0xFF;143t[2] = (usage >> 16) & 0xFF;144t[3] = (usage >> 24) & 0xFF;145146k1_c.checksum.length = sizeof(k1_c_data);147k1_c.checksum.data = k1_c_data;148149ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);150if (ret)151krb5_abortx(context, "hmac failed");152153memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));154155k2_c.checksum.length = sizeof(k2_c_data);156k2_c.checksum.data = k2_c_data;157158ke.key = &kb;159kb.keyvalue = k2_c.checksum;160161cksum.checksum.length = 16;162cksum.checksum.data = data;163164ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);165if (ret)166krb5_abortx(context, "hmac failed");167168ke.key = &kb;169kb.keyvalue = k1_c.checksum;170171k3_c.checksum.length = sizeof(k3_c_data);172k3_c.checksum.data = k3_c_data;173174ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c);175if (ret)176krb5_abortx(context, "hmac failed");177178ctx = EVP_CIPHER_CTX_new();179if (ctx == NULL)180krb5_abortx(context, "malloc failed");181182EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);183EVP_Cipher(ctx, cdata + 16, cdata + 16, len - 16);184EVP_CIPHER_CTX_free(ctx);185186memset (k1_c_data, 0, sizeof(k1_c_data));187memset (k2_c_data, 0, sizeof(k2_c_data));188memset (k3_c_data, 0, sizeof(k3_c_data));189return 0;190}191192static krb5_error_code193ARCFOUR_subdecrypt(krb5_context context,194struct _krb5_key_data *key,195void *data,196size_t len,197unsigned usage,198void *ivec)199{200EVP_CIPHER_CTX *ctx;201struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);202Checksum k1_c, k2_c, k3_c, cksum;203struct _krb5_key_data ke;204krb5_keyblock kb;205unsigned char t[4];206unsigned char *cdata = data;207unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];208unsigned char cksum_data[16];209krb5_error_code ret;210211t[0] = (usage >> 0) & 0xFF;212t[1] = (usage >> 8) & 0xFF;213t[2] = (usage >> 16) & 0xFF;214t[3] = (usage >> 24) & 0xFF;215216k1_c.checksum.length = sizeof(k1_c_data);217k1_c.checksum.data = k1_c_data;218219ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);220if (ret)221krb5_abortx(context, "hmac failed");222223memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));224225k2_c.checksum.length = sizeof(k2_c_data);226k2_c.checksum.data = k2_c_data;227228ke.key = &kb;229kb.keyvalue = k1_c.checksum;230231k3_c.checksum.length = sizeof(k3_c_data);232k3_c.checksum.data = k3_c_data;233234ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);235if (ret)236krb5_abortx(context, "hmac failed");237238ctx = EVP_CIPHER_CTX_new();239if (ctx == NULL)240krb5_abortx(context, "malloc failed");241EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);242EVP_Cipher(ctx, cdata + 16, cdata + 16, len - 16);243EVP_CIPHER_CTX_free(ctx);244245ke.key = &kb;246kb.keyvalue = k2_c.checksum;247248cksum.checksum.length = 16;249cksum.checksum.data = cksum_data;250251ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);252if (ret)253krb5_abortx(context, "hmac failed");254255memset (k1_c_data, 0, sizeof(k1_c_data));256memset (k2_c_data, 0, sizeof(k2_c_data));257memset (k3_c_data, 0, sizeof(k3_c_data));258259if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {260krb5_clear_error_message (context);261return KRB5KRB_AP_ERR_BAD_INTEGRITY;262} else {263return 0;264}265}266267/*268* convert the usage numbers used in269* draft-ietf-cat-kerb-key-derivation-00.txt to the ones in270* draft-brezak-win2k-krb-rc4-hmac-04.txt271*/272273krb5_error_code274_krb5_usage2arcfour(krb5_context context, unsigned *usage)275{276switch (*usage) {277case KRB5_KU_AS_REP_ENC_PART : /* 3 */278*usage = 8;279return 0;280case KRB5_KU_USAGE_SEAL : /* 22 */281*usage = 13;282return 0;283case KRB5_KU_USAGE_SIGN : /* 23 */284*usage = 15;285return 0;286case KRB5_KU_USAGE_SEQ: /* 24 */287*usage = 0;288return 0;289default :290return 0;291}292}293294static krb5_error_code295ARCFOUR_encrypt(krb5_context context,296struct _krb5_key_data *key,297void *data,298size_t len,299krb5_boolean encryptp,300int usage,301void *ivec)302{303krb5_error_code ret;304unsigned keyusage = usage;305306if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)307return ret;308309if (encryptp)310return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);311else312return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);313}314315struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {316ETYPE_ARCFOUR_HMAC_MD5,317"arcfour-hmac-md5",3181,3191,3208,321&keytype_arcfour,322&_krb5_checksum_hmac_md5,323&_krb5_checksum_hmac_md5,324F_SPECIAL,325ARCFOUR_encrypt,3260,327NULL328};329330331