etc/services - sync with NetBSD-8
[minix.git] / crypto / external / bsd / heimdal / dist / lib / krb5 / crypto-arcfour.c
blobe1f1f6c6f257e719a6c13d28256c063b5dc47b96
1 /* $NetBSD: crypto-arcfour.c,v 1.1.1.2 2014/04/24 12:45:49 pettai Exp $ */
3 /*
4 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
37 * ARCFOUR
40 #include "krb5_locl.h"
42 static struct _krb5_key_type keytype_arcfour = {
43 ENCTYPE_ARCFOUR_HMAC_MD5,
44 "arcfour",
45 128,
46 16,
47 sizeof(struct _krb5_evp_schedule),
48 NULL,
49 _krb5_evp_schedule,
50 _krb5_arcfour_salt,
51 NULL,
52 _krb5_evp_cleanup,
53 EVP_rc4
57 * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
60 krb5_error_code
61 _krb5_HMAC_MD5_checksum(krb5_context context,
62 struct _krb5_key_data *key,
63 const void *data,
64 size_t len,
65 unsigned usage,
66 Checksum *result)
68 EVP_MD_CTX *m;
69 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
70 const char signature[] = "signaturekey";
71 Checksum ksign_c;
72 struct _krb5_key_data ksign;
73 krb5_keyblock kb;
74 unsigned char t[4];
75 unsigned char tmp[16];
76 unsigned char ksign_c_data[16];
77 krb5_error_code ret;
79 m = EVP_MD_CTX_create();
80 if (m == NULL) {
81 krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
82 return ENOMEM;
84 ksign_c.checksum.length = sizeof(ksign_c_data);
85 ksign_c.checksum.data = ksign_c_data;
86 ret = _krb5_internal_hmac(context, c, signature, sizeof(signature),
87 0, key, &ksign_c);
88 if (ret) {
89 EVP_MD_CTX_destroy(m);
90 return ret;
92 ksign.key = &kb;
93 kb.keyvalue = ksign_c.checksum;
94 EVP_DigestInit_ex(m, EVP_md5(), NULL);
95 t[0] = (usage >> 0) & 0xFF;
96 t[1] = (usage >> 8) & 0xFF;
97 t[2] = (usage >> 16) & 0xFF;
98 t[3] = (usage >> 24) & 0xFF;
99 EVP_DigestUpdate(m, t, 4);
100 EVP_DigestUpdate(m, data, len);
101 EVP_DigestFinal_ex (m, tmp, NULL);
102 EVP_MD_CTX_destroy(m);
104 ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
105 if (ret)
106 return ret;
107 return 0;
110 struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
111 CKSUMTYPE_HMAC_MD5,
112 "hmac-md5",
115 F_KEYED | F_CPROOF,
116 _krb5_HMAC_MD5_checksum,
117 NULL
121 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
123 * warning: not for small children
126 static krb5_error_code
127 ARCFOUR_subencrypt(krb5_context context,
128 struct _krb5_key_data *key,
129 void *data,
130 size_t len,
131 unsigned usage,
132 void *ivec)
134 EVP_CIPHER_CTX ctx;
135 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
136 Checksum k1_c, k2_c, k3_c, cksum;
137 struct _krb5_key_data ke;
138 krb5_keyblock kb;
139 unsigned char t[4];
140 unsigned char *cdata = data;
141 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
142 krb5_error_code ret;
144 t[0] = (usage >> 0) & 0xFF;
145 t[1] = (usage >> 8) & 0xFF;
146 t[2] = (usage >> 16) & 0xFF;
147 t[3] = (usage >> 24) & 0xFF;
149 k1_c.checksum.length = sizeof(k1_c_data);
150 k1_c.checksum.data = k1_c_data;
152 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
153 if (ret)
154 krb5_abortx(context, "hmac failed");
156 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
158 k2_c.checksum.length = sizeof(k2_c_data);
159 k2_c.checksum.data = k2_c_data;
161 ke.key = &kb;
162 kb.keyvalue = k2_c.checksum;
164 cksum.checksum.length = 16;
165 cksum.checksum.data = data;
167 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
168 if (ret)
169 krb5_abortx(context, "hmac failed");
171 ke.key = &kb;
172 kb.keyvalue = k1_c.checksum;
174 k3_c.checksum.length = sizeof(k3_c_data);
175 k3_c.checksum.data = k3_c_data;
177 ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c);
178 if (ret)
179 krb5_abortx(context, "hmac failed");
181 EVP_CIPHER_CTX_init(&ctx);
183 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 1);
184 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
185 EVP_CIPHER_CTX_cleanup(&ctx);
187 memset (k1_c_data, 0, sizeof(k1_c_data));
188 memset (k2_c_data, 0, sizeof(k2_c_data));
189 memset (k3_c_data, 0, sizeof(k3_c_data));
190 return 0;
193 static krb5_error_code
194 ARCFOUR_subdecrypt(krb5_context context,
195 struct _krb5_key_data *key,
196 void *data,
197 size_t len,
198 unsigned usage,
199 void *ivec)
201 EVP_CIPHER_CTX ctx;
202 struct _krb5_checksum_type *c = _krb5_find_checksum (CKSUMTYPE_RSA_MD5);
203 Checksum k1_c, k2_c, k3_c, cksum;
204 struct _krb5_key_data ke;
205 krb5_keyblock kb;
206 unsigned char t[4];
207 unsigned char *cdata = data;
208 unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
209 unsigned char cksum_data[16];
210 krb5_error_code ret;
212 t[0] = (usage >> 0) & 0xFF;
213 t[1] = (usage >> 8) & 0xFF;
214 t[2] = (usage >> 16) & 0xFF;
215 t[3] = (usage >> 24) & 0xFF;
217 k1_c.checksum.length = sizeof(k1_c_data);
218 k1_c.checksum.data = k1_c_data;
220 ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
221 if (ret)
222 krb5_abortx(context, "hmac failed");
224 memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
226 k2_c.checksum.length = sizeof(k2_c_data);
227 k2_c.checksum.data = k2_c_data;
229 ke.key = &kb;
230 kb.keyvalue = k1_c.checksum;
232 k3_c.checksum.length = sizeof(k3_c_data);
233 k3_c.checksum.data = k3_c_data;
235 ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
236 if (ret)
237 krb5_abortx(context, "hmac failed");
239 EVP_CIPHER_CTX_init(&ctx);
240 EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
241 EVP_Cipher(&ctx, cdata + 16, cdata + 16, len - 16);
242 EVP_CIPHER_CTX_cleanup(&ctx);
244 ke.key = &kb;
245 kb.keyvalue = k2_c.checksum;
247 cksum.checksum.length = 16;
248 cksum.checksum.data = cksum_data;
250 ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
251 if (ret)
252 krb5_abortx(context, "hmac failed");
254 memset (k1_c_data, 0, sizeof(k1_c_data));
255 memset (k2_c_data, 0, sizeof(k2_c_data));
256 memset (k3_c_data, 0, sizeof(k3_c_data));
258 if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
259 krb5_clear_error_message (context);
260 return KRB5KRB_AP_ERR_BAD_INTEGRITY;
261 } else {
262 return 0;
267 * convert the usage numbers used in
268 * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
269 * draft-brezak-win2k-krb-rc4-hmac-04.txt
272 krb5_error_code
273 _krb5_usage2arcfour(krb5_context context, unsigned *usage)
275 switch (*usage) {
276 case KRB5_KU_AS_REP_ENC_PART : /* 3 */
277 *usage = 8;
278 return 0;
279 case KRB5_KU_USAGE_SEAL : /* 22 */
280 *usage = 13;
281 return 0;
282 case KRB5_KU_USAGE_SIGN : /* 23 */
283 *usage = 15;
284 return 0;
285 case KRB5_KU_USAGE_SEQ: /* 24 */
286 *usage = 0;
287 return 0;
288 default :
289 return 0;
293 static krb5_error_code
294 ARCFOUR_encrypt(krb5_context context,
295 struct _krb5_key_data *key,
296 void *data,
297 size_t len,
298 krb5_boolean encryptp,
299 int usage,
300 void *ivec)
302 krb5_error_code ret;
303 unsigned keyusage = usage;
305 if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
306 return ret;
308 if (encryptp)
309 return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
310 else
311 return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
314 struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
315 ETYPE_ARCFOUR_HMAC_MD5,
316 "arcfour-hmac-md5",
320 &keytype_arcfour,
321 &_krb5_checksum_hmac_md5,
322 &_krb5_checksum_hmac_md5,
323 F_SPECIAL,
324 ARCFOUR_encrypt,
326 NULL