17c478bd9Sstevel@tonic-gate /*
2*5e01956fSGlenn Barry  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate  */
47c478bd9Sstevel@tonic-gate /*
57c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
6159d09a2SMark Phalan  *
77c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
87c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
97c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
107c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
117c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
127c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
137c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
147c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
157c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
16159d09a2SMark Phalan  *
177c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
187c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
197c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
207c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
217c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
227c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
237c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
287c478bd9Sstevel@tonic-gate  *
297c478bd9Sstevel@tonic-gate  * All rights reserved.
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
327c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
337c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
347c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
377c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
387c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
397c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
407c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
417c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
427c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
437c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
447c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
457c478bd9Sstevel@tonic-gate  * or implied warranty.
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
487c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
497c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
507c478bd9Sstevel@tonic-gate  */
517c478bd9Sstevel@tonic-gate 
52159d09a2SMark Phalan #include "gssapiP_krb5.h"
537c478bd9Sstevel@tonic-gate #include <k5-int.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate static krb5_error_code
56ab9b2e15Sgtb make_seal_token_v1 (krb5_context context,
57159d09a2SMark Phalan 		    krb5_keyblock *enc,
58159d09a2SMark Phalan 		    krb5_keyblock *seq,
59159d09a2SMark Phalan 		    gssint_uint64 *seqnum,
60159d09a2SMark Phalan 		    int direction,
61159d09a2SMark Phalan 		    gss_buffer_t text,
62159d09a2SMark Phalan 		    gss_buffer_t token,
63159d09a2SMark Phalan 		    int signalg,
64159d09a2SMark Phalan 		    size_t cksum_size,
65159d09a2SMark Phalan 		    int sealalg,
66159d09a2SMark Phalan 		    int encrypt,
67159d09a2SMark Phalan 		    int toktype,
68159d09a2SMark Phalan 		    int bigend,
69159d09a2SMark Phalan 		    gss_OID oid)
707c478bd9Sstevel@tonic-gate {
717c478bd9Sstevel@tonic-gate     krb5_error_code code;
727c478bd9Sstevel@tonic-gate     size_t sumlen;
737c478bd9Sstevel@tonic-gate     char *data_ptr;
747c478bd9Sstevel@tonic-gate     krb5_data plaind;
757c478bd9Sstevel@tonic-gate     krb5_checksum md5cksum;
767c478bd9Sstevel@tonic-gate     krb5_checksum cksum;
77159d09a2SMark Phalan 				/* msglen contains the message length
78159d09a2SMark Phalan 				 * we are signing/encrypting.  tmsglen
79159d09a2SMark Phalan 				 * contains the length of the message
80159d09a2SMark Phalan 				 * we plan to write out to the token.
81159d09a2SMark Phalan 				 * tlen is the length of the token
82159d09a2SMark Phalan 				 * including header. */
83159d09a2SMark Phalan     unsigned  conflen=0, tmsglen, tlen, msglen;
847c478bd9Sstevel@tonic-gate     unsigned char *t, *ptr;
857c478bd9Sstevel@tonic-gate     unsigned char *plain;
867c478bd9Sstevel@tonic-gate     unsigned char pad;
877c478bd9Sstevel@tonic-gate     krb5_keyusage sign_usage = KG_USAGE_SIGN;
887c478bd9Sstevel@tonic-gate     OM_uint32 seqnum32;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate     /* Solaris Kerberos:  check for recognized signalg and sealalg */
917c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() start\n");
927c478bd9Sstevel@tonic-gate #ifdef _KERNEL
937c478bd9Sstevel@tonic-gate 	/*
947c478bd9Sstevel@tonic-gate          * Because the ARCFOUR code bypasses the standard
957c478bd9Sstevel@tonic-gate 	 * crypto interfaces, we must make sure the kernel
967c478bd9Sstevel@tonic-gate 	 * crypto framework mechanism types are properly
977c478bd9Sstevel@tonic-gate 	 * initialized here.
987c478bd9Sstevel@tonic-gate 	 */
997c478bd9Sstevel@tonic-gate 	context->kef_cipher_mt = get_cipher_mech_type(context, seq);
1007c478bd9Sstevel@tonic-gate 	context->kef_hash_mt = get_hash_mech_type(context, seq);
1017c478bd9Sstevel@tonic-gate 	if ((code = init_key_kef(context->kef_cipher_mt, seq))) {
1027c478bd9Sstevel@tonic-gate 		return (code);
1037c478bd9Sstevel@tonic-gate 	}
1047c478bd9Sstevel@tonic-gate         if ((code = init_key_kef(context->kef_cipher_mt, enc))) {
1057c478bd9Sstevel@tonic-gate 		return (code);
1067c478bd9Sstevel@tonic-gate 	}
1077c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate     /* create the token buffer */
1107c478bd9Sstevel@tonic-gate     /* Do we need confounder? */
1117c478bd9Sstevel@tonic-gate     if (encrypt || (!bigend && (toktype == KG_TOK_SEAL_MSG)))
112159d09a2SMark Phalan       conflen = kg_confounder_size(context, enc);
113159d09a2SMark Phalan     else conflen = 0;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate     if (toktype == KG_TOK_SEAL_MSG) {
116159d09a2SMark Phalan       switch (sealalg) {
117159d09a2SMark Phalan       case SEAL_ALG_MICROSOFT_RC4:
118159d09a2SMark Phalan 	msglen = conflen + text->length+1;
119159d09a2SMark Phalan 	pad = 1;
120159d09a2SMark Phalan 	break;
121159d09a2SMark Phalan       default:
122159d09a2SMark Phalan 	/* XXX knows that des block size is 8 */
123159d09a2SMark Phalan 	msglen = (conflen+text->length+8)&(~7);
124159d09a2SMark Phalan 	      pad = 8-(text->length%8);
125159d09a2SMark Phalan       }
126159d09a2SMark Phalan       tmsglen = msglen;
1277c478bd9Sstevel@tonic-gate     } else {
128159d09a2SMark Phalan       tmsglen = 0;
129159d09a2SMark Phalan       msglen = text->length;
130159d09a2SMark Phalan       pad = 0;
1317c478bd9Sstevel@tonic-gate     }
1327c478bd9Sstevel@tonic-gate     tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate     if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
135159d09a2SMark Phalan       return(ENOMEM);
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate     /*** fill in the token */
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate     ptr = t;
1407c478bd9Sstevel@tonic-gate     g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate     /* 0..1 SIGN_ALG */
1437c478bd9Sstevel@tonic-gate     ptr[0] = (unsigned char) (signalg & 0xff);
1447c478bd9Sstevel@tonic-gate     ptr[1] = (unsigned char) ((signalg >> 8) & 0xff);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate     /* 2..3 SEAL_ALG or Filler */
1477c478bd9Sstevel@tonic-gate     if ((toktype == KG_TOK_SEAL_MSG) && encrypt) {
1487c478bd9Sstevel@tonic-gate 	ptr[2] = (unsigned char) (sealalg & 0xff);
1497c478bd9Sstevel@tonic-gate 	ptr[3] = (unsigned char) ((sealalg >> 8) & 0xff);
1507c478bd9Sstevel@tonic-gate     } else {
151159d09a2SMark Phalan       /* No seal */
152159d09a2SMark Phalan       ptr[2] = 0xff;
153159d09a2SMark Phalan       ptr[3] = 0xff;
1547c478bd9Sstevel@tonic-gate     }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate     /* 4..5 Filler */
1577c478bd9Sstevel@tonic-gate     ptr[4] = 0xff;
1587c478bd9Sstevel@tonic-gate     ptr[5] = 0xff;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate     /* pad the plaintext, encrypt if needed, and stick it in the token */
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate     /* initialize the the cksum */
1637c478bd9Sstevel@tonic-gate     switch (signalg) {
1647c478bd9Sstevel@tonic-gate     case SGN_ALG_DES_MAC_MD5:
1657c478bd9Sstevel@tonic-gate     case SGN_ALG_MD2_5:
166159d09a2SMark Phalan       md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
167159d09a2SMark Phalan       break;
1687c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_SHA1_DES3_KD:
169159d09a2SMark Phalan       md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
170159d09a2SMark Phalan       break;
1717c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_MD5:
172159d09a2SMark Phalan       md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
173159d09a2SMark Phalan       if (toktype != KG_TOK_SEAL_MSG)
174159d09a2SMark Phalan 	sign_usage = 15;
175159d09a2SMark Phalan       break;
1767c478bd9Sstevel@tonic-gate     default:
1777c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, error2 signalg=%d\n",
1787c478bd9Sstevel@tonic-gate 		signalg);
1797c478bd9Sstevel@tonic-gate #ifndef	_KERNEL
180159d09a2SMark Phalan       abort ();
1817c478bd9Sstevel@tonic-gate #else
1827c478bd9Sstevel@tonic-gate 	return (GSS_S_DEFECTIVE_TOKEN);
1837c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1847c478bd9Sstevel@tonic-gate     }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
1877c478bd9Sstevel@tonic-gate     if (code) {
1887c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, krb5_c_checksum_length() "
1897c478bd9Sstevel@tonic-gate 		"error code=%d\n", code);
190159d09a2SMark Phalan       return(code);
1917c478bd9Sstevel@tonic-gate     }
192159d09a2SMark Phalan     md5cksum.length = sumlen;
193159d09a2SMark Phalan 
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate     if ((plain = (unsigned char *) xmalloc(msglen ? msglen : 1)) == NULL) {
196159d09a2SMark Phalan       xfree_wrap(t, tlen);
197159d09a2SMark Phalan       return(ENOMEM);
1987c478bd9Sstevel@tonic-gate     }
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate     if (conflen) {
201159d09a2SMark Phalan       if ((code = kg_make_confounder(context, enc, plain))) {
202159d09a2SMark Phalan 	xfree_wrap(plain, msglen ? msglen : 1);
203159d09a2SMark Phalan 	xfree_wrap(t, tlen);
204159d09a2SMark Phalan 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, "
205159d09a2SMark Phalan 		"kg_make_confounder() error code=%d\n", code);
206159d09a2SMark Phalan 	return(code);
207159d09a2SMark Phalan       }
2087c478bd9Sstevel@tonic-gate     }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate     (void) memcpy(plain+conflen, text->value, text->length);
211159d09a2SMark Phalan     if (pad) (void) memset(plain+conflen+text->length, pad, pad);
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate     /* compute the checksum */
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate     /* 8 = head of token body as specified by mech spec */
2167c478bd9Sstevel@tonic-gate     if (! (data_ptr = (char *) xmalloc(8 +
2177c478bd9Sstevel@tonic-gate 		(bigend ? text->length : msglen)))) {
2187c478bd9Sstevel@tonic-gate 	xfree_wrap(plain, msglen ? msglen : 1);
2197c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
2207c478bd9Sstevel@tonic-gate 	return(ENOMEM);
2217c478bd9Sstevel@tonic-gate     }
2227c478bd9Sstevel@tonic-gate     (void) memcpy(data_ptr, ptr-2, 8);
2237c478bd9Sstevel@tonic-gate     if (bigend)
224159d09a2SMark Phalan       (void) memcpy(data_ptr+8, text->value, text->length);
2257c478bd9Sstevel@tonic-gate     else
226159d09a2SMark Phalan       (void) memcpy(data_ptr+8, plain, msglen);
2277c478bd9Sstevel@tonic-gate     plaind.length = 8 + (bigend ? text->length : msglen);
2287c478bd9Sstevel@tonic-gate     plaind.data = data_ptr;
2297c478bd9Sstevel@tonic-gate     code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
230159d09a2SMark Phalan 				sign_usage, &plaind, &md5cksum);
2317c478bd9Sstevel@tonic-gate     xfree_wrap(data_ptr,8 + (bigend ? text->length : msglen));
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate     if (code) {
234159d09a2SMark Phalan       KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, "
235159d09a2SMark Phalan       	"krb5_c_make_checksum() error code=%d\n", code);
236159d09a2SMark Phalan       xfree_wrap(plain, msglen ? msglen : 1);
237159d09a2SMark Phalan       xfree_wrap(t, tlen);
238159d09a2SMark Phalan       return(code);
2397c478bd9Sstevel@tonic-gate     }
2407c478bd9Sstevel@tonic-gate     switch(signalg) {
2417c478bd9Sstevel@tonic-gate     case SGN_ALG_DES_MAC_MD5:
2427c478bd9Sstevel@tonic-gate     case 3:
2437c478bd9Sstevel@tonic-gate 
244159d09a2SMark Phalan       if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL,
245159d09a2SMark Phalan 			     (g_OID_equal(oid, gss_mech_krb5_old) ?
246159d09a2SMark Phalan 			      seq->contents : NULL),
247159d09a2SMark Phalan 			     md5cksum.contents, md5cksum.contents, 16))) {
248159d09a2SMark Phalan 	xfree_wrap(md5cksum.contents, md5cksum.length);
249159d09a2SMark Phalan 	xfree_wrap(t, tlen);
250159d09a2SMark Phalan 
251159d09a2SMark Phalan 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_encrypt() "
252159d09a2SMark Phalan 	        "error code=%d\n", code);
253159d09a2SMark Phalan 	return code;
254159d09a2SMark Phalan       }
2557c478bd9Sstevel@tonic-gate 
256159d09a2SMark Phalan       cksum.length = cksum_size;
257159d09a2SMark Phalan       cksum.contents = md5cksum.contents + 16 - cksum.length;
2587c478bd9Sstevel@tonic-gate 
259159d09a2SMark Phalan      (void) memcpy(ptr+14, cksum.contents, cksum.length);
260159d09a2SMark Phalan       break;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_SHA1_DES3_KD:
263159d09a2SMark Phalan       /*
264159d09a2SMark Phalan        * Using key derivation, the call to krb5_c_make_checksum
265159d09a2SMark Phalan        * already dealt with encrypting.
266159d09a2SMark Phalan        */
267159d09a2SMark Phalan       if (md5cksum.length != cksum_size)
2687c478bd9Sstevel@tonic-gate 	{
2697c478bd9Sstevel@tonic-gate 		KRB5_LOG1(KRB5_ERR, "make_seal_token_v1() end, error "
270159d09a2SMark Phalan 				   "md5cksum.length %u != "
271159d09a2SMark Phalan 				   "cksum_size %u\n",
272159d09a2SMark Phalan 				   (unsigned int)md5cksum.length,
273159d09a2SMark Phalan 				   (unsigned int) cksum_size);
2747c478bd9Sstevel@tonic-gate #ifndef	_KERNEL
275159d09a2SMark Phalan 	abort ();
2767c478bd9Sstevel@tonic-gate #else
277159d09a2SMark Phalan 	return (GSS_S_DEFECTIVE_TOKEN);
2787c478bd9Sstevel@tonic-gate #endif
2797c478bd9Sstevel@tonic-gate 	}
280159d09a2SMark Phalan       (void) memcpy(ptr+14, md5cksum.contents, md5cksum.length);
281159d09a2SMark Phalan       break;
2827c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_MD5:
283159d09a2SMark Phalan 	KRB5_LOG(KRB5_INFO, "make_seal_token_v1() cksum_size = %u",
284159d09a2SMark Phalan 		(unsigned int)cksum_size);
2857c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14, md5cksum.contents, cksum_size);
2867c478bd9Sstevel@tonic-gate 	break;
2877c478bd9Sstevel@tonic-gate     }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate     xfree_wrap(md5cksum.contents, md5cksum.length);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate     /* create the seq_num */
2927c478bd9Sstevel@tonic-gate     seqnum32 = (OM_uint32)(*seqnum & 0xFFFFFFFF);
2937c478bd9Sstevel@tonic-gate     if ((code = kg_make_seq_num(context, seq, direction?0:0xff, seqnum32,
2947c478bd9Sstevel@tonic-gate 				ptr+14, ptr+6))) {
2957c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_make_seq_num() "
2987c478bd9Sstevel@tonic-gate 		    "error code=%d\n", code);
2997c478bd9Sstevel@tonic-gate 	return(code);
3007c478bd9Sstevel@tonic-gate     }
301159d09a2SMark Phalan 
3027c478bd9Sstevel@tonic-gate     if (encrypt) {
303159d09a2SMark Phalan       switch(sealalg) {
304159d09a2SMark Phalan       case SEAL_ALG_MICROSOFT_RC4:
3057c478bd9Sstevel@tonic-gate 	{
306159d09a2SMark Phalan 	  unsigned char bigend_seqnum[4];
307159d09a2SMark Phalan 	  krb5_keyblock *enc_key;
308159d09a2SMark Phalan 	  int i;
309159d09a2SMark Phalan 	  bigend_seqnum[0] = (*seqnum>>24) & 0xff;
310159d09a2SMark Phalan 	  bigend_seqnum[1] = (*seqnum>>16) & 0xff;
311159d09a2SMark Phalan 	  bigend_seqnum[2] = (*seqnum>>8) & 0xff;
312159d09a2SMark Phalan 	  bigend_seqnum[3] = *seqnum & 0xff;
313159d09a2SMark Phalan 	  code = krb5_copy_keyblock (context, enc, &enc_key);
314159d09a2SMark Phalan 	  if (code)
315159d09a2SMark Phalan 	    {
316159d09a2SMark Phalan 	      xfree_wrap(plain, msglen ? msglen : 1);
317159d09a2SMark Phalan 	      xfree_wrap(t, tlen);
318159d09a2SMark Phalan 	      return(code);
319159d09a2SMark Phalan 	    }
320159d09a2SMark Phalan 	  for (i = 0; i <= 15; i++)
321159d09a2SMark Phalan 	    ((char *) enc_key->contents)[i] ^=0xf0;
322159d09a2SMark Phalan 	  code = kg_arcfour_docrypt (context, enc_key, 0,
323159d09a2SMark Phalan 				     bigend_seqnum, 4,
324159d09a2SMark Phalan 				     plain, tmsglen,
325159d09a2SMark Phalan 				     ptr+14+cksum_size);
326159d09a2SMark Phalan 	  krb5_free_keyblock (context, enc_key);
327159d09a2SMark Phalan 	  if (code)
328159d09a2SMark Phalan 	    {
329159d09a2SMark Phalan 	      xfree_wrap(plain, msglen ? msglen : 1);
330159d09a2SMark Phalan 	      xfree_wrap(t, tlen);
331159d09a2SMark Phalan 	      return(code);
332159d09a2SMark Phalan 	    }
3337c478bd9Sstevel@tonic-gate 	}
334159d09a2SMark Phalan 	break;
335159d09a2SMark Phalan       default:
3367c478bd9Sstevel@tonic-gate 	    if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL,
337159d09a2SMark Phalan 				   (krb5_pointer) plain,
338159d09a2SMark Phalan 				   (krb5_pointer) (ptr+cksum_size+14),
339159d09a2SMark Phalan 				   tmsglen))) {
340159d09a2SMark Phalan 	      xfree_wrap(plain, msglen ? msglen : 1);
341159d09a2SMark Phalan 	      xfree_wrap(t, tlen);
342159d09a2SMark Phalan 	      return(code);
343159d09a2SMark Phalan 	    }
3447c478bd9Sstevel@tonic-gate       }
3457c478bd9Sstevel@tonic-gate     }else {
3467c478bd9Sstevel@tonic-gate       if (tmsglen)
3477c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14+cksum_size, plain, tmsglen);
3487c478bd9Sstevel@tonic-gate     }
3497c478bd9Sstevel@tonic-gate     xfree_wrap(plain, msglen ? msglen : 1);
3507c478bd9Sstevel@tonic-gate 
351159d09a2SMark Phalan 
3527c478bd9Sstevel@tonic-gate     /* that's it.  return the token */
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate     (*seqnum)++;
3557c478bd9Sstevel@tonic-gate     *seqnum &= (ulong_t)0xffffffffU;
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate     token->length = tlen;
3587c478bd9Sstevel@tonic-gate     token->value = (void *) t;
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() end\n");
3617c478bd9Sstevel@tonic-gate     return(0);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate /* if signonly is true, ignore conf_req, conf_state,
3657c478bd9Sstevel@tonic-gate    and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate OM_uint32
368ab9b2e15Sgtb kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
3697c478bd9Sstevel@tonic-gate 	input_message_buffer, conf_state, output_message_buffer, toktype)
3707c478bd9Sstevel@tonic-gate     OM_uint32 *minor_status;
3717c478bd9Sstevel@tonic-gate     gss_ctx_id_t context_handle;
3727c478bd9Sstevel@tonic-gate     int conf_req_flag;
3737c478bd9Sstevel@tonic-gate     int qop_req;
3747c478bd9Sstevel@tonic-gate     gss_buffer_t input_message_buffer;
3757c478bd9Sstevel@tonic-gate     int *conf_state;
3767c478bd9Sstevel@tonic-gate     gss_buffer_t output_message_buffer;
3777c478bd9Sstevel@tonic-gate     int toktype;
3787c478bd9Sstevel@tonic-gate {
3797c478bd9Sstevel@tonic-gate     krb5_gss_ctx_id_rec *ctx;
3807c478bd9Sstevel@tonic-gate     krb5_error_code code;
3817c478bd9Sstevel@tonic-gate     krb5_timestamp now;
382ab9b2e15Sgtb     krb5_context context;
3837c478bd9Sstevel@tonic-gate 
3847c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "kg_seal() start");
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate     output_message_buffer->length = 0;
3877c478bd9Sstevel@tonic-gate     output_message_buffer->value = NULL;
3887c478bd9Sstevel@tonic-gate 
3897c478bd9Sstevel@tonic-gate     /* Only default qop or matching established cryptosystem is allowed.
3907c478bd9Sstevel@tonic-gate 
391159d09a2SMark Phalan        There are NO EXTENSIONS to this set for AES and friends!  The
392159d09a2SMark Phalan        new spec says "just use 0".  The old spec plus extensions would
393159d09a2SMark Phalan        actually allow for certain non-zero values.  Fix this to handle
394159d09a2SMark Phalan        them later.  */
3957c478bd9Sstevel@tonic-gate     if (qop_req != 0) {
3967c478bd9Sstevel@tonic-gate 	*minor_status = (OM_uint32) G_UNKNOWN_QOP;
3977c478bd9Sstevel@tonic-gate 	KRB5_LOG0(KRB5_ERR, "kg_seal() end, error G_UNKNOWN_QOP\n");
3987c478bd9Sstevel@tonic-gate 	return (GSS_S_BAD_QOP);
3997c478bd9Sstevel@tonic-gate     }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate     /* validate the context handle */
4027c478bd9Sstevel@tonic-gate     if (! kg_validate_ctx_id(context_handle)) {
4037c478bd9Sstevel@tonic-gate 	*minor_status = (OM_uint32) G_VALIDATE_FAILED;
4047c478bd9Sstevel@tonic-gate 	KRB5_LOG0(KRB5_ERR, "kg_seal() kg_validate_ctx_id() end, "
4057c478bd9Sstevel@tonic-gate 		"error GSS_S_NO_CONTEXT\n");
4067c478bd9Sstevel@tonic-gate 	return (GSS_S_NO_CONTEXT);
4077c478bd9Sstevel@tonic-gate     }
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate     ctx = (krb5_gss_ctx_id_rec *) context_handle;
4107c478bd9Sstevel@tonic-gate 
411220c5023Swyllys     if (ctx->subkey == NULL && !ctx->established) {
4127c478bd9Sstevel@tonic-gate 	*minor_status = KG_CTX_INCOMPLETE;
4137c478bd9Sstevel@tonic-gate 	return(GSS_S_NO_CONTEXT);
4147c478bd9Sstevel@tonic-gate     }
4157c478bd9Sstevel@tonic-gate 
416ab9b2e15Sgtb     context = ctx->k5_context;
4177c478bd9Sstevel@tonic-gate     if ((code = krb5_timeofday(context, &now))) {
4187c478bd9Sstevel@tonic-gate 	*minor_status = code;
419*5e01956fSGlenn Barry         save_error_info(*minor_status, context);
4207c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, krb5_timeofday() error code=%d\n", code);
4217c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4227c478bd9Sstevel@tonic-gate     }
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate     switch (ctx->proto)
4257c478bd9Sstevel@tonic-gate     {
4267c478bd9Sstevel@tonic-gate     case 0:
4277c478bd9Sstevel@tonic-gate 	code = make_seal_token_v1(context, ctx->enc, ctx->seq,
428159d09a2SMark Phalan 				  &ctx->seq_send, ctx->initiate,
429159d09a2SMark Phalan 				  input_message_buffer, output_message_buffer,
430159d09a2SMark Phalan 				  ctx->signalg, ctx->cksum_size, ctx->sealalg,
431159d09a2SMark Phalan 				  conf_req_flag, toktype, ctx->big_endian,
432159d09a2SMark Phalan 				  ctx->mech_used);
4337c478bd9Sstevel@tonic-gate 	break;
4347c478bd9Sstevel@tonic-gate     case 1:
4357c478bd9Sstevel@tonic-gate 	code = gss_krb5int_make_seal_token_v3(context, ctx,
436159d09a2SMark Phalan 					      input_message_buffer,
437159d09a2SMark Phalan 					      output_message_buffer,
438159d09a2SMark Phalan 					      conf_req_flag, toktype);
4397c478bd9Sstevel@tonic-gate 	break;
4407c478bd9Sstevel@tonic-gate     default:
441159d09a2SMark Phalan 	code = G_UNKNOWN_QOP;	/* XXX */
4427c478bd9Sstevel@tonic-gate 	break;
4437c478bd9Sstevel@tonic-gate     }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate     if (code) {
4467c478bd9Sstevel@tonic-gate 	*minor_status = code;
447*5e01956fSGlenn Barry         save_error_info(*minor_status, context);
4487c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, make_seal_token_v1() "
4497c478bd9Sstevel@tonic-gate 		"error code=%d\n", code);
4507c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4517c478bd9Sstevel@tonic-gate     }
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate     if (conf_state)
4547c478bd9Sstevel@tonic-gate 	*conf_state = conf_req_flag;
4557c478bd9Sstevel@tonic-gate 
456159d09a2SMark Phalan     *minor_status = 0;
4577c478bd9Sstevel@tonic-gate    if (ctx->endtime < now) {
4587c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(minor_status, output_message_buffer);
4597c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, error GSS_S_CONTEXT_EXPIRED "
4607c478bd9Sstevel@tonic-gate 		"ctx->endtime = %d\n", ctx->endtime);
4617c478bd9Sstevel@tonic-gate 	return (GSS_S_CONTEXT_EXPIRED);
4627c478bd9Sstevel@tonic-gate    }
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_seal() end\n");
4657c478bd9Sstevel@tonic-gate    return (GSS_S_COMPLETE);
4667c478bd9Sstevel@tonic-gate }
467