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 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 #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
rxkad_derive_des_key(const void * in,size_t insize,char out[8])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
compress_parity_bits(void * buffer,size_t * bufsiz)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
_kafs_derive_des_key(krb5_enctype enctype,void * keydata,size_t keylen,char output[8])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