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
,
61 struct _krb5_key_data
*key
,
63 const struct krb5_crypto_iov
*iov
,
68 struct _krb5_checksum_type
*c
= _krb5_find_checksum (CKSUMTYPE_RSA_MD5
);
69 const char signature
[] = "signaturekey";
71 struct _krb5_key_data ksign
;
74 unsigned char tmp
[16];
75 unsigned char ksign_c_data
[16];
80 if (crypto
->mdctx
== NULL
)
81 crypto
->mdctx
= EVP_MD_CTX_create();
82 if (crypto
->mdctx
== NULL
)
83 return krb5_enomem(context
);
86 m
= EVP_MD_CTX_create();
88 ksign_c
.checksum
.length
= sizeof(ksign_c_data
);
89 ksign_c
.checksum
.data
= ksign_c_data
;
90 ret
= _krb5_internal_hmac(context
, crypto
, c
, signature
, sizeof(signature
),
96 kb
.keyvalue
= ksign_c
.checksum
;
97 EVP_DigestInit_ex(m
, EVP_md5(), NULL
);
98 t
[0] = (usage
>> 0) & 0xFF;
99 t
[1] = (usage
>> 8) & 0xFF;
100 t
[2] = (usage
>> 16) & 0xFF;
101 t
[3] = (usage
>> 24) & 0xFF;
102 EVP_DigestUpdate(m
, t
, 4);
103 for (i
= 0; i
< niov
; i
++) {
104 if (_krb5_crypto_iov_should_sign(&iov
[i
]))
105 EVP_DigestUpdate(m
, iov
[i
].data
.data
, iov
[i
].data
.length
);
107 EVP_DigestFinal_ex (m
, tmp
, NULL
);
109 ret
= _krb5_internal_hmac(context
, crypto
, c
, tmp
, sizeof(tmp
), 0, &ksign
, result
);
112 EVP_MD_CTX_destroy(m
);
117 struct _krb5_checksum_type _krb5_checksum_hmac_md5
= {
123 _krb5_HMAC_MD5_checksum
,
128 * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
130 * warning: not for small children
133 static krb5_error_code
134 ARCFOUR_subencrypt(krb5_context context
,
135 struct _krb5_key_data
*key
,
142 struct _krb5_checksum_type
*c
= _krb5_find_checksum (CKSUMTYPE_RSA_MD5
);
143 Checksum k1_c
, k2_c
, k3_c
, cksum
;
144 struct _krb5_key_data ke
;
147 unsigned char *cdata
= data
;
148 unsigned char k1_c_data
[16], k2_c_data
[16], k3_c_data
[16];
152 return KRB5KRB_AP_ERR_INAPP_CKSUM
;
155 t
[0] = (usage
>> 0) & 0xFF;
156 t
[1] = (usage
>> 8) & 0xFF;
157 t
[2] = (usage
>> 16) & 0xFF;
158 t
[3] = (usage
>> 24) & 0xFF;
160 k1_c
.checksum
.length
= sizeof(k1_c_data
);
161 k1_c
.checksum
.data
= k1_c_data
;
163 ret
= _krb5_internal_hmac(context
, NULL
, c
, t
, sizeof(t
), 0, key
, &k1_c
);
165 krb5_abortx(context
, "hmac failed");
167 memcpy (k2_c_data
, k1_c_data
, sizeof(k1_c_data
));
169 k2_c
.checksum
.length
= sizeof(k2_c_data
);
170 k2_c
.checksum
.data
= k2_c_data
;
173 kb
.keyvalue
= k2_c
.checksum
;
175 cksum
.checksum
.length
= 16;
176 cksum
.checksum
.data
= data
;
178 ret
= _krb5_internal_hmac(context
, NULL
, c
, cdata
+ 16, len
- 16, 0, &ke
, &cksum
);
180 krb5_abortx(context
, "hmac failed");
183 kb
.keyvalue
= k1_c
.checksum
;
185 k3_c
.checksum
.length
= sizeof(k3_c_data
);
186 k3_c
.checksum
.data
= k3_c_data
;
188 ret
= _krb5_internal_hmac(context
, NULL
, c
, data
, 16, 0, &ke
, &k3_c
);
190 krb5_abortx(context
, "hmac failed");
192 EVP_CIPHER_CTX_init(&ctx
);
194 EVP_CipherInit_ex(&ctx
, EVP_rc4(), NULL
, k3_c
.checksum
.data
, NULL
, 1);
195 EVP_Cipher(&ctx
, cdata
+ 16, cdata
+ 16, len
- 16);
196 EVP_CIPHER_CTX_cleanup(&ctx
);
198 memset_s(k1_c_data
, sizeof(k1_c_data
), 0, sizeof(k1_c_data
));
199 memset_s(k2_c_data
, sizeof(k2_c_data
), 0, sizeof(k2_c_data
));
200 memset_s(k3_c_data
, sizeof(k3_c_data
), 0, sizeof(k3_c_data
));
204 static krb5_error_code
205 ARCFOUR_subdecrypt(krb5_context context
,
206 struct _krb5_key_data
*key
,
213 struct _krb5_checksum_type
*c
= _krb5_find_checksum (CKSUMTYPE_RSA_MD5
);
214 Checksum k1_c
, k2_c
, k3_c
, cksum
;
215 struct _krb5_key_data ke
;
218 unsigned char *cdata
= data
;
219 unsigned char k1_c_data
[16], k2_c_data
[16], k3_c_data
[16];
220 unsigned char cksum_data
[16];
224 return KRB5KRB_AP_ERR_INAPP_CKSUM
;
227 t
[0] = (usage
>> 0) & 0xFF;
228 t
[1] = (usage
>> 8) & 0xFF;
229 t
[2] = (usage
>> 16) & 0xFF;
230 t
[3] = (usage
>> 24) & 0xFF;
232 k1_c
.checksum
.length
= sizeof(k1_c_data
);
233 k1_c
.checksum
.data
= k1_c_data
;
235 ret
= _krb5_internal_hmac(context
, NULL
, c
, t
, sizeof(t
), 0, key
, &k1_c
);
237 krb5_abortx(context
, "hmac failed");
239 memcpy (k2_c_data
, k1_c_data
, sizeof(k1_c_data
));
241 k2_c
.checksum
.length
= sizeof(k2_c_data
);
242 k2_c
.checksum
.data
= k2_c_data
;
245 kb
.keyvalue
= k1_c
.checksum
;
247 k3_c
.checksum
.length
= sizeof(k3_c_data
);
248 k3_c
.checksum
.data
= k3_c_data
;
250 ret
= _krb5_internal_hmac(context
, NULL
, c
, cdata
, 16, 0, &ke
, &k3_c
);
252 krb5_abortx(context
, "hmac failed");
254 EVP_CIPHER_CTX_init(&ctx
);
255 EVP_CipherInit_ex(&ctx
, EVP_rc4(), NULL
, k3_c
.checksum
.data
, NULL
, 0);
256 EVP_Cipher(&ctx
, cdata
+ 16, cdata
+ 16, len
- 16);
257 EVP_CIPHER_CTX_cleanup(&ctx
);
260 kb
.keyvalue
= k2_c
.checksum
;
262 cksum
.checksum
.length
= 16;
263 cksum
.checksum
.data
= cksum_data
;
265 ret
= _krb5_internal_hmac(context
, NULL
, c
, cdata
+ 16, len
- 16, 0, &ke
, &cksum
);
267 krb5_abortx(context
, "hmac failed");
269 memset_s(k1_c_data
, sizeof(k1_c_data
), 0, sizeof(k1_c_data
));
270 memset_s(k2_c_data
, sizeof(k2_c_data
), 0, sizeof(k2_c_data
));
271 memset_s(k3_c_data
, sizeof(k3_c_data
), 0, sizeof(k3_c_data
));
273 if (ct_memcmp (cksum
.checksum
.data
, data
, 16) != 0) {
274 krb5_clear_error_message (context
);
275 return KRB5KRB_AP_ERR_BAD_INTEGRITY
;
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
287 KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
288 _krb5_usage2arcfour(krb5_context context
, unsigned *usage
)
291 case KRB5_KU_AS_REP_ENC_PART
: /* 3 */
294 case KRB5_KU_USAGE_SEAL
: /* 22 */
297 case KRB5_KU_USAGE_SIGN
: /* 23 */
300 case KRB5_KU_USAGE_SEQ
: /* 24 */
308 static krb5_error_code
309 ARCFOUR_encrypt(krb5_context context
,
310 struct _krb5_key_data
*key
,
313 krb5_boolean encryptp
,
318 unsigned keyusage
= usage
;
320 if((ret
= _krb5_usage2arcfour (context
, &keyusage
)) != 0)
324 return ARCFOUR_subencrypt (context
, key
, data
, len
, keyusage
, ivec
);
326 return ARCFOUR_subdecrypt (context
, key
, data
, len
, keyusage
, ivec
);
329 static krb5_error_code
330 ARCFOUR_prf(krb5_context context
,
335 struct _krb5_checksum_type
*c
= _krb5_find_checksum(CKSUMTYPE_SHA1
);
339 ret
= krb5_data_alloc(out
, c
->checksumsize
);
343 res
.checksum
.data
= out
->data
;
344 res
.checksum
.length
= out
->length
;
346 ret
= _krb5_internal_hmac(context
, crypto
, c
, in
->data
, in
->length
, 0, &crypto
->key
, &res
);
353 struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5
= {
354 ETYPE_ARCFOUR_HMAC_MD5
,
361 &_krb5_checksum_hmac_md5
,
362 &_krb5_checksum_hmac_md5
,