add NTMakefile and windows directories
[heimdal.git] / lib / krb5 / crypto-arcfour.c
blob82769aea621cf4275d5780298c17a1d704dd75f6
1 /*
2 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
35 * ARCFOUR
38 #include "krb5_locl.h"
40 static struct _krb5_key_type keytype_arcfour = {
41 KEYTYPE_ARCFOUR,
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
55 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
58 krb5_error_code
59 _krb5_HMAC_MD5_checksum(krb5_context context,
60 struct _krb5_key_data *key,
61 const void *data,
62 size_t len,
63 unsigned usage,
64 Checksum *result)
66 EVP_MD_CTX *m;
67 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
68 const char signature[] = "signaturekey";
69 Checksum ksign_c;
70 struct _krb5_key_data ksign;
71 krb5_keyblock kb;
72 unsigned char t[4];
73 unsigned char tmp[16];
74 unsigned char ksign_c_data[16];
75 krb5_error_code ret;
77 m = EVP_MD_CTX_create();
78 if (m == NULL) {
79 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
80 return ENOMEM;
82 ksign_c.checksum.length = sizeof(ksign_c_data);
83 ksign_c.checksum.data = ksign_c_data;
84 ret = _krb5_internal_hmac(context, c, signature, sizeof(signature),
85 0, key, &ksign_c);
86 if (ret) {
87 EVP_MD_CTX_destroy(m);
88 return ret;
90 ksign.key = &kb;
91 kb.keyvalue = ksign_c.checksum;
92 EVP_DigestInit_ex(m, EVP_md5(), NULL);
93 t[0] = (usage >> 0) & 0xFF;
94 t[1] = (usage >> 8) & 0xFF;
95 t[2] = (usage >> 16) & 0xFF;
96 t[3] = (usage >> 24) & 0xFF;
97 EVP_DigestUpdate(m, t, 4);
98 EVP_DigestUpdate(m, data, len);
99 EVP_DigestFinal_ex (m, tmp, NULL);
100 EVP_MD_CTX_destroy(m);
102 ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
103 if (ret)
104 return ret;
105 return 0;
108 struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
109 CKSUMTYPE_HMAC_MD5,
110 "hmac-md5",
113 F_KEYED | F_CPROOF,
114 _krb5_HMAC_MD5_checksum,
115 NULL
119 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
121 * warning: not for small children
124 static krb5_error_code
125 ARCFOUR_subencrypt(krb5_context context,
126 struct _krb5_key_data *key,
127 void *data,
128 size_t len,
129 unsigned usage,
130 void *ivec)
132 EVP_CIPHER_CTX ctx;
133 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
134 Checksum k1_c, k2_c, k3_c, cksum;
135 struct _krb5_key_data ke;
136 krb5_keyblock kb;
137 unsigned char t[4];
138 unsigned char *cdata = data;
139 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
140 krb5_error_code ret;
142 t[0] = (usage >> 0) & 0xFF;
143 t[1] = (usage >> 8) & 0xFF;
144 t[2] = (usage >> 16) & 0xFF;
145 t[3] = (usage >> 24) & 0xFF;
147 k1_c.checksum.length = sizeof(k1_c_data);
148 k1_c.checksum.data = k1_c_data;
150 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
151 if (ret)
152 krb5_abortx(context, "hmac failed");
154 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
156 k2_c.checksum.length = sizeof(k2_c_data);
157 k2_c.checksum.data = k2_c_data;
159 ke.key = &kb;
160 kb.keyvalue = k2_c.checksum;
162 cksum.checksum.length = 16;
163 cksum.checksum.data = data;
165 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
166 if (ret)
167 krb5_abortx(context, "hmac failed");
169 ke.key = &kb;
170 kb.keyvalue = k1_c.checksum;
172 k3_c.checksum.length = sizeof(k3_c_data);
173 k3_c.checksum.data = k3_c_data;
175 ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c);
176 if (ret)
177 krb5_abortx(context, "hmac failed");
179 EVP_CIPHER_CTX_init(&ctx);
181 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
182 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
183 EVP_CIPHER_CTX_cleanup(&ctx);
185 memset (k1_c_data, 0, sizeof(k1_c_data));
186 memset (k2_c_data, 0, sizeof(k2_c_data));
187 memset (k3_c_data, 0, sizeof(k3_c_data));
188 return 0;
191 static krb5_error_code
192 ARCFOUR_subdecrypt(krb5_context context,
193 struct _krb5_key_data *key,
194 void *data,
195 size_t len,
196 unsigned usage,
197 void *ivec)
199 EVP_CIPHER_CTX ctx;
200 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
201 Checksum k1_c, k2_c, k3_c, cksum;
202 struct _krb5_key_data ke;
203 krb5_keyblock kb;
204 unsigned char t[4];
205 unsigned char *cdata = data;
206 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
207 unsigned char cksum_data[16];
208 krb5_error_code ret;
210 t[0] = (usage >> 0) & 0xFF;
211 t[1] = (usage >> 8) & 0xFF;
212 t[2] = (usage >> 16) & 0xFF;
213 t[3] = (usage >> 24) & 0xFF;
215 k1_c.checksum.length = sizeof(k1_c_data);
216 k1_c.checksum.data = k1_c_data;
218 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
219 if (ret)
220 krb5_abortx(context, "hmac failed");
222 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
224 k2_c.checksum.length = sizeof(k2_c_data);
225 k2_c.checksum.data = k2_c_data;
227 ke.key = &kb;
228 kb.keyvalue = k1_c.checksum;
230 k3_c.checksum.length = sizeof(k3_c_data);
231 k3_c.checksum.data = k3_c_data;
233 ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
234 if (ret)
235 krb5_abortx(context, "hmac failed");
237 EVP_CIPHER_CTX_init(&ctx);
238 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
239 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
240 EVP_CIPHER_CTX_cleanup(&ctx);
242 ke.key = &kb;
243 kb.keyvalue = k2_c.checksum;
245 cksum.checksum.length = 16;
246 cksum.checksum.data = cksum_data;
248 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
249 if (ret)
250 krb5_abortx(context, "hmac failed");
252 memset (k1_c_data, 0, sizeof(k1_c_data));
253 memset (k2_c_data, 0, sizeof(k2_c_data));
254 memset (k3_c_data, 0, sizeof(k3_c_data));
256 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
257 krb5_clear_error_message (context);
258 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
259 } else {
260 return 0;
265 * convert the usage numbers used in
266 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
267 * draft-brezak-win2k-krb-rc4-hmac-04.txt
270 krb5_error_code
271 _krb5_usage2arcfour(krb5_context context, unsigned *usage)
273 switch (*usage) {
274 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
275 *usage = 8;
276 return 0;
277 case KRB5_KU_USAGE_SEAL : /* 22 */
278 *usage = 13;
279 return 0;
280 case KRB5_KU_USAGE_SIGN : /* 23 */
281 *usage = 15;
282 return 0;
283 case KRB5_KU_USAGE_SEQ: /* 24 */
284 *usage = 0;
285 return 0;
286 default :
287 return 0;
291 static krb5_error_code
292 ARCFOUR_encrypt(krb5_context context,
293 struct _krb5_key_data *key,
294 void *data,
295 size_t len,
296 krb5_boolean encryptp,
297 int usage,
298 void *ivec)
300 krb5_error_code ret;
301 unsigned keyusage = usage;
303 if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
304 return ret;
306 if (encryptp)
307 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
308 else
309 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
312 struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
313 ETYPE_ARCFOUR_HMAC_MD5,
314 "arcfour-hmac-md5",
318 &keytype_arcfour,
319 &_krb5_checksum_hmac_md5,
320 NULL,
321 F_SPECIAL,
322 ARCFOUR_encrypt,
324 NULL