Home | History | Annotate | Line # | Download | only in kafs
      1 /*	$NetBSD: rxkad_kdf.c,v 1.4 2023/06/19 21:41:44 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995-2003 Kungliga Tekniska Hgskolan
      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 #define HC_DEPRECATED_CRYPTO
     43 #include "kafs_locl.h"
     44 
     45 static int rxkad_derive_des_key(const void *, size_t, char[8]);
     46 static int compress_parity_bits(void *, size_t *);
     47 
     48 /**
     49  * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
     50  * des key from another type of key.
     51  *
     52  * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
     53  * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
     54  * properly should be 1.  However, we apply a slight variation due to the
     55  * possibility of producing a weak des key.  If the output key is weak, do NOT
     56  * simply correct it, instead, the counter is advanced and the next output
     57  * used.  As such, we code so as to have n be the full 255 permitted by our
     58  * encoding of the counter i in an 8-bit field.  L itself is encoded as a
     59  * 32-bit field, big-endian.  We use the constant string "rxkad" as a label
     60  * for this key derivation, the standard NUL byte separator, and omit a
     61  * key-derivation context.  The input key is unique to the krb5 service ticket,
     62  * which is unlikely to be used in an other location.  If it is used in such
     63  * a fashion, both locations will derive the same des key from the PRF, but
     64  * this is no different from if a krb5 des key had been used in the same way,
     65  * as traditional krb5 rxkad uses the ticket session key directly as the token
     66  * key.
     67  *
     68  * @param[in]  in      pointer to input key data
     69  * @param[in]  insize  length of input key data
     70  * @param[out] out     8-byte buffer to hold the derived key
     71  *
     72  * @return Returns 0 to indicate success, or an error code.
     73  *
     74  * @retval KRB5DES_WEAK_KEY  Successive derivation attempts with all
     75  * 255 possible counter values each produced weak DES keys.  This input
     76  * cannot be used to produce a usable key.
     77  */
     78 static int
     79 rxkad_derive_des_key(const void *in, size_t insize, char out[8])
     80 {
     81     unsigned char i;
     82     static unsigned char label[] = "rxkad";
     83     /* bits of output, as 32 bit word, MSB first */
     84     static unsigned char Lbuf[4] = { 0, 0, 0, 64 };
     85     /* only needs to be 16 for md5, but lets be sure it fits */
     86     unsigned char tmp[64];
     87     unsigned int mdsize;
     88     DES_cblock ktmp;
     89     HMAC_CTX *mctx;
     90 
     91     /* stop when 8 bit counter wraps to 0 */
     92     for (i = 1; i; i++) {
     93 #if OPENSSL_VERSION_NUMBER < 0x10100000UL
     94 	HMAC_CTX mctxs;
     95 	mctx = &mctxs;
     96 	HMAC_CTX_init(mctx);
     97 #else
     98 	mctx = HMAC_CTX_new();
     99 #endif
    100 	HMAC_Init_ex(mctx, in, insize, EVP_md5(), NULL);
    101 	HMAC_Update(mctx, &i, 1);
    102 	HMAC_Update(mctx, label, sizeof(label));   /* includes label and separator */
    103 	HMAC_Update(mctx, Lbuf, 4);
    104 	mdsize = sizeof(tmp);
    105 	HMAC_Final(mctx, tmp, &mdsize);
    106 	memcpy(ktmp, tmp, 8);
    107 #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    108 	HMAC_CTX_cleanup(mctx);
    109 #else
    110 	HMAC_CTX_free(mctx);
    111 #endif
    112 	DES_set_odd_parity(&ktmp);
    113 	if (!DES_is_weak_key(&ktmp)) {
    114 	    memcpy(out, ktmp, 8);
    115 	    return 0;
    116 	}
    117     }
    118     return KRB5DES_WEAK_KEY;
    119 }
    120 
    121 /**
    122  * This is the inverse of the random-to-key for 3des specified in
    123  * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing
    124  * the bits of each 8th byte as the lsb of the previous 7 bytes.
    125  *
    126  * @param[in,out]  buffer  Buffer containing the key to be converted
    127  * @param[in,out]  bufsiz  Points to the size of the key data.  On
    128  * return, this is updated to reflect the size of the compressed data.
    129  *
    130  * @return Returns 0 to indicate success, or an error code.
    131  *
    132  * @retval KRB5_BAD_KEYSIZE  The key size was not a multiple of 8 bytes.
    133  */
    134 static int
    135 compress_parity_bits(void *buffer, size_t *bufsiz)
    136 {
    137     unsigned char *cb, tmp;
    138     int i, j, nk;
    139 
    140     if (*bufsiz % 8 != 0)
    141 	return KRB5_BAD_KEYSIZE;
    142     cb = (unsigned char *)buffer;
    143     nk = *bufsiz / 8;
    144     for (i = 0; i < nk; i++) {
    145 	tmp = cb[8 * i + 7] >> 1;
    146 	for (j = 0; j < 7; j++) {
    147 	    cb[8 * i + j] &= 0xfe;
    148 	    cb[8 * i + j] |= tmp & 0x1;
    149 	    tmp >>= 1;
    150 	}
    151     }
    152     for (i = 1; i < nk; i++)
    153 	memmove(cb + 7 * i, cb + 8 * i, 7);
    154     *bufsiz = 7 * nk;
    155     return 0;
    156 }
    157 
    158 /**
    159  * Derive a DES key for use with rxkad and fcrypt from a given Kerberos
    160  * key of (almost) any type.  This function encodes enctype-specific
    161  * knowledge about how to derive a DES key from a given key type.
    162  * If given a des key, use it directly; otherwise, perform any parity
    163  * fixup that may be needed and pass through to the hmad-md5 bits.
    164  *
    165  * @param[in]   enctype  Kerberos enctype of the input key
    166  * @param[in]   keydata  Input key data
    167  * @param[in]   keylen   Size of input key data
    168  * @param[out]  output   8-byte buffer to hold the derived key
    169  *
    170  * @return Returns 0 to indicate success, or an error code.
    171  *
    172  * @retval KRB5_PROG_ETYPE_NOSUPP  The enctype is one for which rxkad-kdf
    173  * is not supported.  This includes several reserved enctypes, enctype
    174  * values used in PKINIT to stand for CMS algorithm identifiers, and all
    175  * private-use (negative) enctypes.
    176  *
    177  * @retval KRB5_BAD_KEYSIZE  The key size was not a multiple of 8 bytes
    178  * (for 3DES key types), exactly 8 bytes (for DES key types), or at least
    179  * 8 bytes (for other key types).
    180  *
    181  * @retval KRB5DES_WEAK_KEY  Successive derivation attempts with all
    182  * 255 possible counter values each produced weak DES keys.  This input
    183  * cannot be used to produce a usable key.
    184  */
    185 int
    186 _kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen,
    187 		     char output[8])
    188 {
    189     int ret = 0;
    190 
    191     switch ((int)enctype) {
    192     case ETYPE_DES_CBC_CRC:
    193     case ETYPE_DES_CBC_MD4:
    194     case ETYPE_DES_CBC_MD5:
    195 	if (keylen != 8)
    196 	    return KRB5_BAD_KEYSIZE;
    197 
    198 	/* Extract session key */
    199 	memcpy(output, keydata, 8);
    200 	break;
    201     case ETYPE_NULL:
    202     case 4:
    203     case 6:
    204     case 8:
    205     case 9:
    206     case 10:
    207     case 11:
    208     case 12:
    209     case 13:
    210     case 14:
    211     case 15:
    212 	return KRB5_PROG_ETYPE_NOSUPP;
    213 	/*In order to become a "Cryptographic Key" as specified in
    214 	 * SP800-108, it must be indistinguishable from a random bitstring. */
    215     case ETYPE_DES3_CBC_MD5:
    216     case ETYPE_OLD_DES3_CBC_SHA1:
    217     case ETYPE_DES3_CBC_SHA1:
    218 	ret = compress_parity_bits(keydata, &keylen);
    219 	if (ret)
    220 	    return ret;
    221 	/* FALLTHROUGH */
    222     default:
    223 	if (enctype < 0)
    224 	    return KRB5_PROG_ETYPE_NOSUPP;
    225 	if (keylen < 7)
    226 	    return KRB5_BAD_KEYSIZE;
    227 	ret = rxkad_derive_des_key(keydata, keylen, output);
    228     }
    229     return ret;
    230 }
    231