From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- third_party/heimdal/lib/krb5/crypto-arcfour.c | 368 ++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 third_party/heimdal/lib/krb5/crypto-arcfour.c (limited to 'third_party/heimdal/lib/krb5/crypto-arcfour.c') diff --git a/third_party/heimdal/lib/krb5/crypto-arcfour.c b/third_party/heimdal/lib/krb5/crypto-arcfour.c new file mode 100644 index 0000000..28fc52e --- /dev/null +++ b/third_party/heimdal/lib/krb5/crypto-arcfour.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * ARCFOUR + */ + +#include "krb5_locl.h" + +static struct _krb5_key_type keytype_arcfour = { + KRB5_ENCTYPE_ARCFOUR_HMAC_MD5, + "arcfour", + 128, + 16, + sizeof(struct _krb5_evp_schedule), + NULL, + _krb5_evp_schedule, + _krb5_arcfour_salt, + NULL, + _krb5_evp_cleanup, + EVP_rc4 +}; + +/* + * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt + */ + +krb5_error_code +_krb5_HMAC_MD5_checksum(krb5_context context, + krb5_crypto crypto, + struct _krb5_key_data *key, + unsigned usage, + const struct krb5_crypto_iov *iov, + int niov, + Checksum *result) +{ + EVP_MD_CTX *m; + struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); + const char signature[] = "signaturekey"; + Checksum ksign_c; + struct _krb5_key_data ksign; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char tmp[16]; + unsigned char ksign_c_data[16]; + krb5_error_code ret; + int i; + + if (crypto != NULL) { + if (crypto->mdctx == NULL) + crypto->mdctx = EVP_MD_CTX_create(); + if (crypto->mdctx == NULL) + return krb5_enomem(context); + m = crypto->mdctx; + } else + m = EVP_MD_CTX_create(); + + ksign_c.checksum.length = sizeof(ksign_c_data); + ksign_c.checksum.data = ksign_c_data; + ret = _krb5_internal_hmac(context, crypto, c, signature, sizeof(signature), + 0, key, &ksign_c); + if (ret) + goto out; + + ksign.key = &kb; + kb.keyvalue = ksign_c.checksum; + EVP_DigestInit_ex(m, EVP_md5(), NULL); + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + EVP_DigestUpdate(m, t, 4); + for (i = 0; i < niov; i++) { + if (_krb5_crypto_iov_should_sign(&iov[i])) + EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length); + } + EVP_DigestFinal_ex (m, tmp, NULL); + + ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result); +out: + if (crypto == NULL) + EVP_MD_CTX_destroy(m); + + return ret; +} + +struct _krb5_checksum_type _krb5_checksum_hmac_md5 = { + CKSUMTYPE_HMAC_MD5, + "hmac-md5", + 64, + 16, + F_KEYED | F_CPROOF, + _krb5_HMAC_MD5_checksum, + NULL +}; + +/* + * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 + * + * warning: not for small children + */ + +static krb5_error_code +ARCFOUR_subencrypt(krb5_context context, + struct _krb5_key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + EVP_CIPHER_CTX ctx; + struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct _krb5_key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + krb5_error_code ret; + + if (len < 16) { + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = data; + + ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = _krb5_internal_hmac(context, NULL, c, data, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + EVP_CIPHER_CTX_init(&ctx); + + EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1); + EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); + EVP_CIPHER_CTX_cleanup(&ctx); + + memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data)); + memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data)); + memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data)); + return 0; +} + +static krb5_error_code +ARCFOUR_subdecrypt(krb5_context context, + struct _krb5_key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + EVP_CIPHER_CTX ctx; + struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct _krb5_key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + unsigned char cksum_data[16]; + krb5_error_code ret; + + if (len < 16) { + return KRB5KRB_AP_ERR_INAPP_CKSUM; + } + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = _krb5_internal_hmac(context, NULL, c, cdata, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + EVP_CIPHER_CTX_init(&ctx); + EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0); + EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16); + EVP_CIPHER_CTX_cleanup(&ctx); + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = cksum_data; + + ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data)); + memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data)); + memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data)); + + if (ct_memcmp (cksum.checksum.data, data, 16) != 0) { + krb5_clear_error_message (context); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else { + return 0; + } +} + +/* + * convert the usage numbers used in + * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in + * draft-brezak-win2k-krb-rc4-hmac-04.txt + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +_krb5_usage2arcfour(krb5_context context, unsigned *usage) +{ + switch (*usage) { + case KRB5_KU_AS_REP_ENC_PART : /* 3 */ + *usage = 8; + return 0; + case KRB5_KU_USAGE_SEAL : /* 22 */ + *usage = 13; + return 0; + case KRB5_KU_USAGE_SIGN : /* 23 */ + *usage = 15; + return 0; + case KRB5_KU_USAGE_SEQ: /* 24 */ + *usage = 0; + return 0; + default : + return 0; + } +} + +static krb5_error_code +ARCFOUR_encrypt(krb5_context context, + struct _krb5_key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + krb5_error_code ret; + unsigned keyusage = usage; + + if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0) + return ret; + + if (encryptp) + return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); + else + return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); +} + +static krb5_error_code +ARCFOUR_prf(krb5_context context, + krb5_crypto crypto, + const krb5_data *in, + krb5_data *out) +{ + struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1); + krb5_error_code ret; + Checksum res; + + ret = krb5_data_alloc(out, c->checksumsize); + if (ret) + return ret; + + res.checksum.data = out->data; + res.checksum.length = out->length; + + ret = _krb5_internal_hmac(context, crypto, c, in->data, in->length, 0, &crypto->key, &res); + if (ret) + krb5_data_free(out); + return 0; +} + + +struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = { + ETYPE_ARCFOUR_HMAC_MD5, + "arcfour-hmac-md5", + "rc4-hmac", + 1, + 1, + 8, + &keytype_arcfour, + &_krb5_checksum_hmac_md5, + &_krb5_checksum_hmac_md5, + F_SPECIAL | F_WEAK | F_OLD, + ARCFOUR_encrypt, + NULL, + 0, + ARCFOUR_prf +}; -- cgit v1.2.3