1184588Sdfr/*- 2184588Sdfr * Copyright (c) 2008 Isilon Inc http://www.isilon.com/ 3184588Sdfr * Authors: Doug Rabson <dfr@rabson.org> 4184588Sdfr * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org> 5184588Sdfr * 6184588Sdfr * Redistribution and use in source and binary forms, with or without 7184588Sdfr * modification, are permitted provided that the following conditions 8184588Sdfr * are met: 9184588Sdfr * 1. Redistributions of source code must retain the above copyright 10184588Sdfr * notice, this list of conditions and the following disclaimer. 11184588Sdfr * 2. Redistributions in binary form must reproduce the above copyright 12184588Sdfr * notice, this list of conditions and the following disclaimer in the 13184588Sdfr * documentation and/or other materials provided with the distribution. 14184588Sdfr * 15184588Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16184588Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17184588Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18184588Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19184588Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20184588Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21184588Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22184588Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23184588Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24184588Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25184588Sdfr * SUCH DAMAGE. 26184588Sdfr */ 27184588Sdfr 28184588Sdfr#include <sys/cdefs.h> 29184588Sdfr__FBSDID("$FreeBSD$"); 30184588Sdfr 31184588Sdfr#include <sys/param.h> 32184588Sdfr#include <sys/lock.h> 33184588Sdfr#include <sys/malloc.h> 34184588Sdfr#include <sys/md5.h> 35184588Sdfr#include <sys/kobj.h> 36184588Sdfr#include <sys/mbuf.h> 37184588Sdfr#include <crypto/rc4/rc4.h> 38184588Sdfr 39184588Sdfr#include <kgssapi/gssapi.h> 40184588Sdfr#include <kgssapi/gssapi_impl.h> 41184588Sdfr 42184588Sdfr#include "kcrypto.h" 43184588Sdfr 44184588Sdfrstatic void 45184588Sdfrarcfour_init(struct krb5_key_state *ks) 46184588Sdfr{ 47184588Sdfr 48184588Sdfr ks->ks_priv = NULL; 49184588Sdfr} 50184588Sdfr 51184588Sdfrstatic void 52184588Sdfrarcfour_destroy(struct krb5_key_state *ks) 53184588Sdfr{ 54184588Sdfr 55184588Sdfr} 56184588Sdfr 57184588Sdfrstatic void 58184588Sdfrarcfour_set_key(struct krb5_key_state *ks, const void *in) 59184588Sdfr{ 60184588Sdfr void *kp = ks->ks_key; 61184588Sdfr 62184588Sdfr if (kp != in) 63184588Sdfr bcopy(in, kp, 16); 64184588Sdfr} 65184588Sdfr 66184588Sdfrstatic void 67184588Sdfrarcfour_random_to_key(struct krb5_key_state *ks, const void *in) 68184588Sdfr{ 69184588Sdfr 70184588Sdfr arcfour_set_key(ks, in); 71184588Sdfr} 72184588Sdfr 73184588Sdfrstatic void 74184588Sdfrarcfour_hmac(uint8_t *key, uint8_t *data, size_t datalen, 75184588Sdfr uint8_t *result) 76184588Sdfr{ 77184588Sdfr uint8_t buf[64]; 78184588Sdfr MD5_CTX md5; 79184588Sdfr int i; 80184588Sdfr 81184588Sdfr for (i = 0; i < 16; i++) 82184588Sdfr buf[i] = key[i] ^ 0x36; 83184588Sdfr for (; i < 64; i++) 84184588Sdfr buf[i] = 0x36; 85184588Sdfr 86184588Sdfr MD5Init(&md5); 87184588Sdfr MD5Update(&md5, buf, 64); 88184588Sdfr MD5Update(&md5, data, datalen); 89184588Sdfr MD5Final(result, &md5); 90184588Sdfr 91184588Sdfr for (i = 0; i < 16; i++) 92184588Sdfr buf[i] = key[i] ^ 0x5c; 93184588Sdfr for (; i < 64; i++) 94184588Sdfr buf[i] = 0x5c; 95184588Sdfr 96184588Sdfr MD5Init(&md5); 97184588Sdfr MD5Update(&md5, buf, 64); 98184588Sdfr MD5Update(&md5, result, 16); 99184588Sdfr MD5Final(result, &md5); 100184588Sdfr} 101184588Sdfr 102184588Sdfrstatic void 103184588Sdfrarcfour_derive_key(const struct krb5_key_state *ks, uint32_t usage, 104184588Sdfr uint8_t *newkey) 105184588Sdfr{ 106184588Sdfr uint8_t t[4]; 107184588Sdfr 108184588Sdfr t[0] = (usage >> 24); 109184588Sdfr t[1] = (usage >> 16); 110184588Sdfr t[2] = (usage >> 8); 111184588Sdfr t[3] = (usage >> 0); 112184588Sdfr if (ks->ks_class->ec_type == ETYPE_ARCFOUR_HMAC_MD5_56) { 113184588Sdfr uint8_t L40[14] = "fortybits"; 114184588Sdfr bcopy(t, L40 + 10, 4); 115184588Sdfr arcfour_hmac(ks->ks_key, L40, 14, newkey); 116184588Sdfr memset(newkey + 7, 0xab, 9); 117184588Sdfr } else { 118184588Sdfr arcfour_hmac(ks->ks_key, t, 4, newkey); 119184588Sdfr } 120184588Sdfr} 121184588Sdfr 122184588Sdfrstatic int 123184588Sdfrrc4_crypt_int(void *rs, void *buf, u_int len) 124184588Sdfr{ 125184588Sdfr 126184588Sdfr rc4_crypt(rs, buf, buf, len); 127184588Sdfr return (0); 128184588Sdfr} 129184588Sdfr 130184588Sdfrstatic void 131184588Sdfrarcfour_encrypt(const struct krb5_key_state *ks, struct mbuf *inout, 132184588Sdfr size_t skip, size_t len, void *ivec, size_t ivlen) 133184588Sdfr{ 134184588Sdfr struct rc4_state rs; 135184588Sdfr uint8_t newkey[16]; 136184588Sdfr 137184588Sdfr arcfour_derive_key(ks, 0, newkey); 138184588Sdfr 139184588Sdfr /* 140184588Sdfr * If we have an IV, then generate a new key from it using HMAC. 141184588Sdfr */ 142184588Sdfr if (ivec) { 143184588Sdfr uint8_t kk[16]; 144184588Sdfr arcfour_hmac(newkey, ivec, ivlen, kk); 145184588Sdfr rc4_init(&rs, kk, 16); 146184588Sdfr } else { 147184588Sdfr rc4_init(&rs, newkey, 16); 148184588Sdfr } 149184588Sdfr 150184588Sdfr m_apply(inout, skip, len, rc4_crypt_int, &rs); 151184588Sdfr} 152184588Sdfr 153184588Sdfrstatic int 154184588SdfrMD5Update_int(void *ctx, void *buf, u_int len) 155184588Sdfr{ 156184588Sdfr 157184588Sdfr MD5Update(ctx, buf, len); 158184588Sdfr return (0); 159184588Sdfr} 160184588Sdfr 161184588Sdfrstatic void 162184588Sdfrarcfour_checksum(const struct krb5_key_state *ks, int usage, 163184588Sdfr struct mbuf *inout, size_t skip, size_t inlen, size_t outlen) 164184588Sdfr{ 165184588Sdfr MD5_CTX md5; 166184588Sdfr uint8_t Ksign[16]; 167184588Sdfr uint8_t t[4]; 168184588Sdfr uint8_t sgn_cksum[16]; 169184588Sdfr 170184588Sdfr arcfour_hmac(ks->ks_key, "signaturekey", 13, Ksign); 171184588Sdfr 172184588Sdfr t[0] = usage >> 0; 173184588Sdfr t[1] = usage >> 8; 174184588Sdfr t[2] = usage >> 16; 175184588Sdfr t[3] = usage >> 24; 176184588Sdfr 177184588Sdfr MD5Init(&md5); 178184588Sdfr MD5Update(&md5, t, 4); 179184588Sdfr m_apply(inout, skip, inlen, MD5Update_int, &md5); 180184588Sdfr MD5Final(sgn_cksum, &md5); 181184588Sdfr 182184588Sdfr arcfour_hmac(Ksign, sgn_cksum, 16, sgn_cksum); 183184588Sdfr m_copyback(inout, skip + inlen, outlen, sgn_cksum); 184184588Sdfr} 185184588Sdfr 186184588Sdfrstruct krb5_encryption_class krb5_arcfour_encryption_class = { 187184588Sdfr "arcfour-hmac-md5", /* name */ 188184588Sdfr ETYPE_ARCFOUR_HMAC_MD5, /* etype */ 189184588Sdfr 0, /* flags */ 190184588Sdfr 1, /* blocklen */ 191184588Sdfr 1, /* msgblocklen */ 192184588Sdfr 8, /* checksumlen */ 193184588Sdfr 128, /* keybits */ 194184588Sdfr 16, /* keylen */ 195184588Sdfr arcfour_init, 196184588Sdfr arcfour_destroy, 197184588Sdfr arcfour_set_key, 198184588Sdfr arcfour_random_to_key, 199184588Sdfr arcfour_encrypt, 200184588Sdfr arcfour_encrypt, 201184588Sdfr arcfour_checksum 202184588Sdfr}; 203184588Sdfr 204184588Sdfrstruct krb5_encryption_class krb5_arcfour_56_encryption_class = { 205184588Sdfr "arcfour-hmac-md5-56", /* name */ 206184588Sdfr ETYPE_ARCFOUR_HMAC_MD5_56, /* etype */ 207184588Sdfr 0, /* flags */ 208184588Sdfr 1, /* blocklen */ 209184588Sdfr 1, /* msgblocklen */ 210184588Sdfr 8, /* checksumlen */ 211184588Sdfr 128, /* keybits */ 212184588Sdfr 16, /* keylen */ 213184588Sdfr arcfour_init, 214184588Sdfr arcfour_destroy, 215184588Sdfr arcfour_set_key, 216184588Sdfr arcfour_random_to_key, 217184588Sdfr arcfour_encrypt, 218184588Sdfr arcfour_encrypt, 219184588Sdfr arcfour_checksum 220184588Sdfr}; 221