Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/gssapi/krb5/arcfour.c
34923 views
1
/*
2
* Copyright (c) 2003 - 2006 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
#include "gsskrb5_locl.h"
35
36
/*
37
* Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
38
*
39
* The arcfour message have the following formats:
40
*
41
* MIC token
42
* TOK_ID[2] = 01 01
43
* SGN_ALG[2] = 11 00
44
* Filler[4]
45
* SND_SEQ[8]
46
* SGN_CKSUM[8]
47
*
48
* WRAP token
49
* TOK_ID[2] = 02 01
50
* SGN_ALG[2];
51
* SEAL_ALG[2]
52
* Filler[2]
53
* SND_SEQ[2]
54
* SGN_CKSUM[8]
55
* Confounder[8]
56
*/
57
58
/*
59
* WRAP in DCE-style have a fixed size header, the oid and length over
60
* the WRAP header is a total of
61
* GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE +
62
* GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead,
63
* remember the 2 bytes from APPL [0] SEQ).
64
*/
65
66
#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
67
#define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13
68
69
70
static krb5_error_code
71
arcfour_mic_key(krb5_context context, krb5_keyblock *key,
72
void *cksum_data, size_t cksum_size,
73
void *key6_data, size_t key6_size)
74
{
75
krb5_error_code ret;
76
77
Checksum cksum_k5;
78
krb5_keyblock key5;
79
char k5_data[16];
80
81
Checksum cksum_k6;
82
83
char T[4];
84
85
memset(T, 0, 4);
86
cksum_k5.checksum.data = k5_data;
87
cksum_k5.checksum.length = sizeof(k5_data);
88
89
if (key->keytype == ENCTYPE_ARCFOUR_HMAC_MD5_56) {
90
char L40[14] = "fortybits";
91
92
memcpy(L40 + 10, T, sizeof(T));
93
ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
94
L40, 14, 0, key, &cksum_k5);
95
memset(&k5_data[7], 0xAB, 9);
96
} else {
97
ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
98
T, 4, 0, key, &cksum_k5);
99
}
100
if (ret)
101
return ret;
102
103
key5.keytype = ENCTYPE_ARCFOUR_HMAC_MD5;
104
key5.keyvalue = cksum_k5.checksum;
105
106
cksum_k6.checksum.data = key6_data;
107
cksum_k6.checksum.length = key6_size;
108
109
return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
110
cksum_data, cksum_size, 0, &key5, &cksum_k6);
111
}
112
113
114
static krb5_error_code
115
arcfour_mic_cksum(krb5_context context,
116
krb5_keyblock *key, unsigned usage,
117
u_char *sgn_cksum, size_t sgn_cksum_sz,
118
const u_char *v1, size_t l1,
119
const void *v2, size_t l2,
120
const void *v3, size_t l3)
121
{
122
Checksum CKSUM;
123
u_char *ptr;
124
size_t len;
125
krb5_crypto crypto;
126
krb5_error_code ret;
127
128
assert(sgn_cksum_sz == 8);
129
130
len = l1 + l2 + l3;
131
132
ptr = malloc(len);
133
if (ptr == NULL)
134
return ENOMEM;
135
136
memcpy(ptr, v1, l1);
137
memcpy(ptr + l1, v2, l2);
138
memcpy(ptr + l1 + l2, v3, l3);
139
140
ret = krb5_crypto_init(context, key, 0, &crypto);
141
if (ret) {
142
free(ptr);
143
return ret;
144
}
145
146
ret = krb5_create_checksum(context,
147
crypto,
148
usage,
149
0,
150
ptr, len,
151
&CKSUM);
152
free(ptr);
153
if (ret == 0) {
154
memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
155
free_Checksum(&CKSUM);
156
}
157
krb5_crypto_destroy(context, crypto);
158
159
return ret;
160
}
161
162
163
OM_uint32
164
_gssapi_get_mic_arcfour(OM_uint32 * minor_status,
165
const gsskrb5_ctx context_handle,
166
krb5_context context,
167
gss_qop_t qop_req,
168
const gss_buffer_t message_buffer,
169
gss_buffer_t message_token,
170
krb5_keyblock *key)
171
{
172
krb5_error_code ret;
173
int32_t seq_number;
174
size_t len, total_len;
175
u_char k6_data[16], *p0, *p;
176
EVP_CIPHER_CTX *rc4_key;
177
178
_gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
179
180
message_token->length = total_len;
181
message_token->value = malloc (total_len);
182
if (message_token->value == NULL) {
183
*minor_status = ENOMEM;
184
return GSS_S_FAILURE;
185
}
186
187
p0 = _gssapi_make_mech_header(message_token->value,
188
len,
189
GSS_KRB5_MECHANISM);
190
p = p0;
191
192
*p++ = 0x01; /* TOK_ID */
193
*p++ = 0x01;
194
*p++ = 0x11; /* SGN_ALG */
195
*p++ = 0x00;
196
*p++ = 0xff; /* Filler */
197
*p++ = 0xff;
198
*p++ = 0xff;
199
*p++ = 0xff;
200
201
p = NULL;
202
203
ret = arcfour_mic_cksum(context,
204
key, KRB5_KU_USAGE_SIGN,
205
p0 + 16, 8, /* SGN_CKSUM */
206
p0, 8, /* TOK_ID, SGN_ALG, Filer */
207
message_buffer->value, message_buffer->length,
208
NULL, 0);
209
if (ret) {
210
_gsskrb5_release_buffer(minor_status, message_token);
211
*minor_status = ret;
212
return GSS_S_FAILURE;
213
}
214
215
ret = arcfour_mic_key(context, key,
216
p0 + 16, 8, /* SGN_CKSUM */
217
k6_data, sizeof(k6_data));
218
if (ret) {
219
_gsskrb5_release_buffer(minor_status, message_token);
220
*minor_status = ret;
221
return GSS_S_FAILURE;
222
}
223
224
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
225
krb5_auth_con_getlocalseqnumber (context,
226
context_handle->auth_context,
227
&seq_number);
228
p = p0 + 8; /* SND_SEQ */
229
_gsskrb5_encode_be_om_uint32(seq_number, p);
230
231
krb5_auth_con_setlocalseqnumber (context,
232
context_handle->auth_context,
233
++seq_number);
234
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
235
236
memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
237
238
rc4_key = EVP_CIPHER_CTX_new();
239
if (rc4_key == NULL) {
240
_gsskrb5_release_buffer(minor_status, message_token);
241
*minor_status = ENOMEM;
242
return GSS_S_FAILURE;
243
}
244
245
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
246
EVP_Cipher(rc4_key, p, p, 8);
247
EVP_CIPHER_CTX_free(rc4_key);
248
249
memset(k6_data, 0, sizeof(k6_data));
250
251
*minor_status = 0;
252
return GSS_S_COMPLETE;
253
}
254
255
256
OM_uint32
257
_gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
258
const gsskrb5_ctx context_handle,
259
krb5_context context,
260
const gss_buffer_t message_buffer,
261
const gss_buffer_t token_buffer,
262
gss_qop_t * qop_state,
263
krb5_keyblock *key,
264
const char *type)
265
{
266
krb5_error_code ret;
267
uint32_t seq_number;
268
OM_uint32 omret;
269
u_char SND_SEQ[8], cksum_data[8], *p;
270
char k6_data[16];
271
int cmp;
272
273
if (qop_state)
274
*qop_state = 0;
275
276
p = token_buffer->value;
277
omret = _gsskrb5_verify_header (&p,
278
token_buffer->length,
279
type,
280
GSS_KRB5_MECHANISM);
281
if (omret)
282
return omret;
283
284
if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
285
return GSS_S_BAD_SIG;
286
p += 2;
287
if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
288
return GSS_S_BAD_MIC;
289
p += 4;
290
291
ret = arcfour_mic_cksum(context,
292
key, KRB5_KU_USAGE_SIGN,
293
cksum_data, sizeof(cksum_data),
294
p - 8, 8,
295
message_buffer->value, message_buffer->length,
296
NULL, 0);
297
if (ret) {
298
*minor_status = ret;
299
return GSS_S_FAILURE;
300
}
301
302
ret = arcfour_mic_key(context, key,
303
cksum_data, sizeof(cksum_data),
304
k6_data, sizeof(k6_data));
305
if (ret) {
306
*minor_status = ret;
307
return GSS_S_FAILURE;
308
}
309
310
cmp = (ct_memcmp(cksum_data, p + 8, 8) != 0);
311
if (cmp) {
312
*minor_status = 0;
313
return GSS_S_BAD_MIC;
314
}
315
316
{
317
EVP_CIPHER_CTX *rc4_key;
318
319
rc4_key = EVP_CIPHER_CTX_new();
320
if (rc4_key == NULL) {
321
*minor_status = ENOMEM;
322
return GSS_S_FAILURE;
323
}
324
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, (void *)k6_data, NULL, 0);
325
EVP_Cipher(rc4_key, SND_SEQ, p, 8);
326
EVP_CIPHER_CTX_free(rc4_key);
327
328
memset(k6_data, 0, sizeof(k6_data));
329
}
330
331
_gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
332
333
if (context_handle->more_flags & LOCAL)
334
cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
335
else
336
cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
337
338
memset(SND_SEQ, 0, sizeof(SND_SEQ));
339
if (cmp != 0) {
340
*minor_status = 0;
341
return GSS_S_BAD_MIC;
342
}
343
344
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
345
omret = _gssapi_msg_order_check(context_handle->order, seq_number);
346
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
347
if (omret)
348
return omret;
349
350
*minor_status = 0;
351
return GSS_S_COMPLETE;
352
}
353
354
OM_uint32
355
_gssapi_wrap_arcfour(OM_uint32 * minor_status,
356
const gsskrb5_ctx context_handle,
357
krb5_context context,
358
int conf_req_flag,
359
gss_qop_t qop_req,
360
const gss_buffer_t input_message_buffer,
361
int * conf_state,
362
gss_buffer_t output_message_buffer,
363
krb5_keyblock *key)
364
{
365
u_char Klocaldata[16], k6_data[16], *p, *p0;
366
size_t len, total_len, datalen;
367
krb5_keyblock Klocal;
368
krb5_error_code ret;
369
int32_t seq_number;
370
371
if (conf_state)
372
*conf_state = 0;
373
374
datalen = input_message_buffer->length;
375
376
if (IS_DCE_STYLE(context_handle)) {
377
len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
378
_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
379
total_len += datalen;
380
} else {
381
datalen += 1; /* padding */
382
len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
383
_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
384
}
385
386
output_message_buffer->length = total_len;
387
output_message_buffer->value = malloc (total_len);
388
if (output_message_buffer->value == NULL) {
389
*minor_status = ENOMEM;
390
return GSS_S_FAILURE;
391
}
392
393
p0 = _gssapi_make_mech_header(output_message_buffer->value,
394
len,
395
GSS_KRB5_MECHANISM);
396
p = p0;
397
398
*p++ = 0x02; /* TOK_ID */
399
*p++ = 0x01;
400
*p++ = 0x11; /* SGN_ALG */
401
*p++ = 0x00;
402
if (conf_req_flag) {
403
*p++ = 0x10; /* SEAL_ALG */
404
*p++ = 0x00;
405
} else {
406
*p++ = 0xff; /* SEAL_ALG */
407
*p++ = 0xff;
408
}
409
*p++ = 0xff; /* Filler */
410
*p++ = 0xff;
411
412
p = NULL;
413
414
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
415
krb5_auth_con_getlocalseqnumber (context,
416
context_handle->auth_context,
417
&seq_number);
418
419
_gsskrb5_encode_be_om_uint32(seq_number, p0 + 8);
420
421
krb5_auth_con_setlocalseqnumber (context,
422
context_handle->auth_context,
423
++seq_number);
424
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
425
426
memset (p0 + 8 + 4,
427
(context_handle->more_flags & LOCAL) ? 0 : 0xff,
428
4);
429
430
krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
431
432
/* p points to data */
433
p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
434
memcpy(p, input_message_buffer->value, input_message_buffer->length);
435
436
if (!IS_DCE_STYLE(context_handle))
437
p[input_message_buffer->length] = 1; /* padding */
438
439
ret = arcfour_mic_cksum(context,
440
key, KRB5_KU_USAGE_SEAL,
441
p0 + 16, 8, /* SGN_CKSUM */
442
p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
443
p0 + 24, 8, /* Confounder */
444
p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
445
datalen);
446
if (ret) {
447
*minor_status = ret;
448
_gsskrb5_release_buffer(minor_status, output_message_buffer);
449
return GSS_S_FAILURE;
450
}
451
452
{
453
int i;
454
455
Klocal.keytype = key->keytype;
456
Klocal.keyvalue.data = Klocaldata;
457
Klocal.keyvalue.length = sizeof(Klocaldata);
458
459
for (i = 0; i < 16; i++)
460
Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
461
}
462
ret = arcfour_mic_key(context, &Klocal,
463
p0 + 8, 4, /* SND_SEQ */
464
k6_data, sizeof(k6_data));
465
memset(Klocaldata, 0, sizeof(Klocaldata));
466
if (ret) {
467
_gsskrb5_release_buffer(minor_status, output_message_buffer);
468
*minor_status = ret;
469
return GSS_S_FAILURE;
470
}
471
472
473
if(conf_req_flag) {
474
EVP_CIPHER_CTX *rc4_key;
475
476
rc4_key = EVP_CIPHER_CTX_new();
477
if (rc4_key == NULL) {
478
_gsskrb5_release_buffer(minor_status, output_message_buffer);
479
*minor_status = ENOMEM;
480
return GSS_S_FAILURE;
481
}
482
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
483
EVP_Cipher(rc4_key, p0 + 24, p0 + 24, 8 + datalen);
484
EVP_CIPHER_CTX_free(rc4_key);
485
}
486
memset(k6_data, 0, sizeof(k6_data));
487
488
ret = arcfour_mic_key(context, key,
489
p0 + 16, 8, /* SGN_CKSUM */
490
k6_data, sizeof(k6_data));
491
if (ret) {
492
_gsskrb5_release_buffer(minor_status, output_message_buffer);
493
*minor_status = ret;
494
return GSS_S_FAILURE;
495
}
496
497
{
498
EVP_CIPHER_CTX *rc4_key;
499
500
rc4_key = EVP_CIPHER_CTX_new();
501
if (rc4_key == NULL) {
502
_gsskrb5_release_buffer(minor_status, output_message_buffer);
503
*minor_status = ENOMEM;
504
return GSS_S_FAILURE;
505
}
506
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
507
EVP_Cipher(rc4_key, p0 + 8, p0 + 8 /* SND_SEQ */, 8);
508
EVP_CIPHER_CTX_free(rc4_key);
509
memset(k6_data, 0, sizeof(k6_data));
510
}
511
512
if (conf_state)
513
*conf_state = conf_req_flag;
514
515
*minor_status = 0;
516
return GSS_S_COMPLETE;
517
}
518
519
OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
520
const gsskrb5_ctx context_handle,
521
krb5_context context,
522
const gss_buffer_t input_message_buffer,
523
gss_buffer_t output_message_buffer,
524
int *conf_state,
525
gss_qop_t *qop_state,
526
krb5_keyblock *key)
527
{
528
u_char Klocaldata[16];
529
krb5_keyblock Klocal;
530
krb5_error_code ret;
531
uint32_t seq_number;
532
size_t datalen;
533
OM_uint32 omret;
534
u_char k6_data[16], SND_SEQ[8], Confounder[8];
535
u_char cksum_data[8];
536
u_char *p, *p0;
537
int cmp;
538
int conf_flag;
539
size_t padlen = 0, len;
540
541
if (conf_state)
542
*conf_state = 0;
543
if (qop_state)
544
*qop_state = 0;
545
546
p0 = input_message_buffer->value;
547
548
if (IS_DCE_STYLE(context_handle)) {
549
len = GSS_ARCFOUR_WRAP_TOKEN_SIZE +
550
GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE;
551
if (input_message_buffer->length < len)
552
return GSS_S_BAD_MECH;
553
} else {
554
len = input_message_buffer->length;
555
}
556
557
omret = _gssapi_verify_mech_header(&p0,
558
len,
559
GSS_KRB5_MECHANISM);
560
if (omret)
561
return omret;
562
563
/* length of mech header */
564
len = (p0 - (u_char *)input_message_buffer->value) +
565
GSS_ARCFOUR_WRAP_TOKEN_SIZE;
566
567
if (len > input_message_buffer->length)
568
return GSS_S_BAD_MECH;
569
570
/* length of data */
571
datalen = input_message_buffer->length - len;
572
573
p = p0;
574
575
if (memcmp(p, "\x02\x01", 2) != 0)
576
return GSS_S_BAD_SIG;
577
p += 2;
578
if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
579
return GSS_S_BAD_SIG;
580
p += 2;
581
582
if (memcmp (p, "\x10\x00", 2) == 0)
583
conf_flag = 1;
584
else if (memcmp (p, "\xff\xff", 2) == 0)
585
conf_flag = 0;
586
else
587
return GSS_S_BAD_SIG;
588
589
p += 2;
590
if (memcmp (p, "\xff\xff", 2) != 0)
591
return GSS_S_BAD_MIC;
592
p = NULL;
593
594
ret = arcfour_mic_key(context, key,
595
p0 + 16, 8, /* SGN_CKSUM */
596
k6_data, sizeof(k6_data));
597
if (ret) {
598
*minor_status = ret;
599
return GSS_S_FAILURE;
600
}
601
602
{
603
EVP_CIPHER_CTX *rc4_key;
604
605
rc4_key = EVP_CIPHER_CTX_new();
606
if (rc4_key == NULL) {
607
*minor_status = ENOMEM;
608
return GSS_S_FAILURE;
609
}
610
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
611
EVP_Cipher(rc4_key, SND_SEQ, p0 + 8, 8);
612
EVP_CIPHER_CTX_free(rc4_key);
613
memset(k6_data, 0, sizeof(k6_data));
614
}
615
616
_gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number);
617
618
if (context_handle->more_flags & LOCAL)
619
cmp = (ct_memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4) != 0);
620
else
621
cmp = (ct_memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4) != 0);
622
623
if (cmp != 0) {
624
*minor_status = 0;
625
return GSS_S_BAD_MIC;
626
}
627
628
{
629
int i;
630
631
Klocal.keytype = key->keytype;
632
Klocal.keyvalue.data = Klocaldata;
633
Klocal.keyvalue.length = sizeof(Klocaldata);
634
635
for (i = 0; i < 16; i++)
636
Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
637
}
638
ret = arcfour_mic_key(context, &Klocal,
639
SND_SEQ, 4,
640
k6_data, sizeof(k6_data));
641
memset(Klocaldata, 0, sizeof(Klocaldata));
642
if (ret) {
643
*minor_status = ret;
644
return GSS_S_FAILURE;
645
}
646
647
output_message_buffer->value = malloc(datalen);
648
if (output_message_buffer->value == NULL) {
649
*minor_status = ENOMEM;
650
return GSS_S_FAILURE;
651
}
652
output_message_buffer->length = datalen;
653
654
if(conf_flag) {
655
EVP_CIPHER_CTX *rc4_key;
656
657
rc4_key = EVP_CIPHER_CTX_new();
658
if (rc4_key == NULL) {
659
_gsskrb5_release_buffer(minor_status, output_message_buffer);
660
*minor_status = ENOMEM;
661
return GSS_S_FAILURE;
662
}
663
EVP_CipherInit_ex(rc4_key, EVP_rc4(), NULL, k6_data, NULL, 1);
664
EVP_Cipher(rc4_key, Confounder, p0 + 24, 8);
665
EVP_Cipher(rc4_key, output_message_buffer->value, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, datalen);
666
EVP_CIPHER_CTX_free(rc4_key);
667
} else {
668
memcpy(Confounder, p0 + 24, 8); /* Confounder */
669
memcpy(output_message_buffer->value,
670
p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
671
datalen);
672
}
673
memset(k6_data, 0, sizeof(k6_data));
674
675
if (!IS_DCE_STYLE(context_handle)) {
676
ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
677
if (ret) {
678
_gsskrb5_release_buffer(minor_status, output_message_buffer);
679
*minor_status = 0;
680
return ret;
681
}
682
output_message_buffer->length -= padlen;
683
}
684
685
ret = arcfour_mic_cksum(context,
686
key, KRB5_KU_USAGE_SEAL,
687
cksum_data, sizeof(cksum_data),
688
p0, 8,
689
Confounder, sizeof(Confounder),
690
output_message_buffer->value,
691
output_message_buffer->length + padlen);
692
if (ret) {
693
_gsskrb5_release_buffer(minor_status, output_message_buffer);
694
*minor_status = ret;
695
return GSS_S_FAILURE;
696
}
697
698
cmp = (ct_memcmp(cksum_data, p0 + 16, 8) != 0); /* SGN_CKSUM */
699
if (cmp) {
700
_gsskrb5_release_buffer(minor_status, output_message_buffer);
701
*minor_status = 0;
702
return GSS_S_BAD_MIC;
703
}
704
705
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
706
omret = _gssapi_msg_order_check(context_handle->order, seq_number);
707
HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
708
if (omret)
709
return omret;
710
711
if (conf_state)
712
*conf_state = conf_flag;
713
714
*minor_status = 0;
715
return GSS_S_COMPLETE;
716
}
717
718
static OM_uint32
719
max_wrap_length_arcfour(const gsskrb5_ctx ctx,
720
krb5_crypto crypto,
721
size_t input_length,
722
OM_uint32 *max_input_size)
723
{
724
/*
725
* if GSS_C_DCE_STYLE is in use:
726
* - we only need to encapsulate the WRAP token
727
* However, since this is a fixed since, we just
728
*/
729
if (IS_DCE_STYLE(ctx)) {
730
size_t len, total_len;
731
732
len = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
733
_gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
734
735
if (input_length < len)
736
*max_input_size = 0;
737
else
738
*max_input_size = input_length - len;
739
740
} else {
741
size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE;
742
size_t blocksize = 8;
743
size_t len, total_len;
744
745
len = 8 + input_length + blocksize + extrasize;
746
747
_gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
748
749
total_len -= input_length; /* token length */
750
if (total_len < input_length) {
751
*max_input_size = (input_length - total_len);
752
(*max_input_size) &= (~(OM_uint32)(blocksize - 1));
753
} else {
754
*max_input_size = 0;
755
}
756
}
757
758
return GSS_S_COMPLETE;
759
}
760
761
OM_uint32
762
_gssapi_wrap_size_arcfour(OM_uint32 *minor_status,
763
const gsskrb5_ctx ctx,
764
krb5_context context,
765
int conf_req_flag,
766
gss_qop_t qop_req,
767
OM_uint32 req_output_size,
768
OM_uint32 *max_input_size,
769
krb5_keyblock *key)
770
{
771
krb5_error_code ret;
772
krb5_crypto crypto;
773
774
ret = krb5_crypto_init(context, key, 0, &crypto);
775
if (ret != 0) {
776
*minor_status = ret;
777
return GSS_S_FAILURE;
778
}
779
780
ret = max_wrap_length_arcfour(ctx, crypto,
781
req_output_size, max_input_size);
782
if (ret != 0) {
783
*minor_status = ret;
784
krb5_crypto_destroy(context, crypto);
785
return GSS_S_FAILURE;
786
}
787
788
krb5_crypto_destroy(context, crypto);
789
790
return GSS_S_COMPLETE;
791
}
792
793