Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/krb5/crypto-arcfour.c
34878 views
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
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
_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)
65
{
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;
76
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;
81
}
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;
89
}
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);
101
102
ret = _krb5_internal_hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
103
if (ret)
104
return ret;
105
return 0;
106
}
107
108
struct _krb5_checksum_type _krb5_checksum_hmac_md5 = {
109
CKSUMTYPE_HMAC_MD5,
110
"hmac-md5",
111
64,
112
16,
113
F_KEYED | F_CPROOF,
114
_krb5_HMAC_MD5_checksum,
115
NULL
116
};
117
118
/*
119
* section 6 of draft-brezak-win2k-krb-rc4-hmac-03
120
*
121
* warning: not for small children
122
*/
123
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)
131
{
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;
141
142
t[0] = (usage >> 0) & 0xFF;
143
t[1] = (usage >> 8) & 0xFF;
144
t[2] = (usage >> 16) & 0xFF;
145
t[3] = (usage >> 24) & 0xFF;
146
147
k1_c.checksum.length = sizeof(k1_c_data);
148
k1_c.checksum.data = k1_c_data;
149
150
ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
151
if (ret)
152
krb5_abortx(context, "hmac failed");
153
154
memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
155
156
k2_c.checksum.length = sizeof(k2_c_data);
157
k2_c.checksum.data = k2_c_data;
158
159
ke.key = &kb;
160
kb.keyvalue = k2_c.checksum;
161
162
cksum.checksum.length = 16;
163
cksum.checksum.data = data;
164
165
ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
166
if (ret)
167
krb5_abortx(context, "hmac failed");
168
169
ke.key = &kb;
170
kb.keyvalue = k1_c.checksum;
171
172
k3_c.checksum.length = sizeof(k3_c_data);
173
k3_c.checksum.data = k3_c_data;
174
175
ret = _krb5_internal_hmac(NULL, c, data, 16, 0, &ke, &k3_c);
176
if (ret)
177
krb5_abortx(context, "hmac failed");
178
179
ctx = EVP_CIPHER_CTX_new();
180
if (ctx == NULL)
181
krb5_abortx(context, "malloc failed");
182
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_free(ctx);
186
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;
191
}
192
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)
200
{
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;
211
212
t[0] = (usage >> 0) & 0xFF;
213
t[1] = (usage >> 8) & 0xFF;
214
t[2] = (usage >> 16) & 0xFF;
215
t[3] = (usage >> 24) & 0xFF;
216
217
k1_c.checksum.length = sizeof(k1_c_data);
218
k1_c.checksum.data = k1_c_data;
219
220
ret = _krb5_internal_hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
221
if (ret)
222
krb5_abortx(context, "hmac failed");
223
224
memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
225
226
k2_c.checksum.length = sizeof(k2_c_data);
227
k2_c.checksum.data = k2_c_data;
228
229
ke.key = &kb;
230
kb.keyvalue = k1_c.checksum;
231
232
k3_c.checksum.length = sizeof(k3_c_data);
233
k3_c.checksum.data = k3_c_data;
234
235
ret = _krb5_internal_hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
236
if (ret)
237
krb5_abortx(context, "hmac failed");
238
239
ctx = EVP_CIPHER_CTX_new();
240
if (ctx == NULL)
241
krb5_abortx(context, "malloc failed");
242
EVP_CipherInit_ex(ctx, EVP_rc4(), NULL, k3_c.checksum.data, NULL, 0);
243
EVP_Cipher(ctx, cdata + 16, cdata + 16, len - 16);
244
EVP_CIPHER_CTX_free(ctx);
245
246
ke.key = &kb;
247
kb.keyvalue = k2_c.checksum;
248
249
cksum.checksum.length = 16;
250
cksum.checksum.data = cksum_data;
251
252
ret = _krb5_internal_hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
253
if (ret)
254
krb5_abortx(context, "hmac failed");
255
256
memset (k1_c_data, 0, sizeof(k1_c_data));
257
memset (k2_c_data, 0, sizeof(k2_c_data));
258
memset (k3_c_data, 0, sizeof(k3_c_data));
259
260
if (ct_memcmp (cksum.checksum.data, data, 16) != 0) {
261
krb5_clear_error_message (context);
262
return KRB5KRB_AP_ERR_BAD_INTEGRITY;
263
} else {
264
return 0;
265
}
266
}
267
268
/*
269
* convert the usage numbers used in
270
* draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
271
* draft-brezak-win2k-krb-rc4-hmac-04.txt
272
*/
273
274
krb5_error_code
275
_krb5_usage2arcfour(krb5_context context, unsigned *usage)
276
{
277
switch (*usage) {
278
case KRB5_KU_AS_REP_ENC_PART : /* 3 */
279
*usage = 8;
280
return 0;
281
case KRB5_KU_USAGE_SEAL : /* 22 */
282
*usage = 13;
283
return 0;
284
case KRB5_KU_USAGE_SIGN : /* 23 */
285
*usage = 15;
286
return 0;
287
case KRB5_KU_USAGE_SEQ: /* 24 */
288
*usage = 0;
289
return 0;
290
default :
291
return 0;
292
}
293
}
294
295
static krb5_error_code
296
ARCFOUR_encrypt(krb5_context context,
297
struct _krb5_key_data *key,
298
void *data,
299
size_t len,
300
krb5_boolean encryptp,
301
int usage,
302
void *ivec)
303
{
304
krb5_error_code ret;
305
unsigned keyusage = usage;
306
307
if((ret = _krb5_usage2arcfour (context, &keyusage)) != 0)
308
return ret;
309
310
if (encryptp)
311
return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
312
else
313
return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
314
}
315
316
struct _krb5_encryption_type _krb5_enctype_arcfour_hmac_md5 = {
317
ETYPE_ARCFOUR_HMAC_MD5,
318
"arcfour-hmac-md5",
319
1,
320
1,
321
8,
322
&keytype_arcfour,
323
&_krb5_checksum_hmac_md5,
324
&_krb5_checksum_hmac_md5,
325
F_SPECIAL,
326
ARCFOUR_encrypt,
327
0,
328
NULL
329
};
330
331