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 "gssapi_locl.h"
36 RCSID("$Id: wrap.c,v 1.31 2005/01/05 02:52:12 lukeh Exp $");
39 gsskrb5_get_initiator_subkey(OM_uint32 *minor_status,
40 gss_ctx_id_t context_handle,
44 krb5_keyblock *skey = NULL;
46 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
47 if (context_handle->more_flags & LOCAL) {
48 ret = krb5_auth_con_getlocalsubkey(gssapi_krb5_context,
49 context_handle->auth_context,
53 return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */
57 ret = krb5_auth_con_getremotesubkey(gssapi_krb5_context,
58 context_handle->auth_context,
62 return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */
66 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
67 key->length = skey->keyvalue.length;
68 key->value = malloc (key->length);
70 krb5_free_keyblock(gssapi_krb5_context, skey);
71 *minor_status = ENOMEM;
74 memcpy(key->value, skey->keyvalue.data, key->length);
75 krb5_free_keyblock(gssapi_krb5_context, skey);
80 gss_krb5_get_subkey(const gss_ctx_id_t context_handle,
83 krb5_keyblock *skey = NULL;
85 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
86 if (context_handle->more_flags & LOCAL) {
87 krb5_auth_con_getremotesubkey(gssapi_krb5_context,
88 context_handle->auth_context,
91 krb5_auth_con_getlocalsubkey(gssapi_krb5_context,
92 context_handle->auth_context,
96 * Only use the initiator subkey or ticket session key if
97 * an acceptor subkey was not required.
100 (context_handle->more_flags & ACCEPTOR_SUBKEY) == 0) {
101 if (context_handle->more_flags & LOCAL) {
102 krb5_auth_con_getlocalsubkey(gssapi_krb5_context,
103 context_handle->auth_context,
106 krb5_auth_con_getremotesubkey(gssapi_krb5_context,
107 context_handle->auth_context,
111 krb5_auth_con_getkey(gssapi_krb5_context,
112 context_handle->auth_context,
115 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
117 return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */
124 OM_uint32 req_output_size,
125 OM_uint32 * max_input_size,
130 size_t len, total_len;
132 len = 8 + req_output_size + blocksize + extrasize;
134 gssapi_krb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
136 total_len -= req_output_size; /* token length */
137 if (total_len < req_output_size) {
138 *max_input_size = (req_output_size - total_len);
139 (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
143 return GSS_S_COMPLETE;
147 gss_wrap_size_limit (
148 OM_uint32 * minor_status,
149 const gss_ctx_id_t context_handle,
152 OM_uint32 req_output_size,
153 OM_uint32 * max_input_size
158 krb5_keytype keytype;
160 ret = gss_krb5_get_subkey(context_handle, &key);
162 gssapi_krb5_set_error_string ();
164 return GSS_S_FAILURE;
166 krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
170 case KEYTYPE_ARCFOUR:
171 case KEYTYPE_ARCFOUR_56:
172 ret = sub_wrap_size(req_output_size, max_input_size, 8, 22);
175 ret = sub_wrap_size(req_output_size, max_input_size, 8, 34);
178 ret = _gssapi_wrap_size_cfx(minor_status, context_handle,
179 conf_req_flag, qop_req,
180 req_output_size, max_input_size, key);
183 krb5_free_keyblock (gssapi_krb5_context, key);
190 (OM_uint32 * minor_status,
191 const gss_ctx_id_t context_handle,
194 const gss_buffer_t input_message_buffer,
196 gss_buffer_t output_message_buffer,
203 DES_key_schedule schedule;
208 size_t len, total_len, padlength, datalen;
210 padlength = 8 - (input_message_buffer->length % 8);
211 datalen = input_message_buffer->length + padlength + 8;
213 gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
215 output_message_buffer->length = total_len;
216 output_message_buffer->value = malloc (total_len);
217 if (output_message_buffer->value == NULL) {
218 *minor_status = ENOMEM;
219 return GSS_S_FAILURE;
222 p = gssapi_krb5_make_header(output_message_buffer->value,
224 "\x02\x01", /* TOK_ID */
228 memcpy (p, "\x00\x00", 2);
232 memcpy (p, "\x00\x00", 2);
234 memcpy (p, "\xff\xff", 2);
237 memcpy (p, "\xff\xff", 2);
244 /* confounder + data + pad */
245 krb5_generate_random_block(p, 8);
246 memcpy (p + 8, input_message_buffer->value,
247 input_message_buffer->length);
248 memset (p + 8 + input_message_buffer->length, padlength, padlength);
252 MD5_Update (&md5, p - 24, 8);
253 MD5_Update (&md5, p, datalen);
254 MD5_Final (hash, &md5);
256 memset (&zero, 0, sizeof(zero));
257 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
258 DES_set_key (&deskey, &schedule);
259 DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
261 memcpy (p - 8, hash, 8);
263 /* sequence number */
264 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
265 krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
266 context_handle->auth_context,
270 p[0] = (seq_number >> 0) & 0xFF;
271 p[1] = (seq_number >> 8) & 0xFF;
272 p[2] = (seq_number >> 16) & 0xFF;
273 p[3] = (seq_number >> 24) & 0xFF;
275 (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
278 DES_set_key (&deskey, &schedule);
279 DES_cbc_encrypt ((void *)p, (void *)p, 8,
280 &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT);
282 krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
283 context_handle->auth_context,
285 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
287 /* encrypt the data */
291 memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
293 for (i = 0; i < sizeof(deskey); ++i)
295 DES_set_key (&deskey, &schedule);
296 memset (&zero, 0, sizeof(zero));
297 DES_cbc_encrypt ((void *)p,
304 memset (deskey, 0, sizeof(deskey));
305 memset (&schedule, 0, sizeof(schedule));
307 if(conf_state != NULL)
308 *conf_state = conf_req_flag;
310 return GSS_S_COMPLETE;
315 (OM_uint32 * minor_status,
316 const gss_ctx_id_t context_handle,
319 const gss_buffer_t input_message_buffer,
321 gss_buffer_t output_message_buffer,
328 size_t len, total_len, padlength, datalen;
334 padlength = 8 - (input_message_buffer->length % 8);
335 datalen = input_message_buffer->length + padlength + 8;
337 gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
339 output_message_buffer->length = total_len;
340 output_message_buffer->value = malloc (total_len);
341 if (output_message_buffer->value == NULL) {
342 *minor_status = ENOMEM;
343 return GSS_S_FAILURE;
346 p = gssapi_krb5_make_header(output_message_buffer->value,
348 "\x02\x01", /* TOK_ID */
352 memcpy (p, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */
356 memcpy (p, "\x02\x00", 2); /* DES3-KD */
358 memcpy (p, "\xff\xff", 2);
361 memcpy (p, "\xff\xff", 2);
364 /* calculate checksum (the above + confounder + data + pad) */
366 memcpy (p + 20, p - 8, 8);
367 krb5_generate_random_block(p + 28, 8);
368 memcpy (p + 28 + 8, input_message_buffer->value,
369 input_message_buffer->length);
370 memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength);
372 ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
374 gssapi_krb5_set_error_string ();
375 free (output_message_buffer->value);
377 return GSS_S_FAILURE;
380 ret = krb5_create_checksum (gssapi_krb5_context,
387 krb5_crypto_destroy (gssapi_krb5_context, crypto);
389 gssapi_krb5_set_error_string ();
390 free (output_message_buffer->value);
392 return GSS_S_FAILURE;
395 /* zero out SND_SEQ + SGN_CKSUM in case */
398 memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
399 free_Checksum (&cksum);
401 HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
402 /* sequence number */
403 krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
404 context_handle->auth_context,
407 seq[0] = (seq_number >> 0) & 0xFF;
408 seq[1] = (seq_number >> 8) & 0xFF;
409 seq[2] = (seq_number >> 16) & 0xFF;
410 seq[3] = (seq_number >> 24) & 0xFF;
412 (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
416 ret = krb5_crypto_init(gssapi_krb5_context, key, ETYPE_DES3_CBC_NONE,
419 free (output_message_buffer->value);
421 return GSS_S_FAILURE;
427 memcpy (&ivec, p + 8, 8);
428 ret = krb5_encrypt_ivec (gssapi_krb5_context,
434 krb5_crypto_destroy (gssapi_krb5_context, crypto);
436 gssapi_krb5_set_error_string ();
437 free (output_message_buffer->value);
439 return GSS_S_FAILURE;
442 assert (encdata.length == 8);
444 memcpy (p, encdata.data, encdata.length);
445 krb5_data_free (&encdata);
447 krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
448 context_handle->auth_context,
450 HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
452 /* encrypt the data */
458 ret = krb5_crypto_init(gssapi_krb5_context, key,
459 ETYPE_DES3_CBC_NONE, &crypto);
461 gssapi_krb5_set_error_string ();
462 free (output_message_buffer->value);
464 return GSS_S_FAILURE;
466 ret = krb5_encrypt(gssapi_krb5_context, crypto, KRB5_KU_USAGE_SEAL,
468 krb5_crypto_destroy(gssapi_krb5_context, crypto);
470 gssapi_krb5_set_error_string ();
471 free (output_message_buffer->value);
473 return GSS_S_FAILURE;
475 assert (tmp.length == datalen);
477 memcpy (p, tmp.data, datalen);
478 krb5_data_free(&tmp);
480 if(conf_state != NULL)
481 *conf_state = conf_req_flag;
483 return GSS_S_COMPLETE;
487 (OM_uint32 * minor_status,
488 const gss_ctx_id_t context_handle,
491 const gss_buffer_t input_message_buffer,
493 gss_buffer_t output_message_buffer
498 krb5_keytype keytype;
500 ret = gss_krb5_get_subkey(context_handle, &key);
502 gssapi_krb5_set_error_string ();
504 return GSS_S_FAILURE;
506 krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
510 ret = wrap_des (minor_status, context_handle, conf_req_flag,
511 qop_req, input_message_buffer, conf_state,
512 output_message_buffer, key);
515 ret = wrap_des3 (minor_status, context_handle, conf_req_flag,
516 qop_req, input_message_buffer, conf_state,
517 output_message_buffer, key);
519 case KEYTYPE_ARCFOUR:
520 case KEYTYPE_ARCFOUR_56:
521 ret = _gssapi_wrap_arcfour (minor_status, context_handle, conf_req_flag,
522 qop_req, input_message_buffer, conf_state,
523 output_message_buffer, key);
526 ret = _gssapi_wrap_cfx (minor_status, context_handle, conf_req_flag,
527 qop_req, input_message_buffer, conf_state,
528 output_message_buffer, key);
531 krb5_free_keyblock (gssapi_krb5_context, key);