2 * Copyright (c) 1997 - 2003 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
34 #include "krb5/gsskrb5_locl.h"
40 (OM_uint32
* minor_status
,
41 const gsskrb5_ctx ctx
,
44 const gss_buffer_t message_buffer
,
45 gss_buffer_t message_token
,
52 DES_key_schedule schedule
;
56 size_t len
, total_len
;
58 _gsskrb5_encap_length (22, &len
, &total_len
, GSS_KRB5_MECHANISM
);
60 message_token
->length
= total_len
;
61 message_token
->value
= malloc (total_len
);
62 if (message_token
->value
== NULL
) {
63 message_token
->length
= 0;
64 *minor_status
= ENOMEM
;
68 p
= _gsskrb5_make_header(message_token
->value
,
70 "\x01\x01", /* TOK_ID */
73 memcpy (p
, "\x00\x00", 2); /* SGN_ALG = DES MAC MD5 */
76 memcpy (p
, "\xff\xff\xff\xff", 4); /* Filler */
79 /* Fill in later (SND-SEQ) */
85 MD5_Update (&md5
, p
- 24, 8);
86 MD5_Update (&md5
, message_buffer
->value
, message_buffer
->length
);
87 MD5_Final (hash
, &md5
);
89 memset (&zero
, 0, sizeof(zero
));
90 memcpy (&deskey
, key
->keyvalue
.data
, sizeof(deskey
));
91 DES_set_key_unchecked (&deskey
, &schedule
);
92 DES_cbc_cksum ((void *)hash
, (void *)hash
, sizeof(hash
),
94 memcpy (p
- 8, hash
, 8); /* SGN_CKSUM */
96 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
98 krb5_auth_con_getlocalseqnumber (context
,
102 p
-= 16; /* SND_SEQ */
103 p
[0] = (seq_number
>> 0) & 0xFF;
104 p
[1] = (seq_number
>> 8) & 0xFF;
105 p
[2] = (seq_number
>> 16) & 0xFF;
106 p
[3] = (seq_number
>> 24) & 0xFF;
108 (ctx
->more_flags
& LOCAL
) ? 0 : 0xFF,
111 DES_set_key_unchecked (&deskey
, &schedule
);
112 DES_cbc_encrypt ((void *)p
, (void *)p
, 8,
113 &schedule
, (DES_cblock
*)(p
+ 8), DES_ENCRYPT
);
115 krb5_auth_con_setlocalseqnumber (context
,
118 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
120 memset (deskey
, 0, sizeof(deskey
));
121 memset (&schedule
, 0, sizeof(schedule
));
124 return GSS_S_COMPLETE
;
129 (OM_uint32
* minor_status
,
130 const gsskrb5_ctx ctx
,
131 krb5_context context
,
133 const gss_buffer_t message_buffer
,
134 gss_buffer_t message_token
,
143 size_t len
, total_len
;
146 krb5_error_code kret
;
151 _gsskrb5_encap_length (36, &len
, &total_len
, GSS_KRB5_MECHANISM
);
153 message_token
->length
= total_len
;
154 message_token
->value
= malloc (total_len
);
155 if (message_token
->value
== NULL
) {
156 message_token
->length
= 0;
157 *minor_status
= ENOMEM
;
158 return GSS_S_FAILURE
;
161 p
= _gsskrb5_make_header(message_token
->value
,
163 "\x01\x01", /* TOK-ID */
166 memcpy (p
, "\x04\x00", 2); /* SGN_ALG = HMAC SHA1 DES3-KD */
169 memcpy (p
, "\xff\xff\xff\xff", 4); /* filler */
172 /* this should be done in parts */
174 tmp
= malloc (message_buffer
->length
+ 8);
176 free (message_token
->value
);
177 message_token
->value
= NULL
;
178 message_token
->length
= 0;
179 *minor_status
= ENOMEM
;
180 return GSS_S_FAILURE
;
182 memcpy (tmp
, p
- 8, 8);
183 memcpy (tmp
+ 8, message_buffer
->value
, message_buffer
->length
);
185 kret
= krb5_crypto_init(context
, key
, 0, &crypto
);
187 free (message_token
->value
);
188 message_token
->value
= NULL
;
189 message_token
->length
= 0;
191 *minor_status
= kret
;
192 return GSS_S_FAILURE
;
195 kret
= krb5_create_checksum (context
,
200 message_buffer
->length
+ 8,
203 krb5_crypto_destroy (context
, crypto
);
205 free (message_token
->value
);
206 message_token
->value
= NULL
;
207 message_token
->length
= 0;
208 *minor_status
= kret
;
209 return GSS_S_FAILURE
;
212 memcpy (p
+ 8, cksum
.checksum
.data
, cksum
.checksum
.length
);
214 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
215 /* sequence number */
216 krb5_auth_con_getlocalseqnumber (context
,
220 seq
[0] = (seq_number
>> 0) & 0xFF;
221 seq
[1] = (seq_number
>> 8) & 0xFF;
222 seq
[2] = (seq_number
>> 16) & 0xFF;
223 seq
[3] = (seq_number
>> 24) & 0xFF;
225 (ctx
->more_flags
& LOCAL
) ? 0 : 0xFF,
228 kret
= krb5_crypto_init(context
, key
,
229 ETYPE_DES3_CBC_NONE
, &crypto
);
231 free (message_token
->value
);
232 message_token
->value
= NULL
;
233 message_token
->length
= 0;
234 *minor_status
= kret
;
235 return GSS_S_FAILURE
;
238 if (ctx
->more_flags
& COMPAT_OLD_DES3
)
241 memcpy(ivec
, p
+ 8, 8);
243 kret
= krb5_encrypt_ivec (context
,
246 seq
, 8, &encdata
, ivec
);
247 krb5_crypto_destroy (context
, crypto
);
249 free (message_token
->value
);
250 message_token
->value
= NULL
;
251 message_token
->length
= 0;
252 *minor_status
= kret
;
253 return GSS_S_FAILURE
;
256 assert (encdata
.length
== 8);
258 memcpy (p
, encdata
.data
, encdata
.length
);
259 krb5_data_free (&encdata
);
261 krb5_auth_con_setlocalseqnumber (context
,
264 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
266 free_Checksum (&cksum
);
268 return GSS_S_COMPLETE
;
271 OM_uint32 _gsskrb5_get_mic
272 (OM_uint32
* minor_status
,
273 const gss_ctx_id_t context_handle
,
275 const gss_buffer_t message_buffer
,
276 gss_buffer_t message_token
279 krb5_context context
;
280 const gsskrb5_ctx ctx
= (const gsskrb5_ctx
) context_handle
;
283 krb5_keytype keytype
;
285 GSSAPI_KRB5_INIT (&context
);
287 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
288 ret
= _gsskrb5i_get_token_key(ctx
, context
, &key
);
289 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
292 return GSS_S_FAILURE
;
294 krb5_enctype_to_keytype (context
, key
->keytype
, &keytype
);
298 ret
= mic_des (minor_status
, ctx
, context
, qop_req
,
299 message_buffer
, message_token
, key
);
302 ret
= mic_des3 (minor_status
, ctx
, context
, qop_req
,
303 message_buffer
, message_token
, key
);
305 case KEYTYPE_ARCFOUR
:
306 case KEYTYPE_ARCFOUR_56
:
307 ret
= _gssapi_get_mic_arcfour (minor_status
, ctx
, context
, qop_req
,
308 message_buffer
, message_token
, key
);
311 ret
= _gssapi_mic_cfx (minor_status
, ctx
, context
, qop_req
,
312 message_buffer
, message_token
, key
);
315 krb5_free_keyblock (context
, key
);