17c478bd9Sstevel@tonic-gate /*
2220c5023Swyllys  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
127c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
137c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
147c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
157c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
167c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
177c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
187c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
197c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
227c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
237c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
247c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
257c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
267c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
277c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * All rights reserved.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
367c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
377c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
387c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
417c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
427c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
437c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
447c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
457c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
467c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
477c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
487c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
497c478bd9Sstevel@tonic-gate  * or implied warranty.
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
527c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
537c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #include <gssapiP_krb5.h>
577c478bd9Sstevel@tonic-gate #include <k5-int.h>
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate static krb5_error_code
60*ab9b2e15Sgtb make_seal_token_v1 (krb5_context context,
617c478bd9Sstevel@tonic-gate 			      krb5_keyblock *enc,
627c478bd9Sstevel@tonic-gate 			      krb5_keyblock *seq,
637c478bd9Sstevel@tonic-gate 			      gssint_uint64 *seqnum,
647c478bd9Sstevel@tonic-gate 			      int direction,
657c478bd9Sstevel@tonic-gate 			      gss_buffer_t text,
667c478bd9Sstevel@tonic-gate 			      gss_buffer_t token,
677c478bd9Sstevel@tonic-gate 			      int signalg,
687c478bd9Sstevel@tonic-gate 			      int cksum_size,
697c478bd9Sstevel@tonic-gate 			      int sealalg,
707c478bd9Sstevel@tonic-gate 			      int encrypt,
717c478bd9Sstevel@tonic-gate 			      int toktype,
727c478bd9Sstevel@tonic-gate 			      int bigend,
73*ab9b2e15Sgtb 			      gss_OID oid);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static krb5_error_code
767c478bd9Sstevel@tonic-gate make_seal_token_v1(context, enc, seq, seqnum, direction, text, token,
777c478bd9Sstevel@tonic-gate 		   signalg, cksum_size, sealalg, encrypt, toktype,
787c478bd9Sstevel@tonic-gate 		   bigend, oid)
797c478bd9Sstevel@tonic-gate     krb5_context context;
807c478bd9Sstevel@tonic-gate     krb5_keyblock *enc;
817c478bd9Sstevel@tonic-gate     krb5_keyblock *seq;
827c478bd9Sstevel@tonic-gate     gssint_uint64 *seqnum;
837c478bd9Sstevel@tonic-gate     int direction;
847c478bd9Sstevel@tonic-gate     gss_buffer_t text;
857c478bd9Sstevel@tonic-gate     gss_buffer_t token;
867c478bd9Sstevel@tonic-gate     int signalg;
877c478bd9Sstevel@tonic-gate     int cksum_size;
887c478bd9Sstevel@tonic-gate     int sealalg;
897c478bd9Sstevel@tonic-gate     int encrypt;
907c478bd9Sstevel@tonic-gate     int toktype;
917c478bd9Sstevel@tonic-gate     int bigend;
927c478bd9Sstevel@tonic-gate     gss_OID oid;
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate     krb5_error_code code;
957c478bd9Sstevel@tonic-gate     size_t sumlen;
967c478bd9Sstevel@tonic-gate     char *data_ptr;
977c478bd9Sstevel@tonic-gate     krb5_data plaind;
987c478bd9Sstevel@tonic-gate     krb5_checksum md5cksum;
997c478bd9Sstevel@tonic-gate     krb5_checksum cksum;
1007c478bd9Sstevel@tonic-gate 	/*
1017c478bd9Sstevel@tonic-gate 	 * msglen contains the message length
1027c478bd9Sstevel@tonic-gate 	 * we are signing/encrypting.  tmsglen
1037c478bd9Sstevel@tonic-gate 	 * contains the length of the message
1047c478bd9Sstevel@tonic-gate 	 * we plan to write out to the token.
1057c478bd9Sstevel@tonic-gate 	 * tlen is the length of the token
1067c478bd9Sstevel@tonic-gate 	 * including header.
1077c478bd9Sstevel@tonic-gate 	 */
1087c478bd9Sstevel@tonic-gate     int conflen=0, tmsglen, tlen, msglen;
1097c478bd9Sstevel@tonic-gate     unsigned char *t, *ptr;
1107c478bd9Sstevel@tonic-gate     unsigned char *plain;
1117c478bd9Sstevel@tonic-gate     unsigned char pad;
1127c478bd9Sstevel@tonic-gate     krb5_keyusage sign_usage = KG_USAGE_SIGN;
1137c478bd9Sstevel@tonic-gate     OM_uint32 seqnum32;
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate     /* Solaris Kerberos:  check for recognized signalg and sealalg */
1167c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() start\n");
1177c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1187c478bd9Sstevel@tonic-gate 	/*
1197c478bd9Sstevel@tonic-gate          * Because the ARCFOUR code bypasses the standard
1207c478bd9Sstevel@tonic-gate 	 * crypto interfaces, we must make sure the kernel
1217c478bd9Sstevel@tonic-gate 	 * crypto framework mechanism types are properly
1227c478bd9Sstevel@tonic-gate 	 * initialized here.
1237c478bd9Sstevel@tonic-gate 	 */
1247c478bd9Sstevel@tonic-gate 	context->kef_cipher_mt = get_cipher_mech_type(context, seq);
1257c478bd9Sstevel@tonic-gate 	context->kef_hash_mt = get_hash_mech_type(context, seq);
1267c478bd9Sstevel@tonic-gate 	if ((code = init_key_kef(context->kef_cipher_mt, seq))) {
1277c478bd9Sstevel@tonic-gate 		return (code);
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate         if ((code = init_key_kef(context->kef_cipher_mt, enc))) {
1307c478bd9Sstevel@tonic-gate 		return (code);
1317c478bd9Sstevel@tonic-gate 	}
1327c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate     /* create the token buffer */
1357c478bd9Sstevel@tonic-gate     /* Do we need confounder? */
1367c478bd9Sstevel@tonic-gate     if (encrypt || (!bigend && (toktype == KG_TOK_SEAL_MSG)))
1377c478bd9Sstevel@tonic-gate 	conflen = kg_confounder_size(context, enc);
1387c478bd9Sstevel@tonic-gate     else
1397c478bd9Sstevel@tonic-gate 	conflen = 0;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate     if (toktype == KG_TOK_SEAL_MSG) {
1427c478bd9Sstevel@tonic-gate 	switch (sealalg) {
1437c478bd9Sstevel@tonic-gate 		case SEAL_ALG_MICROSOFT_RC4:
1447c478bd9Sstevel@tonic-gate 			msglen = conflen + text->length+1;
1457c478bd9Sstevel@tonic-gate 			pad = 1;
1467c478bd9Sstevel@tonic-gate 			break;
1477c478bd9Sstevel@tonic-gate 		default:
1487c478bd9Sstevel@tonic-gate 			/* XXX knows that des block size is 8 */
1497c478bd9Sstevel@tonic-gate 			msglen = (conflen+text->length+8)&(~7);
1507c478bd9Sstevel@tonic-gate 			pad = 8-(text->length%8);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	tmsglen = msglen;
1537c478bd9Sstevel@tonic-gate     } else {
1547c478bd9Sstevel@tonic-gate 	tmsglen = 0;
1557c478bd9Sstevel@tonic-gate 	msglen = text->length;
1567c478bd9Sstevel@tonic-gate 	pad = 0;
1577c478bd9Sstevel@tonic-gate     }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate     tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate     if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
1627c478bd9Sstevel@tonic-gate 	return(ENOMEM);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate     /*** fill in the token */
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate     ptr = t;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate     g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate     /* 0..1 SIGN_ALG */
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate     ptr[0] = (unsigned char) (signalg & 0xff);
1737c478bd9Sstevel@tonic-gate     ptr[1] = (unsigned char) ((signalg >> 8) & 0xff);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate     /* 2..3 SEAL_ALG or Filler */
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate     if ((toktype == KG_TOK_SEAL_MSG) && encrypt) {
1787c478bd9Sstevel@tonic-gate 	ptr[2] = (unsigned char) (sealalg & 0xff);
1797c478bd9Sstevel@tonic-gate 	ptr[3] = (unsigned char) ((sealalg >> 8) & 0xff);
1807c478bd9Sstevel@tonic-gate     } else {
1817c478bd9Sstevel@tonic-gate 	/* No seal */
1827c478bd9Sstevel@tonic-gate 	ptr[2] = 0xff;
1837c478bd9Sstevel@tonic-gate 	ptr[3] = 0xff;
1847c478bd9Sstevel@tonic-gate     }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate     /* 4..5 Filler */
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate     ptr[4] = 0xff;
1897c478bd9Sstevel@tonic-gate     ptr[5] = 0xff;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate     /* pad the plaintext, encrypt if needed, and stick it in the token */
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate     /* initialize the the cksum */
1947c478bd9Sstevel@tonic-gate     switch (signalg) {
1957c478bd9Sstevel@tonic-gate     case SGN_ALG_DES_MAC_MD5:
1967c478bd9Sstevel@tonic-gate     case SGN_ALG_MD2_5:
1977c478bd9Sstevel@tonic-gate 	md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
1987c478bd9Sstevel@tonic-gate 	break;
1997c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_SHA1_DES3_KD:
2007c478bd9Sstevel@tonic-gate 	md5cksum.checksum_type = CKSUMTYPE_HMAC_SHA1_DES3;
2017c478bd9Sstevel@tonic-gate 	break;
2027c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_MD5:
2037c478bd9Sstevel@tonic-gate 	md5cksum.checksum_type = CKSUMTYPE_HMAC_MD5_ARCFOUR;
2047c478bd9Sstevel@tonic-gate 	if (toktype != KG_TOK_SEAL_MSG)
2057c478bd9Sstevel@tonic-gate 		sign_usage = 15;
2067c478bd9Sstevel@tonic-gate 	break;
2077c478bd9Sstevel@tonic-gate     default:
2087c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, error2 signalg=%d\n",
2097c478bd9Sstevel@tonic-gate 		signalg);
2107c478bd9Sstevel@tonic-gate #ifndef	_KERNEL
2117c478bd9Sstevel@tonic-gate 	abort ();
2127c478bd9Sstevel@tonic-gate #else
2137c478bd9Sstevel@tonic-gate 	return (GSS_S_DEFECTIVE_TOKEN);
2147c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2157c478bd9Sstevel@tonic-gate     }
2167c478bd9Sstevel@tonic-gate 
2177c478bd9Sstevel@tonic-gate     code = krb5_c_checksum_length(context, md5cksum.checksum_type, &sumlen);
2187c478bd9Sstevel@tonic-gate     if (code) {
2197c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, krb5_c_checksum_length() "
2207c478bd9Sstevel@tonic-gate 		"error code=%d\n", code);
2217c478bd9Sstevel@tonic-gate 	return(code);
2227c478bd9Sstevel@tonic-gate     }
2237c478bd9Sstevel@tonic-gate     md5cksum.length = (size_t)sumlen;
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate     if ((plain = (unsigned char *) xmalloc(msglen ? msglen : 1)) == NULL) {
2267c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
2277c478bd9Sstevel@tonic-gate 	return(ENOMEM);
2287c478bd9Sstevel@tonic-gate     }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate     if (conflen) {
2317c478bd9Sstevel@tonic-gate 	if ((code = kg_make_confounder(context, enc, plain))) {
2327c478bd9Sstevel@tonic-gate 		xfree_wrap(plain, msglen ? msglen : 1);
2337c478bd9Sstevel@tonic-gate 		xfree_wrap(t, tlen);
2347c478bd9Sstevel@tonic-gate 		KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, "
2357c478bd9Sstevel@tonic-gate 			"kg_make_confounder() error code=%d\n", code);
2367c478bd9Sstevel@tonic-gate 		return(code);
2377c478bd9Sstevel@tonic-gate 	}
2387c478bd9Sstevel@tonic-gate     }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate     (void) memcpy(plain+conflen, text->value, text->length);
2417c478bd9Sstevel@tonic-gate     if (pad)
2427c478bd9Sstevel@tonic-gate 	(void) memset(plain+conflen+text->length, pad, pad);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate     /* compute the checksum */
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate     /* 8 = head of token body as specified by mech spec */
2477c478bd9Sstevel@tonic-gate     if (! (data_ptr = (char *) xmalloc(8 +
2487c478bd9Sstevel@tonic-gate 		(bigend ? text->length : msglen)))) {
2497c478bd9Sstevel@tonic-gate 	xfree_wrap(plain, msglen ? msglen : 1);
2507c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
2517c478bd9Sstevel@tonic-gate 	return(ENOMEM);
2527c478bd9Sstevel@tonic-gate     }
2537c478bd9Sstevel@tonic-gate     (void) memcpy(data_ptr, ptr-2, 8);
2547c478bd9Sstevel@tonic-gate     if (bigend)
2557c478bd9Sstevel@tonic-gate 	(void) memcpy(data_ptr+8, text->value, text->length);
2567c478bd9Sstevel@tonic-gate     else
2577c478bd9Sstevel@tonic-gate 	(void) memcpy(data_ptr+8, plain, msglen);
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate     plaind.length = 8 + (bigend ? text->length : msglen);
2607c478bd9Sstevel@tonic-gate     plaind.data = data_ptr;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate     code = krb5_c_make_checksum(context, md5cksum.checksum_type, seq,
2637c478bd9Sstevel@tonic-gate 			    sign_usage, &plaind, &md5cksum);
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate     xfree_wrap(data_ptr,8 + (bigend ? text->length : msglen));
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate     if (code) {
2687c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, "
2697c478bd9Sstevel@tonic-gate 		"krb5_c_make_checksum() error code=%d\n", code);
2707c478bd9Sstevel@tonic-gate 	xfree_wrap(plain, msglen ? msglen : 1);
2717c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
2727c478bd9Sstevel@tonic-gate 	return(code);
2737c478bd9Sstevel@tonic-gate     }
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate     switch(signalg) {
2767c478bd9Sstevel@tonic-gate     case SGN_ALG_DES_MAC_MD5:
2777c478bd9Sstevel@tonic-gate     case 3:
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate        if ((code = kg_encrypt(context, seq, KG_USAGE_SEAL,
2807c478bd9Sstevel@tonic-gate 			       (g_OID_equal(oid, gss_mech_krb5_old) ?
2817c478bd9Sstevel@tonic-gate 				seq->contents : NULL),
2827c478bd9Sstevel@tonic-gate 			       md5cksum.contents, md5cksum.contents, 16))) {
2837c478bd9Sstevel@tonic-gate 	    xfree_wrap(md5cksum.contents, md5cksum.length);
2847c478bd9Sstevel@tonic-gate 	    xfree_wrap(t, tlen);
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	    KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_encrypt() "
2877c478bd9Sstevel@tonic-gate 		    "error code=%d\n", code);
2887c478bd9Sstevel@tonic-gate 	    return code;
2897c478bd9Sstevel@tonic-gate 	}
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	cksum.length = cksum_size;
2927c478bd9Sstevel@tonic-gate 	cksum.contents = md5cksum.contents + 16 - cksum.length;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14, cksum.contents, cksum.length);
2957c478bd9Sstevel@tonic-gate 	break;
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_SHA1_DES3_KD:
2987c478bd9Sstevel@tonic-gate 	/*
2997c478bd9Sstevel@tonic-gate 	 * Using key derivation, the call to krb5_c_make_checksum
3007c478bd9Sstevel@tonic-gate 	 * already dealt with encrypting.
3017c478bd9Sstevel@tonic-gate 	 */
3027c478bd9Sstevel@tonic-gate 	if (md5cksum.length != cksum_size)
3037c478bd9Sstevel@tonic-gate 	{
3047c478bd9Sstevel@tonic-gate 		KRB5_LOG1(KRB5_ERR, "make_seal_token_v1() end, error "
3057c478bd9Sstevel@tonic-gate 				   "md5cksum.length %d != "
3067c478bd9Sstevel@tonic-gate 				   "cksum_size %d\n",
3077c478bd9Sstevel@tonic-gate 				   md5cksum.length, cksum_size);
3087c478bd9Sstevel@tonic-gate #ifndef	_KERNEL
3097c478bd9Sstevel@tonic-gate 		abort ();
3107c478bd9Sstevel@tonic-gate #else
3117c478bd9Sstevel@tonic-gate 		return (GSS_S_DEFECTIVE_TOKEN);
3127c478bd9Sstevel@tonic-gate #endif
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14, md5cksum.contents, md5cksum.length);
3157c478bd9Sstevel@tonic-gate 	break;
3167c478bd9Sstevel@tonic-gate     case SGN_ALG_HMAC_MD5:
3177c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_INFO, "make_seal_token_v1() cksum_size = %d",
3187c478bd9Sstevel@tonic-gate 		cksum_size);
3197c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14, md5cksum.contents, cksum_size);
3207c478bd9Sstevel@tonic-gate 	break;
3217c478bd9Sstevel@tonic-gate     }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate     xfree_wrap(md5cksum.contents, md5cksum.length);
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate     /* create the seq_num */
3267c478bd9Sstevel@tonic-gate     seqnum32 = (OM_uint32)(*seqnum & 0xFFFFFFFF);
3277c478bd9Sstevel@tonic-gate     if ((code = kg_make_seq_num(context, seq, direction?0:0xff, seqnum32,
3287c478bd9Sstevel@tonic-gate 				ptr+14, ptr+6))) {
3297c478bd9Sstevel@tonic-gate 	xfree_wrap(t, tlen);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "make_seal_token_v1() end, kg_make_seq_num() "
3327c478bd9Sstevel@tonic-gate 		    "error code=%d\n", code);
3337c478bd9Sstevel@tonic-gate 	return(code);
3347c478bd9Sstevel@tonic-gate     }
3357c478bd9Sstevel@tonic-gate     if (encrypt) {
3367c478bd9Sstevel@tonic-gate 	switch(sealalg) {
3377c478bd9Sstevel@tonic-gate 	case SEAL_ALG_MICROSOFT_RC4:
3387c478bd9Sstevel@tonic-gate 	{
3397c478bd9Sstevel@tonic-gate 		unsigned char bigend_seqnum[4];
3407c478bd9Sstevel@tonic-gate 		krb5_keyblock *enc_key;
3417c478bd9Sstevel@tonic-gate 		int i;
3427c478bd9Sstevel@tonic-gate 		bigend_seqnum[0] = (*seqnum>>24) & 0xff;
3437c478bd9Sstevel@tonic-gate 		bigend_seqnum[1] = (*seqnum>>16) & 0xff;
3447c478bd9Sstevel@tonic-gate 		bigend_seqnum[2] = (*seqnum>>8) & 0xff;
3457c478bd9Sstevel@tonic-gate 		bigend_seqnum[3] = *seqnum & 0xff;
3467c478bd9Sstevel@tonic-gate 		code = krb5_copy_keyblock (context, enc, &enc_key);
3477c478bd9Sstevel@tonic-gate 		if (code)
3487c478bd9Sstevel@tonic-gate 		{
3497c478bd9Sstevel@tonic-gate 			xfree_wrap(plain, msglen ? msglen : 1);
3507c478bd9Sstevel@tonic-gate 			xfree_wrap(t, tlen);
3517c478bd9Sstevel@tonic-gate 			return(code);
3527c478bd9Sstevel@tonic-gate 		}
3537c478bd9Sstevel@tonic-gate 		for (i = 0; i <= 15; i++)
3547c478bd9Sstevel@tonic-gate 			((char *) enc_key->contents)[i] ^=0xf0;
3557c478bd9Sstevel@tonic-gate 		code = kg_arcfour_docrypt (context,
3567c478bd9Sstevel@tonic-gate 			enc_key, 0,
3577c478bd9Sstevel@tonic-gate 			bigend_seqnum, 4,
3587c478bd9Sstevel@tonic-gate 			plain, tmsglen,
3597c478bd9Sstevel@tonic-gate 			ptr+14+cksum_size);
3607c478bd9Sstevel@tonic-gate 		krb5_free_keyblock (context, enc_key);
3617c478bd9Sstevel@tonic-gate 		if (code)
3627c478bd9Sstevel@tonic-gate 		{
3637c478bd9Sstevel@tonic-gate 			xfree_wrap(plain, msglen ? msglen : 1);
3647c478bd9Sstevel@tonic-gate 			xfree_wrap(t, tlen);
3657c478bd9Sstevel@tonic-gate 			return(code);
3667c478bd9Sstevel@tonic-gate 		}
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate         break;
3697c478bd9Sstevel@tonic-gate 	default:
3707c478bd9Sstevel@tonic-gate 	    if ((code = kg_encrypt(context, enc, KG_USAGE_SEAL, NULL,
3717c478bd9Sstevel@tonic-gate                                    (krb5_pointer) plain,
3727c478bd9Sstevel@tonic-gate                                    (krb5_pointer) (ptr+cksum_size+14),
3737c478bd9Sstevel@tonic-gate                                    tmsglen))) {
3747c478bd9Sstevel@tonic-gate 		xfree_wrap(plain, msglen ? msglen : 1);
3757c478bd9Sstevel@tonic-gate 		xfree_wrap(t, tlen);
3767c478bd9Sstevel@tonic-gate 		return(code);
3777c478bd9Sstevel@tonic-gate             }
3787c478bd9Sstevel@tonic-gate       }
3797c478bd9Sstevel@tonic-gate     }else {
3807c478bd9Sstevel@tonic-gate       if (tmsglen)
3817c478bd9Sstevel@tonic-gate 	(void) memcpy(ptr+14+cksum_size, plain, tmsglen);
3827c478bd9Sstevel@tonic-gate     }
3837c478bd9Sstevel@tonic-gate     xfree_wrap(plain, msglen ? msglen : 1);
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate     /* that's it.  return the token */
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate     (*seqnum)++;
3887c478bd9Sstevel@tonic-gate     *seqnum &= (ulong_t)0xffffffffU;
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate     token->length = tlen;
3917c478bd9Sstevel@tonic-gate     token->value = (void *) t;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "make_seal_token_v1() end\n");
3947c478bd9Sstevel@tonic-gate     return(0);
3957c478bd9Sstevel@tonic-gate }
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /* if signonly is true, ignore conf_req, conf_state,
3987c478bd9Sstevel@tonic-gate    and do not encode the ENC_TYPE, MSG_LENGTH, or MSG_TEXT fields */
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate OM_uint32
401*ab9b2e15Sgtb kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
4027c478bd9Sstevel@tonic-gate 	input_message_buffer, conf_state, output_message_buffer, toktype)
4037c478bd9Sstevel@tonic-gate     OM_uint32 *minor_status;
4047c478bd9Sstevel@tonic-gate     gss_ctx_id_t context_handle;
4057c478bd9Sstevel@tonic-gate     int conf_req_flag;
4067c478bd9Sstevel@tonic-gate     int qop_req;
4077c478bd9Sstevel@tonic-gate     gss_buffer_t input_message_buffer;
4087c478bd9Sstevel@tonic-gate     int *conf_state;
4097c478bd9Sstevel@tonic-gate     gss_buffer_t output_message_buffer;
4107c478bd9Sstevel@tonic-gate     int toktype;
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate     krb5_gss_ctx_id_rec *ctx;
4137c478bd9Sstevel@tonic-gate     krb5_error_code code;
4147c478bd9Sstevel@tonic-gate     krb5_timestamp now;
415*ab9b2e15Sgtb     krb5_context context;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate     KRB5_LOG0(KRB5_INFO, "kg_seal() start");
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate     output_message_buffer->length = 0;
4207c478bd9Sstevel@tonic-gate     output_message_buffer->value = NULL;
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate     /* Only default qop or matching established cryptosystem is allowed.
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	There are NO EXTENSIONS to this set for AES and friends!	 The
4257c478bd9Sstevel@tonic-gate 	new spec says "just use 0".  The old spec plus extensions would
4267c478bd9Sstevel@tonic-gate 	actually allow for certain non-zero values.  Fix this to handle
4277c478bd9Sstevel@tonic-gate 	them later.  */
4287c478bd9Sstevel@tonic-gate     if (qop_req != 0) {
4297c478bd9Sstevel@tonic-gate 	*minor_status = (OM_uint32) G_UNKNOWN_QOP;
4307c478bd9Sstevel@tonic-gate 	KRB5_LOG0(KRB5_ERR, "kg_seal() end, error G_UNKNOWN_QOP\n");
4317c478bd9Sstevel@tonic-gate 	return (GSS_S_BAD_QOP);
4327c478bd9Sstevel@tonic-gate     }
4337c478bd9Sstevel@tonic-gate 
4347c478bd9Sstevel@tonic-gate     /* validate the context handle */
4357c478bd9Sstevel@tonic-gate     if (! kg_validate_ctx_id(context_handle)) {
4367c478bd9Sstevel@tonic-gate 	*minor_status = (OM_uint32) G_VALIDATE_FAILED;
4377c478bd9Sstevel@tonic-gate 	KRB5_LOG0(KRB5_ERR, "kg_seal() kg_validate_ctx_id() end, "
4387c478bd9Sstevel@tonic-gate 		"error GSS_S_NO_CONTEXT\n");
4397c478bd9Sstevel@tonic-gate 	return (GSS_S_NO_CONTEXT);
4407c478bd9Sstevel@tonic-gate     }
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate     ctx = (krb5_gss_ctx_id_rec *) context_handle;
4437c478bd9Sstevel@tonic-gate 
444220c5023Swyllys     if (ctx->subkey == NULL && !ctx->established) {
4457c478bd9Sstevel@tonic-gate 	*minor_status = KG_CTX_INCOMPLETE;
4467c478bd9Sstevel@tonic-gate 	return(GSS_S_NO_CONTEXT);
4477c478bd9Sstevel@tonic-gate     }
4487c478bd9Sstevel@tonic-gate 
449*ab9b2e15Sgtb     context = ctx->k5_context;
4507c478bd9Sstevel@tonic-gate     if ((code = krb5_timeofday(context, &now))) {
4517c478bd9Sstevel@tonic-gate 	*minor_status = code;
4527c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, krb5_timeofday() error code=%d\n", code);
4537c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4547c478bd9Sstevel@tonic-gate     }
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate     switch (ctx->proto)
4577c478bd9Sstevel@tonic-gate     {
4587c478bd9Sstevel@tonic-gate     case 0:
4597c478bd9Sstevel@tonic-gate 	code = make_seal_token_v1(context, ctx->enc, ctx->seq,
4607c478bd9Sstevel@tonic-gate                                   &ctx->seq_send, ctx->initiate,
4617c478bd9Sstevel@tonic-gate                                   input_message_buffer, output_message_buffer,
4627c478bd9Sstevel@tonic-gate                                   ctx->signalg, ctx->cksum_size, ctx->sealalg,
4637c478bd9Sstevel@tonic-gate                                   conf_req_flag, toktype, ctx->big_endian,
464*ab9b2e15Sgtb                                   ctx->mech_used);
4657c478bd9Sstevel@tonic-gate 	break;
4667c478bd9Sstevel@tonic-gate     case 1:
4677c478bd9Sstevel@tonic-gate 	code = gss_krb5int_make_seal_token_v3(context, ctx,
4687c478bd9Sstevel@tonic-gate                                               input_message_buffer,
4697c478bd9Sstevel@tonic-gate                                               output_message_buffer,
4707c478bd9Sstevel@tonic-gate                                               conf_req_flag, toktype);
4717c478bd9Sstevel@tonic-gate 	break;
4727c478bd9Sstevel@tonic-gate     default:
4737c478bd9Sstevel@tonic-gate 	code = G_UNKNOWN_QOP;
4747c478bd9Sstevel@tonic-gate 	break;
4757c478bd9Sstevel@tonic-gate     }
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate     if (code) {
4787c478bd9Sstevel@tonic-gate 	*minor_status = code;
4797c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, make_seal_token_v1() "
4807c478bd9Sstevel@tonic-gate 		"error code=%d\n", code);
4817c478bd9Sstevel@tonic-gate 	return (GSS_S_FAILURE);
4827c478bd9Sstevel@tonic-gate     }
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate     if (conf_state)
4857c478bd9Sstevel@tonic-gate 	*conf_state = conf_req_flag;
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate    *minor_status = 0;
4887c478bd9Sstevel@tonic-gate    if (ctx->endtime < now) {
4897c478bd9Sstevel@tonic-gate 	(void) gss_release_buffer(minor_status, output_message_buffer);
4907c478bd9Sstevel@tonic-gate 	KRB5_LOG(KRB5_ERR, "kg_seal() end, error GSS_S_CONTEXT_EXPIRED "
4917c478bd9Sstevel@tonic-gate 		"ctx->endtime = %d\n", ctx->endtime);
4927c478bd9Sstevel@tonic-gate 	return (GSS_S_CONTEXT_EXPIRED);
4937c478bd9Sstevel@tonic-gate    }
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_seal() end\n");
4967c478bd9Sstevel@tonic-gate    return (GSS_S_COMPLETE);
4977c478bd9Sstevel@tonic-gate }
498