Line data Source code
1 : /*
2 : * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
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.
16 : *
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.
20 : *
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
31 : * SUCH DAMAGE.
32 : */
33 :
34 : /*
35 : * ARCFOUR
36 : */
37 :
38 : #include "krb5_locl.h"
39 :
40 : static struct _krb5_key_type keytype_arcfour = {
41 : KRB5_ENCTYPE_ARCFOUR_HMAC_MD5,
42 : "arcfour",
43 : 128,
44 : 16,
45 : sizeof(struct _krb5_evp_schedule),
46 : NULL,
47 : _krb5_evp_schedule,
48 : _krb5_arcfour_salt,
49 : NULL,
50 : _krb5_evp_cleanup,
51 : EVP_rc4
52 : };
53 :
54 : /*
55 : * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
56 : */
57 :
58 : krb5_error_code
59 194047 : _krb5_HMAC_MD5_checksum(krb5_context context,
60 : krb5_crypto crypto,
61 : struct _krb5_key_data *key,
62 : unsigned usage,
63 : const struct krb5_crypto_iov *iov,
64 : int niov,
65 : Checksum *result)
66 : {
67 44 : EVP_MD_CTX *m;
68 194047 : struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
69 194047 : const char signature[] = "signaturekey";
70 44 : Checksum ksign_c;
71 44 : struct _krb5_key_data ksign;
72 44 : krb5_keyblock kb;
73 44 : unsigned char t[4];
74 44 : unsigned char tmp[16];
75 44 : unsigned char ksign_c_data[16];
76 44 : krb5_error_code ret;
77 44 : int i;
78 :
79 194047 : if (crypto != NULL) {
80 169134 : if (crypto->mdctx == NULL)
81 169032 : crypto->mdctx = EVP_MD_CTX_create();
82 169134 : if (crypto->mdctx == NULL)
83 0 : return krb5_enomem(context);
84 169090 : m = crypto->mdctx;
85 : } else
86 24913 : m = EVP_MD_CTX_create();
87 :
88 194047 : ksign_c.checksum.length = sizeof(ksign_c_data);
89 194047 : ksign_c.checksum.data = ksign_c_data;
90 194047 : ret = _krb5_internal_hmac(context, crypto, c, signature, sizeof(signature),
91 : 0, key, &ksign_c);
92 194047 : if (ret)
93 0 : goto out;
94 :
95 194047 : ksign.key = &kb;
96 194047 : kb.keyvalue = ksign_c.checksum;
97 194047 : EVP_DigestInit_ex(m, EVP_md5(), NULL);
98 194047 : t[0] = (usage >> 0) & 0xFF;
99 194047 : t[1] = (usage >> 8) & 0xFF;
100 194047 : t[2] = (usage >> 16) & 0xFF;
101 194047 : t[3] = (usage >> 24) & 0xFF;
102 194047 : EVP_DigestUpdate(m, t, 4);
103 388138 : for (i = 0; i < niov; i++) {
104 194047 : if (_krb5_crypto_iov_should_sign(&iov[i]))
105 194047 : EVP_DigestUpdate(m, iov[i].data.data, iov[i].data.length);
106 : }
107 194047 : EVP_DigestFinal_ex (m, tmp, NULL);
108 :
109 194047 : ret = _krb5_internal_hmac(context, crypto, c, tmp, sizeof(tmp), 0, &ksign, result);
110 194047 : out:
111 194047 : if (crypto == NULL)
112 24913 : EVP_MD_CTX_destroy(m);
113 :
114 194003 : return ret;
115 : }
116 :
117 : struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
118 : CKSUMTYPE_HMAC_MD5,
119 : "hmac-md5",
120 : 64,
121 : 16,
122 : F_KEYED | F_CPROOF,
123 : _krb5_HMAC_MD5_checksum,
124 : NULL
125 : };
126 :
127 : /*
128 : * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
129 : *
130 : * warning: not for small children
131 : */
132 :
133 : static krb5_error_code
134 26903 : ARCFOUR_subencrypt(krb5_context context,
135 : struct _krb5_key_data *key,
136 : void *data,
137 : size_t len,
138 : unsigned usage,
139 : void *ivec)
140 : {
141 18 : EVP_CIPHER_CTX ctx;
142 26903 : struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
143 18 : Checksum k1_c, k2_c, k3_c, cksum;
144 18 : struct _krb5_key_data ke;
145 18 : krb5_keyblock kb;
146 18 : unsigned char t[4];
147 26903 : unsigned char *cdata = data;
148 18 : unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
149 18 : krb5_error_code ret;
150 :
151 26903 : if (len < 16) {
152 0 : return KRB5KRB_AP_ERR_INAPP_CKSUM;
153 : }
154 :
155 26903 : t[0] = (usage >> 0) & 0xFF;
156 26903 : t[1] = (usage >> 8) & 0xFF;
157 26903 : t[2] = (usage >> 16) & 0xFF;
158 26903 : t[3] = (usage >> 24) & 0xFF;
159 :
160 26903 : k1_c.checksum.length = sizeof(k1_c_data);
161 26903 : k1_c.checksum.data = k1_c_data;
162 :
163 26903 : ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
164 26903 : if (ret)
165 0 : krb5_abortx(context, "hmac failed");
166 :
167 26903 : memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
168 :
169 26903 : k2_c.checksum.length = sizeof(k2_c_data);
170 26903 : k2_c.checksum.data = k2_c_data;
171 :
172 26903 : ke.key = &kb;
173 26903 : kb.keyvalue = k2_c.checksum;
174 :
175 26903 : cksum.checksum.length = 16;
176 26903 : cksum.checksum.data = data;
177 :
178 26903 : ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
179 26903 : if (ret)
180 0 : krb5_abortx(context, "hmac failed");
181 :
182 26903 : ke.key = &kb;
183 26903 : kb.keyvalue = k1_c.checksum;
184 :
185 26903 : k3_c.checksum.length = sizeof(k3_c_data);
186 26903 : k3_c.checksum.data = k3_c_data;
187 :
188 26903 : ret = _krb5_internal_hmac(context, NULL, c, data, 16, 0, &ke, &k3_c);
189 26903 : if (ret)
190 0 : krb5_abortx(context, "hmac failed");
191 :
192 26903 : EVP_CIPHER_CTX_init(&ctx);
193 :
194 26903 : EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
195 26903 : EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
196 26903 : EVP_CIPHER_CTX_cleanup(&ctx);
197 :
198 26903 : memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
199 26903 : memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
200 26903 : memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
201 26903 : return 0;
202 : }
203 :
204 : static krb5_error_code
205 21212 : ARCFOUR_subdecrypt(krb5_context context,
206 : struct _krb5_key_data *key,
207 : void *data,
208 : size_t len,
209 : unsigned usage,
210 : void *ivec)
211 : {
212 18 : EVP_CIPHER_CTX ctx;
213 21212 : struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
214 18 : Checksum k1_c, k2_c, k3_c, cksum;
215 18 : struct _krb5_key_data ke;
216 18 : krb5_keyblock kb;
217 18 : unsigned char t[4];
218 21212 : unsigned char *cdata = data;
219 18 : unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
220 18 : unsigned char cksum_data[16];
221 18 : krb5_error_code ret;
222 :
223 21212 : if (len < 16) {
224 0 : return KRB5KRB_AP_ERR_INAPP_CKSUM;
225 : }
226 :
227 21212 : t[0] = (usage >> 0) & 0xFF;
228 21212 : t[1] = (usage >> 8) & 0xFF;
229 21212 : t[2] = (usage >> 16) & 0xFF;
230 21212 : t[3] = (usage >> 24) & 0xFF;
231 :
232 21212 : k1_c.checksum.length = sizeof(k1_c_data);
233 21212 : k1_c.checksum.data = k1_c_data;
234 :
235 21212 : ret = _krb5_internal_hmac(context, NULL, c, t, sizeof(t), 0, key, &k1_c);
236 21212 : if (ret)
237 0 : krb5_abortx(context, "hmac failed");
238 :
239 21212 : memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
240 :
241 21212 : k2_c.checksum.length = sizeof(k2_c_data);
242 21212 : k2_c.checksum.data = k2_c_data;
243 :
244 21212 : ke.key = &kb;
245 21212 : kb.keyvalue = k1_c.checksum;
246 :
247 21212 : k3_c.checksum.length = sizeof(k3_c_data);
248 21212 : k3_c.checksum.data = k3_c_data;
249 :
250 21212 : ret = _krb5_internal_hmac(context, NULL, c, cdata, 16, 0, &ke, &k3_c);
251 21212 : if (ret)
252 0 : krb5_abortx(context, "hmac failed");
253 :
254 21212 : EVP_CIPHER_CTX_init(&ctx);
255 21212 : EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
256 21212 : EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
257 21212 : EVP_CIPHER_CTX_cleanup(&ctx);
258 :
259 21212 : ke.key = &kb;
260 21212 : kb.keyvalue = k2_c.checksum;
261 :
262 21212 : cksum.checksum.length = 16;
263 21212 : cksum.checksum.data = cksum_data;
264 :
265 21212 : ret = _krb5_internal_hmac(context, NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
266 21212 : if (ret)
267 0 : krb5_abortx(context, "hmac failed");
268 :
269 21212 : memset_s(k1_c_data, sizeof(k1_c_data), 0, sizeof(k1_c_data));
270 21212 : memset_s(k2_c_data, sizeof(k2_c_data), 0, sizeof(k2_c_data));
271 21212 : memset_s(k3_c_data, sizeof(k3_c_data), 0, sizeof(k3_c_data));
272 :
273 21212 : if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
274 17 : krb5_clear_error_message (context);
275 17 : return KRB5KRB_AP_ERR_BAD_INTEGRITY;
276 : } else {
277 21177 : return 0;
278 : }
279 : }
280 :
281 : /*
282 : * convert the usage numbers used in
283 : * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
284 : * draft-brezak-win2k-krb-rc4-hmac-04.txt
285 : */
286 :
287 : KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
288 217249 : _krb5_usage2arcfour(krb5_context context, unsigned *usage)
289 : {
290 217249 : switch (*usage) {
291 1836 : case KRB5_KU_AS_REP_ENC_PART : /* 3 */
292 1836 : *usage = 8;
293 1836 : return 0;
294 132298 : case KRB5_KU_USAGE_SEAL : /* 22 */
295 132298 : *usage = 13;
296 132298 : return 0;
297 30342 : case KRB5_KU_USAGE_SIGN : /* 23 */
298 30342 : *usage = 15;
299 30342 : return 0;
300 0 : case KRB5_KU_USAGE_SEQ: /* 24 */
301 0 : *usage = 0;
302 0 : return 0;
303 52711 : default :
304 52711 : return 0;
305 : }
306 : }
307 :
308 : static krb5_error_code
309 48115 : ARCFOUR_encrypt(krb5_context context,
310 : struct _krb5_key_data *key,
311 : void *data,
312 : size_t len,
313 : krb5_boolean encryptp,
314 : int usage,
315 : void *ivec)
316 : {
317 36 : krb5_error_code ret;
318 48115 : unsigned keyusage = usage;
319 :
320 48115 : if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
321 0 : return ret;
322 :
323 48115 : if (encryptp)
324 26903 : return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
325 : else
326 21212 : return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
327 : }
328 :
329 : static krb5_error_code
330 7804 : ARCFOUR_prf(krb5_context context,
331 : krb5_crypto crypto,
332 : const krb5_data *in,
333 : krb5_data *out)
334 : {
335 7804 : struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1);
336 0 : krb5_error_code ret;
337 0 : Checksum res;
338 :
339 7804 : ret = krb5_data_alloc(out, c->checksumsize);
340 7804 : if (ret)
341 0 : return ret;
342 :
343 7804 : res.checksum.data = out->data;
344 7804 : res.checksum.length = out->length;
345 :
346 7804 : ret = _krb5_internal_hmac(context, crypto, c, in->data, in->length, 0, &crypto->key, &res);
347 7804 : if (ret)
348 0 : krb5_data_free(out);
349 7804 : return 0;
350 : }
351 :
352 :
353 : struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
354 : ETYPE_ARCFOUR_HMAC_MD5,
355 : "arcfour-hmac-md5",
356 : "rc4-hmac",
357 : 1,
358 : 1,
359 : 8,
360 : &keytype_arcfour,
361 : &_krb5_checksum_hmac_md5,
362 : &_krb5_checksum_hmac_md5,
363 : F_SPECIAL | F_WEAK | F_OLD,
364 : ARCFOUR_encrypt,
365 : NULL,
366 : 0,
367 : ARCFOUR_prf
368 : };
|