1 /* $NetBSD: wrap.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
4 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "gsskrb5_locl.h"
39 * Return initiator subkey, or if that doesn't exists, the subkey.
43 _gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx
,
50 if (ctx
->more_flags
& LOCAL
) {
51 ret
= krb5_auth_con_getlocalsubkey(context
,
55 ret
= krb5_auth_con_getremotesubkey(context
,
59 if (ret
== 0 && *key
== NULL
)
60 ret
= krb5_auth_con_getkey(context
,
63 if (ret
== 0 && *key
== NULL
) {
64 krb5_set_error_message(context
, 0, "No initiator subkey available");
65 return GSS_KRB5_S_KG_NO_SUBKEY
;
71 _gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx
,
78 if (ctx
->more_flags
& LOCAL
) {
79 ret
= krb5_auth_con_getremotesubkey(context
,
83 ret
= krb5_auth_con_getlocalsubkey(context
,
87 if (ret
== 0 && *key
== NULL
) {
88 krb5_set_error_message(context
, 0, "No acceptor subkey available");
89 return GSS_KRB5_S_KG_NO_SUBKEY
;
95 _gsskrb5i_get_token_key(const gsskrb5_ctx ctx
,
99 _gsskrb5i_get_acceptor_subkey(ctx
, context
, key
);
102 * Only use the initiator subkey or ticket session key if an
103 * acceptor subkey was not required.
105 if ((ctx
->more_flags
& ACCEPTOR_SUBKEY
) == 0)
106 _gsskrb5i_get_initiator_subkey(ctx
, context
, key
);
109 krb5_set_error_message(context
, 0, "No token key available");
110 return GSS_KRB5_S_KG_NO_SUBKEY
;
117 OM_uint32 req_output_size
,
118 OM_uint32
* max_input_size
,
123 size_t len
, total_len
;
125 len
= 8 + req_output_size
+ blocksize
+ extrasize
;
127 _gsskrb5_encap_length(len
, &len
, &total_len
, GSS_KRB5_MECHANISM
);
129 total_len
-= req_output_size
; /* token length */
130 if (total_len
< req_output_size
) {
131 *max_input_size
= (req_output_size
- total_len
);
132 (*max_input_size
) &= (~(OM_uint32
)(blocksize
- 1));
136 return GSS_S_COMPLETE
;
139 OM_uint32 GSSAPI_CALLCONV
140 _gsskrb5_wrap_size_limit (
141 OM_uint32
* minor_status
,
142 const gss_ctx_id_t context_handle
,
145 OM_uint32 req_output_size
,
146 OM_uint32
* max_input_size
149 krb5_context context
;
152 krb5_keytype keytype
;
153 const gsskrb5_ctx ctx
= (const gsskrb5_ctx
) context_handle
;
155 GSSAPI_KRB5_INIT (&context
);
157 if (ctx
->more_flags
& IS_CFX
)
158 return _gssapi_wrap_size_cfx(minor_status
, ctx
, context
,
159 conf_req_flag
, qop_req
,
160 req_output_size
, max_input_size
);
162 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
163 ret
= _gsskrb5i_get_token_key(ctx
, context
, &key
);
164 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
167 return GSS_S_FAILURE
;
169 krb5_enctype_to_keytype (context
, key
->keytype
, &keytype
);
173 #ifdef HEIM_WEAK_CRYPTO
174 ret
= sub_wrap_size(req_output_size
, max_input_size
, 8, 22);
179 case ENCTYPE_ARCFOUR_HMAC_MD5
:
180 case ENCTYPE_ARCFOUR_HMAC_MD5_56
:
181 ret
= _gssapi_wrap_size_arcfour(minor_status
, ctx
, context
,
182 conf_req_flag
, qop_req
,
183 req_output_size
, max_input_size
, key
);
186 ret
= sub_wrap_size(req_output_size
, max_input_size
, 8, 34);
192 krb5_free_keyblock (context
, key
);
197 #ifdef HEIM_WEAK_CRYPTO
201 (OM_uint32
* minor_status
,
202 const gsskrb5_ctx ctx
,
203 krb5_context context
,
206 const gss_buffer_t input_message_buffer
,
208 gss_buffer_t output_message_buffer
,
215 DES_key_schedule schedule
;
216 EVP_CIPHER_CTX des_ctx
;
221 size_t len
, total_len
, padlength
, datalen
;
223 if (IS_DCE_STYLE(ctx
)) {
225 datalen
= input_message_buffer
->length
;
227 _gsskrb5_encap_length (len
, &len
, &total_len
, GSS_KRB5_MECHANISM
);
228 total_len
+= datalen
;
231 padlength
= 8 - (input_message_buffer
->length
% 8);
232 datalen
= input_message_buffer
->length
+ padlength
+ 8;
234 _gsskrb5_encap_length (len
, &len
, &total_len
, GSS_KRB5_MECHANISM
);
237 output_message_buffer
->length
= total_len
;
238 output_message_buffer
->value
= malloc (total_len
);
239 if (output_message_buffer
->value
== NULL
) {
240 output_message_buffer
->length
= 0;
241 *minor_status
= ENOMEM
;
242 return GSS_S_FAILURE
;
245 p
= _gsskrb5_make_header(output_message_buffer
->value
,
247 "\x02\x01", /* TOK_ID */
251 memcpy (p
, "\x00\x00", 2);
255 memcpy (p
, "\x00\x00", 2);
257 memcpy (p
, "\xff\xff", 2);
260 memcpy (p
, "\xff\xff", 2);
267 /* confounder + data + pad */
268 krb5_generate_random_block(p
, 8);
269 memcpy (p
+ 8, input_message_buffer
->value
,
270 input_message_buffer
->length
);
271 memset (p
+ 8 + input_message_buffer
->length
, padlength
, padlength
);
274 md5
= EVP_MD_CTX_create();
275 EVP_DigestInit_ex(md5
, EVP_md5(), NULL
);
276 EVP_DigestUpdate(md5
, p
- 24, 8);
277 EVP_DigestUpdate(md5
, p
, datalen
);
278 EVP_DigestFinal_ex(md5
, hash
, NULL
);
279 EVP_MD_CTX_destroy(md5
);
281 memset (&zero
, 0, sizeof(zero
));
282 memcpy (&deskey
, key
->keyvalue
.data
, sizeof(deskey
));
283 DES_set_key_unchecked (&deskey
, &schedule
);
284 DES_cbc_cksum ((void *)hash
, (void *)hash
, sizeof(hash
),
286 memcpy (p
- 8, hash
, 8);
288 /* sequence number */
289 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
290 krb5_auth_con_getlocalseqnumber (context
,
295 p
[0] = (seq_number
>> 0) & 0xFF;
296 p
[1] = (seq_number
>> 8) & 0xFF;
297 p
[2] = (seq_number
>> 16) & 0xFF;
298 p
[3] = (seq_number
>> 24) & 0xFF;
300 (ctx
->more_flags
& LOCAL
) ? 0 : 0xFF,
303 EVP_CIPHER_CTX_init(&des_ctx
);
304 EVP_CipherInit_ex(&des_ctx
, EVP_des_cbc(), NULL
, key
->keyvalue
.data
, p
+ 8, 1);
305 EVP_Cipher(&des_ctx
, p
, p
, 8);
306 EVP_CIPHER_CTX_cleanup(&des_ctx
);
308 krb5_auth_con_setlocalseqnumber (context
,
311 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
313 /* encrypt the data */
317 memcpy (&deskey
, key
->keyvalue
.data
, sizeof(deskey
));
319 for (i
= 0; i
< sizeof(deskey
); ++i
)
322 EVP_CIPHER_CTX_init(&des_ctx
);
323 EVP_CipherInit_ex(&des_ctx
, EVP_des_cbc(), NULL
, deskey
, zero
, 1);
324 EVP_Cipher(&des_ctx
, p
, p
, datalen
);
325 EVP_CIPHER_CTX_cleanup(&des_ctx
);
327 memset (deskey
, 0, sizeof(deskey
));
328 memset (&schedule
, 0, sizeof(schedule
));
330 if(conf_state
!= NULL
)
331 *conf_state
= conf_req_flag
;
333 return GSS_S_COMPLETE
;
340 (OM_uint32
* minor_status
,
341 const gsskrb5_ctx ctx
,
342 krb5_context context
,
345 const gss_buffer_t input_message_buffer
,
347 gss_buffer_t output_message_buffer
,
354 size_t len
, total_len
, padlength
, datalen
;
360 if (IS_DCE_STYLE(ctx
)) {
362 datalen
= input_message_buffer
->length
;
364 _gsskrb5_encap_length (len
, &len
, &total_len
, GSS_KRB5_MECHANISM
);
365 total_len
+= datalen
;
368 padlength
= 8 - (input_message_buffer
->length
% 8);
369 datalen
= input_message_buffer
->length
+ padlength
+ 8;
371 _gsskrb5_encap_length (len
, &len
, &total_len
, GSS_KRB5_MECHANISM
);
374 output_message_buffer
->length
= total_len
;
375 output_message_buffer
->value
= malloc (total_len
);
376 if (output_message_buffer
->value
== NULL
) {
377 output_message_buffer
->length
= 0;
378 *minor_status
= ENOMEM
;
379 return GSS_S_FAILURE
;
382 p
= _gsskrb5_make_header(output_message_buffer
->value
,
384 "\x02\x01", /* TOK_ID */
388 memcpy (p
, "\x04\x00", 2); /* HMAC SHA1 DES3-KD */
392 memcpy (p
, "\x02\x00", 2); /* DES3-KD */
394 memcpy (p
, "\xff\xff", 2);
397 memcpy (p
, "\xff\xff", 2);
400 /* calculate checksum (the above + confounder + data + pad) */
402 memcpy (p
+ 20, p
- 8, 8);
403 krb5_generate_random_block(p
+ 28, 8);
404 memcpy (p
+ 28 + 8, input_message_buffer
->value
,
405 input_message_buffer
->length
);
406 memset (p
+ 28 + 8 + input_message_buffer
->length
, padlength
, padlength
);
408 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
410 free (output_message_buffer
->value
);
411 output_message_buffer
->length
= 0;
412 output_message_buffer
->value
= NULL
;
414 return GSS_S_FAILURE
;
417 ret
= krb5_create_checksum (context
,
424 krb5_crypto_destroy (context
, crypto
);
426 free (output_message_buffer
->value
);
427 output_message_buffer
->length
= 0;
428 output_message_buffer
->value
= NULL
;
430 return GSS_S_FAILURE
;
433 /* zero out SND_SEQ + SGN_CKSUM in case */
436 memcpy (p
+ 8, cksum
.checksum
.data
, cksum
.checksum
.length
);
437 free_Checksum (&cksum
);
439 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
440 /* sequence number */
441 krb5_auth_con_getlocalseqnumber (context
,
445 seq
[0] = (seq_number
>> 0) & 0xFF;
446 seq
[1] = (seq_number
>> 8) & 0xFF;
447 seq
[2] = (seq_number
>> 16) & 0xFF;
448 seq
[3] = (seq_number
>> 24) & 0xFF;
450 (ctx
->more_flags
& LOCAL
) ? 0 : 0xFF,
454 ret
= krb5_crypto_init(context
, key
, ETYPE_DES3_CBC_NONE
,
457 free (output_message_buffer
->value
);
458 output_message_buffer
->length
= 0;
459 output_message_buffer
->value
= NULL
;
461 return GSS_S_FAILURE
;
467 memcpy (&ivec
, p
+ 8, 8);
468 ret
= krb5_encrypt_ivec (context
,
474 krb5_crypto_destroy (context
, crypto
);
476 free (output_message_buffer
->value
);
477 output_message_buffer
->length
= 0;
478 output_message_buffer
->value
= NULL
;
480 return GSS_S_FAILURE
;
483 assert (encdata
.length
== 8);
485 memcpy (p
, encdata
.data
, encdata
.length
);
486 krb5_data_free (&encdata
);
488 krb5_auth_con_setlocalseqnumber (context
,
491 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
493 /* encrypt the data */
499 ret
= krb5_crypto_init(context
, key
,
500 ETYPE_DES3_CBC_NONE
, &crypto
);
502 free (output_message_buffer
->value
);
503 output_message_buffer
->length
= 0;
504 output_message_buffer
->value
= NULL
;
506 return GSS_S_FAILURE
;
508 ret
= krb5_encrypt(context
, crypto
, KRB5_KU_USAGE_SEAL
,
510 krb5_crypto_destroy(context
, crypto
);
512 free (output_message_buffer
->value
);
513 output_message_buffer
->length
= 0;
514 output_message_buffer
->value
= NULL
;
516 return GSS_S_FAILURE
;
518 assert (tmp
.length
== datalen
);
520 memcpy (p
, tmp
.data
, datalen
);
521 krb5_data_free(&tmp
);
523 if(conf_state
!= NULL
)
524 *conf_state
= conf_req_flag
;
526 return GSS_S_COMPLETE
;
529 OM_uint32 GSSAPI_CALLCONV
531 (OM_uint32
* minor_status
,
532 const gss_ctx_id_t context_handle
,
535 const gss_buffer_t input_message_buffer
,
537 gss_buffer_t output_message_buffer
540 krb5_context context
;
543 krb5_keytype keytype
;
544 const gsskrb5_ctx ctx
= (const gsskrb5_ctx
) context_handle
;
546 output_message_buffer
->value
= NULL
;
547 output_message_buffer
->length
= 0;
549 GSSAPI_KRB5_INIT (&context
);
551 if (ctx
->more_flags
& IS_CFX
)
552 return _gssapi_wrap_cfx (minor_status
, ctx
, context
, conf_req_flag
,
553 input_message_buffer
, conf_state
,
554 output_message_buffer
);
556 HEIMDAL_MUTEX_lock(&ctx
->ctx_id_mutex
);
557 ret
= _gsskrb5i_get_token_key(ctx
, context
, &key
);
558 HEIMDAL_MUTEX_unlock(&ctx
->ctx_id_mutex
);
561 return GSS_S_FAILURE
;
563 krb5_enctype_to_keytype (context
, key
->keytype
, &keytype
);
567 #ifdef HEIM_WEAK_CRYPTO
568 ret
= wrap_des (minor_status
, ctx
, context
, conf_req_flag
,
569 qop_req
, input_message_buffer
, conf_state
,
570 output_message_buffer
, key
);
576 ret
= wrap_des3 (minor_status
, ctx
, context
, conf_req_flag
,
577 qop_req
, input_message_buffer
, conf_state
,
578 output_message_buffer
, key
);
580 case KEYTYPE_ARCFOUR
:
581 case KEYTYPE_ARCFOUR_56
:
582 ret
= _gssapi_wrap_arcfour (minor_status
, ctx
, context
, conf_req_flag
,
583 qop_req
, input_message_buffer
, conf_state
,
584 output_message_buffer
, key
);
590 krb5_free_keyblock (context
, key
);