1 /* $NetBSD: rxkad_kdf.c,v 1.3 2018/02/05 16:00:53 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1995-2003 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Portions Copyright (c) 2013-2014 Carnegie Mellon University 9 * All rights reserved. 10 * 11 * Portions Copyright (c) 2013 by the Massachusetts Institute of Technology 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * 3. Neither the name of the Institute nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 */ 41 42 #include "kafs_locl.h" 43 44 static int rxkad_derive_des_key(const void *, size_t, char[8]); 45 static int compress_parity_bits(void *, size_t *); 46 47 /** 48 * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a 49 * des key from another type of key. 50 * 51 * L is 64, as we take 64 random bits and turn them into a 56-bit des key. 52 * The output of hmac_md5 is 128 bits; we take the first 64 only, so n 53 * properly should be 1. However, we apply a slight variation due to the 54 * possibility of producing a weak des key. If the output key is weak, do NOT 55 * simply correct it, instead, the counter is advanced and the next output 56 * used. As such, we code so as to have n be the full 255 permitted by our 57 * encoding of the counter i in an 8-bit field. L itself is encoded as a 58 * 32-bit field, big-endian. We use the constant string "rxkad" as a label 59 * for this key derivation, the standard NUL byte separator, and omit a 60 * key-derivation context. The input key is unique to the krb5 service ticket, 61 * which is unlikely to be used in an other location. If it is used in such 62 * a fashion, both locations will derive the same des key from the PRF, but 63 * this is no different from if a krb5 des key had been used in the same way, 64 * as traditional krb5 rxkad uses the ticket session key directly as the token 65 * key. 66 * 67 * @param[in] in pointer to input key data 68 * @param[in] insize length of input key data 69 * @param[out] out 8-byte buffer to hold the derived key 70 * 71 * @return Returns 0 to indicate success, or an error code. 72 * 73 * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all 74 * 255 possible counter values each produced weak DES keys. This input 75 * cannot be used to produce a usable key. 76 */ 77 static int 78 rxkad_derive_des_key(const void *in, size_t insize, char out[8]) 79 { 80 unsigned char i; 81 static unsigned char label[] = "rxkad"; 82 /* bits of output, as 32 bit word, MSB first */ 83 static unsigned char Lbuf[4] = { 0, 0, 0, 64 }; 84 /* only needs to be 16 for md5, but lets be sure it fits */ 85 unsigned char tmp[64]; 86 unsigned int mdsize; 87 DES_cblock ktmp; 88 HMAC_CTX *mctx; 89 90 /* stop when 8 bit counter wraps to 0 */ 91 for (i = 1; i; i++) { 92 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 93 HMAC_CTX mctxs; 94 mctx = &mctxs; 95 HMAC_CTX_init(mctx); 96 #else 97 mctx = HMAC_CTX_new(); 98 #endif 99 HMAC_Init_ex(mctx, in, insize, EVP_md5(), NULL); 100 HMAC_Update(mctx, &i, 1); 101 HMAC_Update(mctx, label, sizeof(label)); /* includes label and separator */ 102 HMAC_Update(mctx, Lbuf, 4); 103 mdsize = sizeof(tmp); 104 HMAC_Final(mctx, tmp, &mdsize); 105 memcpy(ktmp, tmp, 8); 106 #if OPENSSL_VERSION_NUMBER < 0x10100000UL 107 HMAC_CTX_cleanup(mctx); 108 #else 109 HMAC_CTX_free(mctx); 110 #endif 111 DES_set_odd_parity(&ktmp); 112 if (!DES_is_weak_key(&ktmp)) { 113 memcpy(out, ktmp, 8); 114 return 0; 115 } 116 } 117 return KRB5DES_WEAK_KEY; 118 } 119 120 /** 121 * This is the inverse of the random-to-key for 3des specified in 122 * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing 123 * the bits of each 8th byte as the lsb of the previous 7 bytes. 124 * 125 * @param[in,out] buffer Buffer containing the key to be converted 126 * @param[in,out] bufsiz Points to the size of the key data. On 127 * return, this is updated to reflect the size of the compressed data. 128 * 129 * @return Returns 0 to indicate success, or an error code. 130 * 131 * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes. 132 */ 133 static int 134 compress_parity_bits(void *buffer, size_t *bufsiz) 135 { 136 unsigned char *cb, tmp; 137 int i, j, nk; 138 139 if (*bufsiz % 8 != 0) 140 return KRB5_BAD_KEYSIZE; 141 cb = (unsigned char *)buffer; 142 nk = *bufsiz / 8; 143 for (i = 0; i < nk; i++) { 144 tmp = cb[8 * i + 7] >> 1; 145 for (j = 0; j < 7; j++) { 146 cb[8 * i + j] &= 0xfe; 147 cb[8 * i + j] |= tmp & 0x1; 148 tmp >>= 1; 149 } 150 } 151 for (i = 1; i < nk; i++) 152 memmove(cb + 7 * i, cb + 8 * i, 7); 153 *bufsiz = 7 * nk; 154 return 0; 155 } 156 157 /** 158 * Derive a DES key for use with rxkad and fcrypt from a given Kerberos 159 * key of (almost) any type. This function encodes enctype-specific 160 * knowledge about how to derive a DES key from a given key type. 161 * If given a des key, use it directly; otherwise, perform any parity 162 * fixup that may be needed and pass through to the hmad-md5 bits. 163 * 164 * @param[in] enctype Kerberos enctype of the input key 165 * @param[in] keydata Input key data 166 * @param[in] keylen Size of input key data 167 * @param[out] output 8-byte buffer to hold the derived key 168 * 169 * @return Returns 0 to indicate success, or an error code. 170 * 171 * @retval KRB5_PROG_ETYPE_NOSUPP The enctype is one for which rxkad-kdf 172 * is not supported. This includes several reserved enctypes, enctype 173 * values used in PKINIT to stand for CMS algorithm identifiers, and all 174 * private-use (negative) enctypes. 175 * 176 * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes 177 * (for 3DES key types), exactly 8 bytes (for DES key types), or at least 178 * 8 bytes (for other key types). 179 * 180 * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all 181 * 255 possible counter values each produced weak DES keys. This input 182 * cannot be used to produce a usable key. 183 */ 184 int 185 _kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen, 186 char output[8]) 187 { 188 int ret = 0; 189 190 switch ((int)enctype) { 191 case ETYPE_DES_CBC_CRC: 192 case ETYPE_DES_CBC_MD4: 193 case ETYPE_DES_CBC_MD5: 194 if (keylen != 8) 195 return KRB5_BAD_KEYSIZE; 196 197 /* Extract session key */ 198 memcpy(output, keydata, 8); 199 break; 200 case ETYPE_NULL: 201 case 4: 202 case 6: 203 case 8: 204 case 9: 205 case 10: 206 case 11: 207 case 12: 208 case 13: 209 case 14: 210 case 15: 211 return KRB5_PROG_ETYPE_NOSUPP; 212 /*In order to become a "Cryptographic Key" as specified in 213 * SP800-108, it must be indistinguishable from a random bitstring. */ 214 case ETYPE_DES3_CBC_MD5: 215 case ETYPE_OLD_DES3_CBC_SHA1: 216 case ETYPE_DES3_CBC_SHA1: 217 ret = compress_parity_bits(keydata, &keylen); 218 if (ret) 219 return ret; 220 /* FALLTHROUGH */ 221 default: 222 if (enctype < 0) 223 return KRB5_PROG_ETYPE_NOSUPP; 224 if (keylen < 7) 225 return KRB5_BAD_KEYSIZE; 226 ret = rxkad_derive_des_key(keydata, keylen, output); 227 } 228 return ret; 229 } 230