2 * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
5 * Copyright 1993 by OpenVision Technologies, Inc.
7 * Permission to use, copy, modify, distribute, and sell this software
8 * and its documentation for any purpose is hereby granted without fee,
9 * provided that the above copyright notice appears in all copies and
10 * that both that copyright notice and this permission notice appear in
11 * supporting documentation, and that the name of OpenVision not be used
12 * in advertising or publicity pertaining to distribution of the software
13 * without specific, written prior permission. OpenVision makes no
14 * representations about the suitability of this software for any
15 * purpose. It is provided "as is" without express or implied warranty.
17 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
21 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
27 * Copyright (C) 1998 by the FundsXpress, INC.
29 * All rights reserved.
31 * Export of this software from the United States of America may require
32 * a specific license from the United States Government. It is the
33 * responsibility of any person or organization contemplating export to
34 * obtain such a license before exporting.
36 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
37 * distribute this software and its documentation for any purpose and
38 * without fee is hereby granted, provided that the above copyright
39 * notice appear in all copies and that both that copyright notice and
40 * this permission notice appear in supporting documentation, and that
41 * the name of FundsXpress. not be used in advertising or publicity pertaining
42 * to distribution of the software without specific, written prior
43 * permission. FundsXpress makes no representations about the suitability of
44 * this software for any purpose. It is provided "as is" without express
45 * or implied warranty.
47 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
52 #include "gssapiP_krb5.h"
55 static krb5_error_code
56 make_seal_token_v1 (krb5_context context
,
59 gssint_uint64
*seqnum
,
75 krb5_checksum md5cksum
;
77 /* msglen contains the message length
78 * we are signing/encrypting. tmsglen
79 * contains the length of the message
80 * we plan to write out to the token.
81 * tlen is the length of the token
82 * including header. */
83 unsigned conflen
=0, tmsglen
, tlen
, msglen
;
84 unsigned char *t
, *ptr
;
87 krb5_keyusage sign_usage
= KG_USAGE_SIGN
;
90 /* Solaris Kerberos: check for recognized signalg and sealalg */
91 KRB5_LOG0(KRB5_INFO
, "make_seal_token_v1() start\n");
94 * Because the ARCFOUR code bypasses the standard
95 * crypto interfaces, we must make sure the kernel
96 * crypto framework mechanism types are properly
99 context
->kef_cipher_mt
= get_cipher_mech_type(context
, seq
);
100 context
->kef_hash_mt
= get_hash_mech_type(context
, seq
);
101 if ((code
= init_key_kef(context
->kef_cipher_mt
, seq
))) {
104 if ((code
= init_key_kef(context
->kef_cipher_mt
, enc
))) {
109 /* create the token buffer */
110 /* Do we need confounder? */
111 if (encrypt
|| (!bigend
&& (toktype
== KG_TOK_SEAL_MSG
)))
112 conflen
= kg_confounder_size(context
, enc
);
115 if (toktype
== KG_TOK_SEAL_MSG
) {
117 case SEAL_ALG_MICROSOFT_RC4
:
118 msglen
= conflen
+ text
->length
+1;
122 /* XXX knows that des block size is 8 */
123 msglen
= (conflen
+text
->length
+8)&(~7);
124 pad
= 8-(text
->length
%8);
129 msglen
= text
->length
;
132 tlen
= g_token_size((gss_OID
) oid
, 14+cksum_size
+tmsglen
);
134 if ((t
= (unsigned char *) xmalloc(tlen
)) == NULL
)
137 /*** fill in the token */
140 g_make_token_header((gss_OID
) oid
, 14+cksum_size
+tmsglen
, &ptr
, toktype
);
143 ptr
[0] = (unsigned char) (signalg
& 0xff);
144 ptr
[1] = (unsigned char) ((signalg
>> 8) & 0xff);
146 /* 2..3 SEAL_ALG or Filler */
147 if ((toktype
== KG_TOK_SEAL_MSG
) && encrypt
) {
148 ptr
[2] = (unsigned char) (sealalg
& 0xff);
149 ptr
[3] = (unsigned char) ((sealalg
>> 8) & 0xff);
160 /* pad the plaintext, encrypt if needed, and stick it in the token */
162 /* initialize the the cksum */
164 case SGN_ALG_DES_MAC_MD5
:
166 md5cksum
.checksum_type
= CKSUMTYPE_RSA_MD5
;
168 case SGN_ALG_HMAC_SHA1_DES3_KD
:
169 md5cksum
.checksum_type
= CKSUMTYPE_HMAC_SHA1_DES3
;
171 case SGN_ALG_HMAC_MD5
:
172 md5cksum
.checksum_type
= CKSUMTYPE_HMAC_MD5_ARCFOUR
;
173 if (toktype
!= KG_TOK_SEAL_MSG
)
177 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, error2 signalg=%d\n",
182 return (GSS_S_DEFECTIVE_TOKEN
);
186 code
= krb5_c_checksum_length(context
, md5cksum
.checksum_type
, &sumlen
);
188 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, krb5_c_checksum_length() "
189 "error code=%d\n", code
);
192 md5cksum
.length
= sumlen
;
195 if ((plain
= (unsigned char *) xmalloc(msglen
? msglen
: 1)) == NULL
) {
201 if ((code
= kg_make_confounder(context
, enc
, plain
))) {
202 xfree_wrap(plain
, msglen
? msglen
: 1);
204 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, "
205 "kg_make_confounder() error code=%d\n", code
);
210 (void) memcpy(plain
+conflen
, text
->value
, text
->length
);
211 if (pad
) (void) memset(plain
+conflen
+text
->length
, pad
, pad
);
213 /* compute the checksum */
215 /* 8 = head of token body as specified by mech spec */
216 if (! (data_ptr
= (char *) xmalloc(8 +
217 (bigend
? text
->length
: msglen
)))) {
218 xfree_wrap(plain
, msglen
? msglen
: 1);
222 (void) memcpy(data_ptr
, ptr
-2, 8);
224 (void) memcpy(data_ptr
+8, text
->value
, text
->length
);
226 (void) memcpy(data_ptr
+8, plain
, msglen
);
227 plaind
.length
= 8 + (bigend
? text
->length
: msglen
);
228 plaind
.data
= data_ptr
;
229 code
= krb5_c_make_checksum(context
, md5cksum
.checksum_type
, seq
,
230 sign_usage
, &plaind
, &md5cksum
);
231 xfree_wrap(data_ptr
,8 + (bigend
? text
->length
: msglen
));
234 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, "
235 "krb5_c_make_checksum() error code=%d\n", code
);
236 xfree_wrap(plain
, msglen
? msglen
: 1);
241 case SGN_ALG_DES_MAC_MD5
:
244 if ((code
= kg_encrypt(context
, seq
, KG_USAGE_SEAL
,
245 (g_OID_equal(oid
, gss_mech_krb5_old
) ?
246 seq
->contents
: NULL
),
247 md5cksum
.contents
, md5cksum
.contents
, 16))) {
248 xfree_wrap(md5cksum
.contents
, md5cksum
.length
);
251 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, kg_encrypt() "
252 "error code=%d\n", code
);
256 cksum
.length
= cksum_size
;
257 cksum
.contents
= md5cksum
.contents
+ 16 - cksum
.length
;
259 (void) memcpy(ptr
+14, cksum
.contents
, cksum
.length
);
262 case SGN_ALG_HMAC_SHA1_DES3_KD
:
264 * Using key derivation, the call to krb5_c_make_checksum
265 * already dealt with encrypting.
267 if (md5cksum
.length
!= cksum_size
)
269 KRB5_LOG1(KRB5_ERR
, "make_seal_token_v1() end, error "
270 "md5cksum.length %u != "
272 (unsigned int)md5cksum
.length
,
273 (unsigned int) cksum_size
);
277 return (GSS_S_DEFECTIVE_TOKEN
);
280 (void) memcpy(ptr
+14, md5cksum
.contents
, md5cksum
.length
);
282 case SGN_ALG_HMAC_MD5
:
283 KRB5_LOG(KRB5_INFO
, "make_seal_token_v1() cksum_size = %u",
284 (unsigned int)cksum_size
);
285 (void) memcpy(ptr
+14, md5cksum
.contents
, cksum_size
);
289 xfree_wrap(md5cksum
.contents
, md5cksum
.length
);
291 /* create the seq_num */
292 seqnum32
= (OM_uint32
)(*seqnum
& 0xFFFFFFFF);
293 if ((code
= kg_make_seq_num(context
, seq
, direction
?0:0xff, seqnum32
,
297 KRB5_LOG(KRB5_ERR
, "make_seal_token_v1() end, kg_make_seq_num() "
298 "error code=%d\n", code
);
304 case SEAL_ALG_MICROSOFT_RC4
:
306 unsigned char bigend_seqnum
[4];
307 krb5_keyblock
*enc_key
;
309 bigend_seqnum
[0] = (*seqnum
>>24) & 0xff;
310 bigend_seqnum
[1] = (*seqnum
>>16) & 0xff;
311 bigend_seqnum
[2] = (*seqnum
>>8) & 0xff;
312 bigend_seqnum
[3] = *seqnum
& 0xff;
313 code
= krb5_copy_keyblock (context
, enc
, &enc_key
);
316 xfree_wrap(plain
, msglen
? msglen
: 1);
320 for (i
= 0; i
<= 15; i
++)
321 ((char *) enc_key
->contents
)[i
] ^=0xf0;
322 code
= kg_arcfour_docrypt (context
, enc_key
, 0,
326 krb5_free_keyblock (context
, enc_key
);
329 xfree_wrap(plain
, msglen
? msglen
: 1);
336 if ((code
= kg_encrypt(context
, enc
, KG_USAGE_SEAL
, NULL
,
337 (krb5_pointer
) plain
,
338 (krb5_pointer
) (ptr
+cksum_size
+14),
340 xfree_wrap(plain
, msglen
? msglen
: 1);
347 (void) memcpy(ptr
+14+cksum_size
, plain
, tmsglen
);
349 xfree_wrap(plain
, msglen
? msglen
: 1);
352 /* that's it. return the token */
355 *seqnum
&= (ulong_t
)0xffffffffU
;
357 token
->length
= tlen
;
358 token
->value
= (void *) t
;
360 KRB5_LOG0(KRB5_INFO
, "make_seal_token_v1() end\n");
364 /* if signonly is true, ignore conf_req, conf_state,
365 and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */
368 kg_seal(minor_status
, context_handle
, conf_req_flag
, qop_req
,
369 input_message_buffer
, conf_state
, output_message_buffer
, toktype
)
370 OM_uint32
*minor_status
;
371 gss_ctx_id_t context_handle
;
374 gss_buffer_t input_message_buffer
;
376 gss_buffer_t output_message_buffer
;
379 krb5_gss_ctx_id_rec
*ctx
;
380 krb5_error_code code
;
382 krb5_context context
;
384 KRB5_LOG0(KRB5_INFO
, "kg_seal() start");
386 output_message_buffer
->length
= 0;
387 output_message_buffer
->value
= NULL
;
389 /* Only default qop or matching established cryptosystem is allowed.
391 There are NO EXTENSIONS to this set for AES and friends! The
392 new spec says "just use 0". The old spec plus extensions would
393 actually allow for certain non-zero values. Fix this to handle
396 *minor_status
= (OM_uint32
) G_UNKNOWN_QOP
;
397 KRB5_LOG0(KRB5_ERR
, "kg_seal() end, error G_UNKNOWN_QOP\n");
398 return (GSS_S_BAD_QOP
);
401 /* validate the context handle */
402 if (! kg_validate_ctx_id(context_handle
)) {
403 *minor_status
= (OM_uint32
) G_VALIDATE_FAILED
;
404 KRB5_LOG0(KRB5_ERR
, "kg_seal() kg_validate_ctx_id() end, "
405 "error GSS_S_NO_CONTEXT\n");
406 return (GSS_S_NO_CONTEXT
);
409 ctx
= (krb5_gss_ctx_id_rec
*) context_handle
;
411 if (ctx
->subkey
== NULL
&& !ctx
->established
) {
412 *minor_status
= KG_CTX_INCOMPLETE
;
413 return(GSS_S_NO_CONTEXT
);
416 context
= ctx
->k5_context
;
417 if ((code
= krb5_timeofday(context
, &now
))) {
418 *minor_status
= code
;
419 save_error_info(*minor_status
, context
);
420 KRB5_LOG(KRB5_ERR
, "kg_seal() end, krb5_timeofday() error code=%d\n", code
);
421 return (GSS_S_FAILURE
);
427 code
= make_seal_token_v1(context
, ctx
->enc
, ctx
->seq
,
428 &ctx
->seq_send
, ctx
->initiate
,
429 input_message_buffer
, output_message_buffer
,
430 ctx
->signalg
, ctx
->cksum_size
, ctx
->sealalg
,
431 conf_req_flag
, toktype
, ctx
->big_endian
,
435 code
= gss_krb5int_make_seal_token_v3(context
, ctx
,
436 input_message_buffer
,
437 output_message_buffer
,
438 conf_req_flag
, toktype
);
441 code
= G_UNKNOWN_QOP
; /* XXX */
446 *minor_status
= code
;
447 save_error_info(*minor_status
, context
);
448 KRB5_LOG(KRB5_ERR
, "kg_seal() end, make_seal_token_v1() "
449 "error code=%d\n", code
);
450 return (GSS_S_FAILURE
);
454 *conf_state
= conf_req_flag
;
457 if (ctx
->endtime
< now
) {
458 (void) gss_release_buffer(minor_status
, output_message_buffer
);
459 KRB5_LOG(KRB5_ERR
, "kg_seal() end, error GSS_S_CONTEXT_EXPIRED "
460 "ctx->endtime = %d\n", ctx
->endtime
);
461 return (GSS_S_CONTEXT_EXPIRED
);
464 KRB5_LOG0(KRB5_INFO
, "kg_seal() end\n");
465 return (GSS_S_COMPLETE
);