/* [<][>][^][v][top][bottom][index][help] */
1 /*
2 * Copyright (c) 1997 - 2004 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 "krb5/gsskrb5_locl.h"
35
36 RCSID("$Id$");
37
38 static OM_uint32
39 unwrap_des
40 (OM_uint32 * minor_status,
41 const gsskrb5_ctx context_handle,
42 const gss_buffer_t input_message_buffer,
43 gss_buffer_t output_message_buffer,
44 int * conf_state,
45 gss_qop_t * qop_state,
46 krb5_keyblock *key
47 )
48 {
49 u_char *p, *seq;
50 size_t len;
51 MD5_CTX md5;
52 u_char hash[16];
53 DES_key_schedule schedule;
54 DES_cblock deskey;
55 DES_cblock zero;
56 int i;
57 uint32_t seq_number;
58 size_t padlength;
59 OM_uint32 ret;
60 int cstate;
61 int cmp;
62 int token_len;
63
64 if (IS_DCE_STYLE(context_handle)) {
65 token_len = 22 + 8 + 15; /* 45 */
66 } else {
67 token_len = input_message_buffer->length;
68 }
69
70 p = input_message_buffer->value;
71 ret = _gsskrb5_verify_header (&p,
72 token_len,
73 "\x02\x01",
74 GSS_KRB5_MECHANISM);
75 if (ret)
76 return ret;
77
78 if (memcmp (p, "\x00\x00", 2) != 0)
79 return GSS_S_BAD_SIG;
80 p += 2;
81 if (memcmp (p, "\x00\x00", 2) == 0) {
82 cstate = 1;
83 } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
84 cstate = 0;
85 } else
86 return GSS_S_BAD_MIC;
87 p += 2;
88 if(conf_state != NULL)
89 *conf_state = cstate;
90 if (memcmp (p, "\xff\xff", 2) != 0)
91 return GSS_S_DEFECTIVE_TOKEN;
92 p += 2;
93 p += 16;
94
95 len = p - (u_char *)input_message_buffer->value;
96
97 if(cstate) {
98 /* decrypt data */
99 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
100
101 for (i = 0; i < sizeof(deskey); ++i)
102 deskey[i] ^= 0xf0;
103 DES_set_key_unchecked (&deskey, &schedule);
104 memset (&zero, 0, sizeof(zero));
105 DES_cbc_encrypt ((void *)p,
106 (void *)p,
107 input_message_buffer->length - len,
108 &schedule,
109 &zero,
110 DES_DECRYPT);
111
112 memset (deskey, 0, sizeof(deskey));
113 memset (&schedule, 0, sizeof(schedule));
114 }
115
116 if (IS_DCE_STYLE(context_handle)) {
117 padlength = 0;
118 } else {
119 /* check pad */
120 ret = _gssapi_verify_pad(input_message_buffer,
121 input_message_buffer->length - len,
122 &padlength);
123 if (ret)
124 return ret;
125 }
126
127 MD5_Init (&md5);
128 MD5_Update (&md5, p - 24, 8);
129 MD5_Update (&md5, p, input_message_buffer->length - len);
130 MD5_Final (hash, &md5);
131
132 memset (&zero, 0, sizeof(zero));
133 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
134 DES_set_key_unchecked (&deskey, &schedule);
135 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
136 &schedule, &zero);
137 if (memcmp (p - 8, hash, 8) != 0)
138 return GSS_S_BAD_MIC;
139
140 /* verify sequence number */
141
142 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
143
144 p -= 16;
145 DES_set_key_unchecked (&deskey, &schedule);
146 DES_cbc_encrypt ((void *)p, (void *)p, 8,
147 &schedule, (DES_cblock *)hash, DES_DECRYPT);
148
149 memset (deskey, 0, sizeof(deskey));
150 memset (&schedule, 0, sizeof(schedule));
151
152 seq = p;
153 _gsskrb5_decode_om_uint32(seq, &seq_number);
154
155 if (context_handle->more_flags & LOCAL)
156 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
157 else
158 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
159
160 if (cmp != 0) {
161 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
162 return GSS_S_BAD_MIC;
163 }
164
165 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
166 if (ret) {
167 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
168 return ret;
169 }
170
171 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
172
173 /* copy out data */
174
175 output_message_buffer->length = input_message_buffer->length
176 - len - padlength - 8;
177 output_message_buffer->value = malloc(output_message_buffer->length);
178 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
179 return GSS_S_FAILURE;
180 memcpy (output_message_buffer->value,
181 p + 24,
182 output_message_buffer->length);
183 return GSS_S_COMPLETE;
184 }
185
186 static OM_uint32
187 unwrap_des3
188 (OM_uint32 * minor_status,
189 const gsskrb5_ctx context_handle,
190 krb5_context context,
191 const gss_buffer_t input_message_buffer,
192 gss_buffer_t output_message_buffer,
193 int * conf_state,
194 gss_qop_t * qop_state,
195 krb5_keyblock *key
196 )
197 {
198 u_char *p;
199 size_t len;
200 u_char *seq;
201 krb5_data seq_data;
202 u_char cksum[20];
203 uint32_t seq_number;
204 size_t padlength;
205 OM_uint32 ret;
206 int cstate;
207 krb5_crypto crypto;
208 Checksum csum;
209 int cmp;
210 int token_len;
211
212 if (IS_DCE_STYLE(context_handle)) {
213 token_len = 34 + 8 + 15; /* 57 */
214 } else {
215 token_len = input_message_buffer->length;
216 }
217
218 p = input_message_buffer->value;
219 ret = _gsskrb5_verify_header (&p,
220 token_len,
221 "\x02\x01",
222 GSS_KRB5_MECHANISM);
223 if (ret)
224 return ret;
225
226 if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
227 return GSS_S_BAD_SIG;
228 p += 2;
229 if (memcmp (p, "\x02\x00", 2) == 0) {
230 cstate = 1;
231 } else if (memcmp (p, "\xff\xff", 2) == 0) {
232 cstate = 0;
233 } else
234 return GSS_S_BAD_MIC;
235 p += 2;
236 if(conf_state != NULL)
237 *conf_state = cstate;
238 if (memcmp (p, "\xff\xff", 2) != 0)
239 return GSS_S_DEFECTIVE_TOKEN;
240 p += 2;
241 p += 28;
242
243 len = p - (u_char *)input_message_buffer->value;
244
245 if(cstate) {
246 /* decrypt data */
247 krb5_data tmp;
248
249 ret = krb5_crypto_init(context, key,
250 ETYPE_DES3_CBC_NONE, &crypto);
251 if (ret) {
252 *minor_status = ret;
253 return GSS_S_FAILURE;
254 }
255 ret = krb5_decrypt(context, crypto, KRB5_KU_USAGE_SEAL,
256 p, input_message_buffer->length - len, &tmp);
257 krb5_crypto_destroy(context, crypto);
258 if (ret) {
259 *minor_status = ret;
260 return GSS_S_FAILURE;
261 }
262 assert (tmp.length == input_message_buffer->length - len);
263
264 memcpy (p, tmp.data, tmp.length);
265 krb5_data_free(&tmp);
266 }
267
268 if (IS_DCE_STYLE(context_handle)) {
269 padlength = 0;
270 } else {
271 /* check pad */
272 ret = _gssapi_verify_pad(input_message_buffer,
273 input_message_buffer->length - len,
274 &padlength);
275 if (ret)
276 return ret;
277 }
278
279 /* verify sequence number */
280
281 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
282
283 p -= 28;
284
285 ret = krb5_crypto_init(context, key,
286 ETYPE_DES3_CBC_NONE, &crypto);
287 if (ret) {
288 *minor_status = ret;
289 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
290 return GSS_S_FAILURE;
291 }
292 {
293 DES_cblock ivec;
294
295 memcpy(&ivec, p + 8, 8);
296 ret = krb5_decrypt_ivec (context,
297 crypto,
298 KRB5_KU_USAGE_SEQ,
299 p, 8, &seq_data,
300 &ivec);
301 }
302 krb5_crypto_destroy (context, crypto);
303 if (ret) {
304 *minor_status = ret;
305 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
306 return GSS_S_FAILURE;
307 }
308 if (seq_data.length != 8) {
309 krb5_data_free (&seq_data);
310 *minor_status = 0;
311 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
312 return GSS_S_BAD_MIC;
313 }
314
315 seq = seq_data.data;
316 _gsskrb5_decode_om_uint32(seq, &seq_number);
317
318 if (context_handle->more_flags & LOCAL)
319 cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
320 else
321 cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
322
323 krb5_data_free (&seq_data);
324 if (cmp != 0) {
325 *minor_status = 0;
326 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
327 return GSS_S_BAD_MIC;
328 }
329
330 ret = _gssapi_msg_order_check(context_handle->order, seq_number);
331 if (ret) {
332 *minor_status = 0;
333 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
334 return ret;
335 }
336
337 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
338
339 /* verify checksum */
340
341 memcpy (cksum, p + 8, 20);
342
343 memcpy (p + 20, p - 8, 8);
344
345 csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
346 csum.checksum.length = 20;
347 csum.checksum.data = cksum;
348
349 ret = krb5_crypto_init(context, key, 0, &crypto);
350 if (ret) {
351 *minor_status = ret;
352 return GSS_S_FAILURE;
353 }
354
355 ret = krb5_verify_checksum (context, crypto,
356 KRB5_KU_USAGE_SIGN,
357 p + 20,
358 input_message_buffer->length - len + 8,
359 &csum);
360 krb5_crypto_destroy (context, crypto);
361 if (ret) {
362 *minor_status = ret;
363 return GSS_S_FAILURE;
364 }
365
366 /* copy out data */
367
368 output_message_buffer->length = input_message_buffer->length
369 - len - padlength - 8;
370 output_message_buffer->value = malloc(output_message_buffer->length);
371 if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
372 return GSS_S_FAILURE;
373 memcpy (output_message_buffer->value,
374 p + 36,
375 output_message_buffer->length);
376 return GSS_S_COMPLETE;
377 }
378
379 OM_uint32 _gsskrb5_unwrap
380 (OM_uint32 * minor_status,
381 const gss_ctx_id_t context_handle,
382 const gss_buffer_t input_message_buffer,
383 gss_buffer_t output_message_buffer,
384 int * conf_state,
385 gss_qop_t * qop_state
386 )
387 {
388 krb5_keyblock *key;
389 krb5_context context;
390 OM_uint32 ret;
391 krb5_keytype keytype;
392 gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
393
394 output_message_buffer->value = NULL;
395 output_message_buffer->length = 0;
396
397 GSSAPI_KRB5_INIT (&context);
398
399 if (qop_state != NULL)
400 *qop_state = GSS_C_QOP_DEFAULT;
401 HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
402 ret = _gsskrb5i_get_token_key(ctx, context, &key);
403 HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
404 if (ret) {
405 *minor_status = ret;
406 return GSS_S_FAILURE;
407 }
408 krb5_enctype_to_keytype (context, key->keytype, &keytype);
409
410 *minor_status = 0;
411
412 switch (keytype) {
413 case KEYTYPE_DES :
414 ret = unwrap_des (minor_status, ctx,
415 input_message_buffer, output_message_buffer,
416 conf_state, qop_state, key);
417 break;
418 case KEYTYPE_DES3 :
419 ret = unwrap_des3 (minor_status, ctx, context,
420 input_message_buffer, output_message_buffer,
421 conf_state, qop_state, key);
422 break;
423 case KEYTYPE_ARCFOUR:
424 case KEYTYPE_ARCFOUR_56:
425 ret = _gssapi_unwrap_arcfour (minor_status, ctx, context,
426 input_message_buffer, output_message_buffer,
427 conf_state, qop_state, key);
428 break;
429 default :
430 ret = _gssapi_unwrap_cfx (minor_status, ctx, context,
431 input_message_buffer, output_message_buffer,
432 conf_state, qop_state, key);
433 break;
434 }
435 krb5_free_keyblock (context, key);
436 return ret;
437 }