2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include "krb5_locl.h"
40 static struct _krb5_key_type keytype_arcfour = {
41 KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
45 sizeof(struct _krb5_evp_schedule),
55 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
59 _krb5_HMAC_MD5_checksum(krb5_context context,
60 struct _krb5_key_data *key,
67 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
68 const char signature[] = "signaturekey";
70 struct _krb5_key_data ksign;
73 unsigned char tmp[16];
74 unsigned char ksign_c_data[16];
77 m = EVP_MD_CTX_create();
79 return krb5_enomem(context);
80 ksign_c.checksum.length = sizeof(ksign_c_data);
81 ksign_c.checksum.data = ksign_c_data;
82 ret = _krb5_internal_hmac(context, c, signature, sizeof(signature),
85 EVP_MD_CTX_destroy(m);
89 kb.keyvalue = ksign_c.checksum;
90 EVP_DigestInit_ex(m, EVP_md5(), NULL);
91 t[0] = (usage >> 0) & 0xFF;
92 t[1] = (usage >> 8) & 0xFF;
93 t[2] = (usage >> 16) & 0xFF;
94 t[3] = (usage >> 24) & 0xFF;
95 EVP_DigestUpdate(m, t, 4);
96 EVP_DigestUpdate(m, data, len);
97 EVP_DigestFinal_ex (m, tmp, NULL);
98 EVP_MD_CTX_destroy(m);
100 ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
106 struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
112 _krb5_HMAC_MD5_checksum,
117 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
119 * warning: not for small children
122 static krb5_error_code
123 ARCFOUR_subencrypt(krb5_context context,
124 struct _krb5_key_data *key,
131 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
132 Checksum k1_c, k2_c, k3_c, cksum;
133 struct _krb5_key_data ke;
136 unsigned char *cdata = data;
137 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
140 t[0] = (usage >> 0) & 0xFF;
141 t[1] = (usage >> 8) & 0xFF;
142 t[2] = (usage >> 16) & 0xFF;
143 t[3] = (usage >> 24) & 0xFF;
145 k1_c.checksum.length = sizeof(k1_c_data);
146 k1_c.checksum.data = k1_c_data;
148 ret = _krb5_internal_hmac(context, c, t, sizeof(t), 0, key, &k1_c);
150 krb5_abortx(context, "hmac failed");
152 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
154 k2_c.checksum.length = sizeof(k2_c_data);
155 k2_c.checksum.data = k2_c_data;
158 kb.keyvalue = k2_c.checksum;
160 cksum.checksum.length = 16;
161 cksum.checksum.data = data;
163 ret = _krb5_internal_hmac(context, c, cdata + 16, len - 16, 0, &ke, &cksum);
165 krb5_abortx(context, "hmac failed");
168 kb.keyvalue = k1_c.checksum;
170 k3_c.checksum.length = sizeof(k3_c_data);
171 k3_c.checksum.data = k3_c_data;
173 ret = _krb5_internal_hmac(context, c, data, 16, 0, &ke, &k3_c);
175 krb5_abortx(context, "hmac failed");
177 EVP_CIPHER_CTX_init(&ctx);
179 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
180 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
181 EVP_CIPHER_CTX_cleanup(&ctx);
183 memset (k1_c_data, 0, sizeof(k1_c_data));
184 memset (k2_c_data, 0, sizeof(k2_c_data));
185 memset (k3_c_data, 0, sizeof(k3_c_data));
189 static krb5_error_code
190 ARCFOUR_subdecrypt(krb5_context context,
191 struct _krb5_key_data *key,
198 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
199 Checksum k1_c, k2_c, k3_c, cksum;
200 struct _krb5_key_data ke;
203 unsigned char *cdata = data;
204 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
205 unsigned char cksum_data[16];
208 t[0] = (usage >> 0) & 0xFF;
209 t[1] = (usage >> 8) & 0xFF;
210 t[2] = (usage >> 16) & 0xFF;
211 t[3] = (usage >> 24) & 0xFF;
213 k1_c.checksum.length = sizeof(k1_c_data);
214 k1_c.checksum.data = k1_c_data;
216 ret = _krb5_internal_hmac(context, c, t, sizeof(t), 0, key, &k1_c);
218 krb5_abortx(context, "hmac failed");
220 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
222 k2_c.checksum.length = sizeof(k2_c_data);
223 k2_c.checksum.data = k2_c_data;
226 kb.keyvalue = k1_c.checksum;
228 k3_c.checksum.length = sizeof(k3_c_data);
229 k3_c.checksum.data = k3_c_data;
231 ret = _krb5_internal_hmac(context, c, cdata, 16, 0, &ke, &k3_c);
233 krb5_abortx(context, "hmac failed");
235 EVP_CIPHER_CTX_init(&ctx);
236 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
237 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
238 EVP_CIPHER_CTX_cleanup(&ctx);
241 kb.keyvalue = k2_c.checksum;
243 cksum.checksum.length = 16;
244 cksum.checksum.data = cksum_data;
246 ret = _krb5_internal_hmac(context, c, cdata + 16, len - 16, 0, &ke, &cksum);
248 krb5_abortx(context, "hmac failed");
250 memset (k1_c_data, 0, sizeof(k1_c_data));
251 memset (k2_c_data, 0, sizeof(k2_c_data));
252 memset (k3_c_data, 0, sizeof(k3_c_data));
254 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
255 krb5_clear_error_message (context);
256 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
263 * convert the usage numbers used in
264 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
265 * draft-brezak-win2k-krb-rc4-hmac-04.txt
268 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
269 _krb5_usage2arcfour(krb5_context context, unsigned *usage)
272 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
275 case KRB5_KU_USAGE_SEAL : /* 22 */
278 case KRB5_KU_USAGE_SIGN : /* 23 */
281 case KRB5_KU_USAGE_SEQ: /* 24 */
289 static krb5_error_code
290 ARCFOUR_encrypt(krb5_context context,
291 struct _krb5_key_data *key,
294 krb5_boolean encryptp,
299 unsigned keyusage = usage;
301 if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
305 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
307 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
310 static krb5_error_code
311 ARCFOUR_prf(krb5_context context,
316 struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
320 ret = krb5_data_alloc(out, c->checksumsize);
324 res.checksum.data = out->data;
325 res.checksum.length = out->length;
327 ret = _krb5_internal_hmac(context, c, in->data, in->length, 0, &crypto->key, &res);
334 struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
335 ETYPE_ARCFOUR_HMAC_MD5,
342 &_krb5_checksum_hmac_md5,
343 &_krb5_checksum_hmac_md5,