xref: /onnv-gate/usr/src/lib/gss_mechs/mech_dh/backend/mech/seq.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/note.h>
30*0Sstevel@tonic-gate #include "dh_gssapi.h"
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate /*
33*0Sstevel@tonic-gate  * This module implements the interfaces for replay and out-of-sequence
34*0Sstevel@tonic-gate  * detection.
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #define	WBITS_DEF 8 * sizeof (seq_word_t) /*  Bits in a seq_word_t */
38*0Sstevel@tonic-gate static const int WBITS = WBITS_DEF; /* Stored in a static int for debuging */
39*0Sstevel@tonic-gate static const int NBITS =  SSIZE * WBITS_DEF; /* Total bits in the sequence */
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /*
42*0Sstevel@tonic-gate  * The following routines are for debuging:
43*0Sstevel@tonic-gate  *	__context_debug_set_next_seqno
44*0Sstevel@tonic-gate  *	__context_debug_get_next_seqno
45*0Sstevel@tonic-gate  *	__context_debug_set_last_seqno
46*0Sstevel@tonic-gate  *	__context_debug_get_last_seqno
47*0Sstevel@tonic-gate  *	__context_debug_print_seq_hist
48*0Sstevel@tonic-gate  *      __context_debug_get_hist_size
49*0Sstevel@tonic-gate  *	__context_debug
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  * These routines are declared static and there addresses placed into a table.
52*0Sstevel@tonic-gate  * There is one publicly declare routine __context_debug_entry that is used
53*0Sstevel@tonic-gate  * to fetch these entries. This way other routines can be added with out
54*0Sstevel@tonic-gate  * changing the map-version file. This is being done for use with a libgss
55*0Sstevel@tonic-gate  * test driver. In particular this technique is being used to implement
56*0Sstevel@tonic-gate  * a pseudo libgss entry point gss_context_cntrl. Its declaration is
57*0Sstevel@tonic-gate  * OM_uint32
58*0Sstevel@tonic-gate  * gss_context_cntl(OM_uint32 *minor, gss_ctx_id_t ctx, int cmd, void *argp);
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  * Hence the declaratin of the debug routines below.
61*0Sstevel@tonic-gate  */
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate /* Set the next sequence number to be sent */
64*0Sstevel@tonic-gate static OM_uint32
__context_debug_set_next_seqno(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)65*0Sstevel@tonic-gate __context_debug_set_next_seqno(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
68*0Sstevel@tonic-gate 	OM_uint32 seqno = (OM_uint32)(intptr_t)argp;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	if (minor == 0)
71*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
74*0Sstevel@tonic-gate 	/*
75*0Sstevel@tonic-gate 	 * If context, set the sequence number.
76*0Sstevel@tonic-gate 	 * Locking should not be necessary since OM_uint32 should be atomic
77*0Sstevel@tonic-gate 	 * size.
78*0Sstevel@tonic-gate 	 */
79*0Sstevel@tonic-gate 	if (ctx) {
80*0Sstevel@tonic-gate 		mutex_lock(&ctx->seqno_lock);
81*0Sstevel@tonic-gate 		ctx->next_seqno = seqno;
82*0Sstevel@tonic-gate 		mutex_unlock(&ctx->seqno_lock);
83*0Sstevel@tonic-gate 	}
84*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
85*0Sstevel@tonic-gate }
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate /* Get the next sequence number to be sent */
88*0Sstevel@tonic-gate static OM_uint32
__context_debug_get_next_seqno(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)89*0Sstevel@tonic-gate __context_debug_get_next_seqno(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
90*0Sstevel@tonic-gate {
91*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	if (minor == 0)
94*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 	if (argp == 0)
97*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
100*0Sstevel@tonic-gate 	/* Grap the next sequence number */
101*0Sstevel@tonic-gate 	*(OM_uint32 *)argp = ctx->next_seqno;
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
104*0Sstevel@tonic-gate }
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate /* Set the last sequence number to was seen */
107*0Sstevel@tonic-gate static OM_uint32
__context_debug_set_last_seqno(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)108*0Sstevel@tonic-gate __context_debug_set_last_seqno(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
109*0Sstevel@tonic-gate {
110*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
111*0Sstevel@tonic-gate 	OM_uint32 seqno = (OM_uint32)(intptr_t)argp;
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate 	if (minor == 0)
114*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	/*
119*0Sstevel@tonic-gate 	 * If context, set the sequence number.
120*0Sstevel@tonic-gate 	 * Locking should not be necessary since OM_uint32 should be atomic
121*0Sstevel@tonic-gate 	 * size.
122*0Sstevel@tonic-gate 	 */
123*0Sstevel@tonic-gate 	if (ctx) {
124*0Sstevel@tonic-gate 		mutex_lock(&ctx->hist.seq_arr_lock);
125*0Sstevel@tonic-gate 		ctx->hist.seqno = seqno;
126*0Sstevel@tonic-gate 		mutex_unlock(&ctx->hist.seq_arr_lock);
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
129*0Sstevel@tonic-gate }
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate /* Get the last sequence number seen */
132*0Sstevel@tonic-gate static OM_uint32
__context_debug_get_last_seqno(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)133*0Sstevel@tonic-gate __context_debug_get_last_seqno(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	if (minor == 0)
138*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	if (argp == 0)
141*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
142*0Sstevel@tonic-gate 
143*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
144*0Sstevel@tonic-gate 	/* Grap the next sequence number */
145*0Sstevel@tonic-gate 	*(OM_uint32 *)argp = ctx->hist.seqno;
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
148*0Sstevel@tonic-gate }
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate static seq_word_t
rev(seq_word_t r)151*0Sstevel@tonic-gate rev(seq_word_t r)
152*0Sstevel@tonic-gate {
153*0Sstevel@tonic-gate 	int i;
154*0Sstevel@tonic-gate 	seq_word_t t = 0;
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 	for (i = 0; i < WBITS; i++)
157*0Sstevel@tonic-gate 		if (r & ((seq_word_t)1 << i))
158*0Sstevel@tonic-gate 			t |= ((seq_word_t)1 << (WBITS - 1 - i));
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	return (t);
161*0Sstevel@tonic-gate }
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate /* Print out the sequence history to stderr */
164*0Sstevel@tonic-gate static OM_uint32
__context_debug_print_seq_hist(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)165*0Sstevel@tonic-gate __context_debug_print_seq_hist(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
166*0Sstevel@tonic-gate {
167*0Sstevel@tonic-gate _NOTE(ARGUNUSED(argp))
168*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
169*0Sstevel@tonic-gate 	int i;
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	if (minor == 0)
172*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate 	/* Print out the sequence history */
177*0Sstevel@tonic-gate 	fprintf(stderr, "%u: ", ctx->hist.seqno);
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	for (i = 0; i < SSIZE; i++)
180*0Sstevel@tonic-gate 		fprintf(stderr, "%016.16llx", rev(ctx->hist.arr[i]));
181*0Sstevel@tonic-gate 	fprintf(stderr, "\n");
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
184*0Sstevel@tonic-gate }
185*0Sstevel@tonic-gate 
186*0Sstevel@tonic-gate /* Fetch the size of the history */
187*0Sstevel@tonic-gate static OM_uint32
__context_debug_get_hist_size(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)188*0Sstevel@tonic-gate __context_debug_get_hist_size(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
189*0Sstevel@tonic-gate {
190*0Sstevel@tonic-gate _NOTE(ARGUNUSED(cntx))
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	if (minor == 0)
193*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
194*0Sstevel@tonic-gate 	if (argp == 0)
195*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
198*0Sstevel@tonic-gate 	*(OM_uint32 *)argp = NBITS;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
201*0Sstevel@tonic-gate }
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate /* Set the debug flag on the context */
204*0Sstevel@tonic-gate static OM_uint32
__context_debug(OM_uint32 * minor,gss_ctx_id_t cntx,void * argp)205*0Sstevel@tonic-gate __context_debug(OM_uint32 *minor, gss_ctx_id_t cntx, void *argp)
206*0Sstevel@tonic-gate {
207*0Sstevel@tonic-gate 	dh_gss_context_t ctx = (dh_gss_context_t)cntx;
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate 	if (minor == 0)
210*0Sstevel@tonic-gate 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 	*minor = DH_SUCCESS;
213*0Sstevel@tonic-gate 	ctx->debug = (OM_uint32)(intptr_t)argp;
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	return (GSS_S_COMPLETE);
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /* Type to descript debug routines */
219*0Sstevel@tonic-gate typedef OM_uint32 (*fptr)(OM_uint32 *, gss_ctx_id_t, void *);
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate /* Array of debug entries defined above */
222*0Sstevel@tonic-gate static fptr __context_debug_entry_array[] = {
223*0Sstevel@tonic-gate 	__context_debug,
224*0Sstevel@tonic-gate 	__context_debug_set_next_seqno,
225*0Sstevel@tonic-gate 	__context_debug_get_next_seqno,
226*0Sstevel@tonic-gate 	__context_debug_print_seq_hist,
227*0Sstevel@tonic-gate 	__context_debug_get_hist_size,
228*0Sstevel@tonic-gate 	__context_debug_set_last_seqno,
229*0Sstevel@tonic-gate 	__context_debug_get_last_seqno
230*0Sstevel@tonic-gate };
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate /* Structure to hold the debug entries */
233*0Sstevel@tonic-gate static struct {
234*0Sstevel@tonic-gate 	int no_entries;
235*0Sstevel@tonic-gate 	fptr  *entrys;
236*0Sstevel@tonic-gate } __context_debug_entry_points = {
237*0Sstevel@tonic-gate 	sizeof (__context_debug_entry_array)/sizeof (fptr),
238*0Sstevel@tonic-gate 	__context_debug_entry_array
239*0Sstevel@tonic-gate };
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate /*
242*0Sstevel@tonic-gate  * Exported entry point for debug routines. A call to this routine will
243*0Sstevel@tonic-gate  * return a pointer to the above structure.
244*0Sstevel@tonic-gate  */
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate void*
__context_debug_entry()247*0Sstevel@tonic-gate __context_debug_entry()
248*0Sstevel@tonic-gate {
249*0Sstevel@tonic-gate 	return (&__context_debug_entry_points);
250*0Sstevel@tonic-gate }
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate /* *************** End of Debug Section ***************** */
253*0Sstevel@tonic-gate 
254*0Sstevel@tonic-gate /* Clear all the bits in a sequence array */
255*0Sstevel@tonic-gate static void
clear_all_bits(seq_array_t sa)256*0Sstevel@tonic-gate clear_all_bits(seq_array_t sa)
257*0Sstevel@tonic-gate {
258*0Sstevel@tonic-gate 	unsigned int i;
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	for (i = 0; i < SSIZE; i++)
261*0Sstevel@tonic-gate 		sa->arr[i] = (seq_word_t)0;
262*0Sstevel@tonic-gate }
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate /* Check that a bit is set in a sequence array */
265*0Sstevel@tonic-gate static unsigned int
check_bit(seq_array_t sa,unsigned int bit)266*0Sstevel@tonic-gate check_bit(seq_array_t sa, unsigned int bit)
267*0Sstevel@tonic-gate {
268*0Sstevel@tonic-gate 	if (bit >=  NBITS)
269*0Sstevel@tonic-gate 		return (0);
270*0Sstevel@tonic-gate 
271*0Sstevel@tonic-gate 	return (sa->arr[bit/WBITS] & ((seq_word_t)1 << (bit % WBITS)) ? 1 : 0);
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate /* Set a bit in a sequence array */
275*0Sstevel@tonic-gate void
set_bit(seq_array_t sa,unsigned int bit)276*0Sstevel@tonic-gate set_bit(seq_array_t sa, unsigned int bit)
277*0Sstevel@tonic-gate {
278*0Sstevel@tonic-gate 	if (bit < NBITS)
279*0Sstevel@tonic-gate 		sa->arr[bit/WBITS] |= ((seq_word_t)1 << (bit % WBITS));
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate /* Clear a bit in a sequence array */
283*0Sstevel@tonic-gate /*
284*0Sstevel@tonic-gate  * This function is not used, but is here as a comment for completeness.
285*0Sstevel@tonic-gate  * Lint will complain if it is not commented out.
286*0Sstevel@tonic-gate  * static void
287*0Sstevel@tonic-gate  * clear_bit(seq_array_t sa, unsigned int bit)
288*0Sstevel@tonic-gate  * {
289*0Sstevel@tonic-gate  *	if (bit < NBITS)
290*0Sstevel@tonic-gate  *		sa->arr[bit/WBITS] &= ~((seq_word_t)1 << (bit % WBITS));
291*0Sstevel@tonic-gate  * }
292*0Sstevel@tonic-gate  */
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate /*
295*0Sstevel@tonic-gate  * Sift the bits in a sequence array by n
296*0Sstevel@tonic-gate  *
297*0Sstevel@tonic-gate  * The seqeunece arrays are logically arranged least significant bit to
298*0Sstevel@tonic-gate  * most significant bit, where the LSB represents that last sequence
299*0Sstevel@tonic-gate  * number seen. Thus this routine shifts the entire array to the left by
300*0Sstevel@tonic-gate  * n.
301*0Sstevel@tonic-gate  *
302*0Sstevel@tonic-gate  *  0                                                             NBITS-1
303*0Sstevel@tonic-gate  * +---------------------------------------------------------------+
304*0Sstevel@tonic-gate  * |                                                               |
305*0Sstevel@tonic-gate  * +---------------------------------------------------------------+
306*0Sstevel@tonic-gate  *  ^
307*0Sstevel@tonic-gate  *  This bit corresponds to the last sequence number seen sa->seqno.
308*0Sstevel@tonic-gate  */
309*0Sstevel@tonic-gate static void
shift_bits(seq_array_t sa,unsigned int n)310*0Sstevel@tonic-gate shift_bits(seq_array_t sa, unsigned int n)
311*0Sstevel@tonic-gate {
312*0Sstevel@tonic-gate 	int i, m;
313*0Sstevel@tonic-gate 	seq_word_t in = 0, out;
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 	/* How many words to shift */
316*0Sstevel@tonic-gate 	m = n / WBITS;
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	/* Do we need to shift by words */
319*0Sstevel@tonic-gate 	if (m) {
320*0Sstevel@tonic-gate 		for (i = SSIZE - 1; i >= m; i--)
321*0Sstevel@tonic-gate 			sa->arr[i] = sa->arr[i - m];
322*0Sstevel@tonic-gate 		for (; i >= 0; i--)
323*0Sstevel@tonic-gate 			sa->arr[i] = (seq_word_t)0;
324*0Sstevel@tonic-gate 	}
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate 	if (m >= SSIZE)
327*0Sstevel@tonic-gate 		return;
328*0Sstevel@tonic-gate 
329*0Sstevel@tonic-gate 	/* The bits we need to shift */
330*0Sstevel@tonic-gate 	n %= WBITS;
331*0Sstevel@tonic-gate 	if (n == 0)
332*0Sstevel@tonic-gate 		return;
333*0Sstevel@tonic-gate 
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	for (i = m; i < SSIZE; i++) {
336*0Sstevel@tonic-gate 		/* The out going bits */
337*0Sstevel@tonic-gate 		out = (sa->arr[i] >> (WBITS - n));
338*0Sstevel@tonic-gate 		/*
339*0Sstevel@tonic-gate 		 * shift this part of the bit array and "add in"
340*0Sstevel@tonic-gate 		 * the most significant bits shifted out of the previous
341*0Sstevel@tonic-gate 		 * previous word.
342*0Sstevel@tonic-gate 		 */
343*0Sstevel@tonic-gate 		sa->arr[i] = (sa->arr[i] << n) |  in;
344*0Sstevel@tonic-gate 		/* The output of this word is the input to the next */
345*0Sstevel@tonic-gate 		in = out;
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate }
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate /*
351*0Sstevel@tonic-gate  * See if the given sequence number is out of sequence or is a replay
352*0Sstevel@tonic-gate  * on the given context. If the context is not interested in either
353*0Sstevel@tonic-gate  * just return GSS_S_COMPLETE
354*0Sstevel@tonic-gate  */
355*0Sstevel@tonic-gate OM_uint32
__dh_seq_detection(dh_gss_context_t ctx,OM_uint32 seqno)356*0Sstevel@tonic-gate __dh_seq_detection(dh_gss_context_t ctx, OM_uint32 seqno)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	OM_uint32 n;
359*0Sstevel@tonic-gate 	OM_uint32 stat = GSS_S_COMPLETE;
360*0Sstevel@tonic-gate 	OM_uint32 minor;
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	/*
363*0Sstevel@tonic-gate 	 * See if there is anything to do. If not return with no bits set.
364*0Sstevel@tonic-gate 	 */
365*0Sstevel@tonic-gate 
366*0Sstevel@tonic-gate 	if (((ctx->flags & GSS_C_REPLAY_FLAG) == 0) &&
367*0Sstevel@tonic-gate 	    ((ctx->flags & GSS_C_SEQUENCE_FLAG) == 0))
368*0Sstevel@tonic-gate 		return (stat);
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 	/* lock the history why we check */
371*0Sstevel@tonic-gate 	mutex_lock(&ctx->hist.seq_arr_lock);
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	/* If debugging print out the current history */
374*0Sstevel@tonic-gate 	if (ctx->debug)
375*0Sstevel@tonic-gate 		__context_debug_print_seq_hist(&minor, (gss_ctx_id_t)ctx, 0);
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 	n = seqno - ctx->hist.seqno;
378*0Sstevel@tonic-gate 	/* See if n is zero or that the high order bit is set or n = 0 */
379*0Sstevel@tonic-gate 	if ((n & ~((~((OM_uint32)0)) >> 1)) || n == 0) {
380*0Sstevel@tonic-gate 		/* sequence number is in the past */
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 		/*
383*0Sstevel@tonic-gate 		 * We want the small piece of the pie, so take the
384*0Sstevel@tonic-gate 		 * 2s complement (-n).
385*0Sstevel@tonic-gate 		 */
386*0Sstevel@tonic-gate 		n =  ~n + 1;
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 		/* the sequence number is ancient history */
389*0Sstevel@tonic-gate 		if (n > NBITS - 1)
390*0Sstevel@tonic-gate 			stat = GSS_S_OLD_TOKEN;
391*0Sstevel@tonic-gate 		/* See if it has been seen before */
392*0Sstevel@tonic-gate 		else if (check_bit(&ctx->hist, n))
393*0Sstevel@tonic-gate 			stat = GSS_S_DUPLICATE_TOKEN;
394*0Sstevel@tonic-gate 		else {
395*0Sstevel@tonic-gate 			/* Otherwise we've seen it now, so recored the fact */
396*0Sstevel@tonic-gate 			set_bit(&ctx->hist, n);
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 			/* If we care, report that we're out of sequence */
399*0Sstevel@tonic-gate 			if (ctx->flags & GSS_C_SEQUENCE_FLAG)
400*0Sstevel@tonic-gate 				stat = GSS_S_UNSEQ_TOKEN;
401*0Sstevel@tonic-gate 		}
402*0Sstevel@tonic-gate 	} else {
403*0Sstevel@tonic-gate 		/* sequence number is in the future so shift */
404*0Sstevel@tonic-gate 		shift_bits(&ctx->hist, n);
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 		/* The sequence number is the most recent now */
407*0Sstevel@tonic-gate 		ctx->hist.seqno = seqno;
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 		/* So set the most recent bit */
410*0Sstevel@tonic-gate 		set_bit(&ctx->hist, 0);
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 		/* if n > 1 and we care report a gap in the sequence */
413*0Sstevel@tonic-gate 		if (n > 1 && (ctx->flags & GSS_C_SEQUENCE_FLAG))
414*0Sstevel@tonic-gate 			stat = GSS_S_GAP_TOKEN;
415*0Sstevel@tonic-gate 	}
416*0Sstevel@tonic-gate 
417*0Sstevel@tonic-gate 	/* If we're debugging print out the new state */
418*0Sstevel@tonic-gate 	if (ctx->debug)
419*0Sstevel@tonic-gate 		__context_debug_print_seq_hist(&minor, (gss_ctx_id_t)ctx, 0);
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	/* Let other threads in */
422*0Sstevel@tonic-gate 	mutex_unlock(&ctx->hist.seq_arr_lock);
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 	/* return the status */
425*0Sstevel@tonic-gate 	return (stat);
426*0Sstevel@tonic-gate }
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate /*
429*0Sstevel@tonic-gate  * Set the next sequence number to use on this context.
430*0Sstevel@tonic-gate  * Return that sequence number.
431*0Sstevel@tonic-gate  */
432*0Sstevel@tonic-gate OM_uint32
__dh_next_seqno(dh_gss_context_t ctx)433*0Sstevel@tonic-gate __dh_next_seqno(dh_gss_context_t ctx)
434*0Sstevel@tonic-gate {
435*0Sstevel@tonic-gate 	OM_uint32 t;
436*0Sstevel@tonic-gate 
437*0Sstevel@tonic-gate 	mutex_lock(&ctx->seqno_lock);
438*0Sstevel@tonic-gate 	t = ctx->next_seqno++;
439*0Sstevel@tonic-gate 	mutex_unlock(&ctx->seqno_lock);
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate 	return (t);
442*0Sstevel@tonic-gate }
443*0Sstevel@tonic-gate 
444*0Sstevel@tonic-gate 
445*0Sstevel@tonic-gate /*
446*0Sstevel@tonic-gate  * Initialize sequence history on a new context
447*0Sstevel@tonic-gate  */
448*0Sstevel@tonic-gate void
__dh_init_seq_hist(dh_gss_context_t ctx)449*0Sstevel@tonic-gate __dh_init_seq_hist(dh_gss_context_t ctx)
450*0Sstevel@tonic-gate {
451*0Sstevel@tonic-gate 	mutex_init(&ctx->seqno_lock, USYNC_THREAD, 0);
452*0Sstevel@tonic-gate 	ctx->next_seqno = 1;
453*0Sstevel@tonic-gate 	mutex_init(&ctx->hist.seq_arr_lock, USYNC_THREAD, 0);
454*0Sstevel@tonic-gate 	ctx->hist.seqno = 0;
455*0Sstevel@tonic-gate 	clear_all_bits(&ctx->hist);
456*0Sstevel@tonic-gate }
457*0Sstevel@tonic-gate 
458*0Sstevel@tonic-gate /*
459*0Sstevel@tonic-gate  * Destroy sequence history on a context.
460*0Sstevel@tonic-gate  */
461*0Sstevel@tonic-gate void
__dh_destroy_seq_hist(dh_gss_context_t ctx)462*0Sstevel@tonic-gate __dh_destroy_seq_hist(dh_gss_context_t ctx)
463*0Sstevel@tonic-gate {
464*0Sstevel@tonic-gate 	if (ctx) {
465*0Sstevel@tonic-gate 		mutex_destroy(&ctx->seqno_lock);
466*0Sstevel@tonic-gate 		mutex_destroy(&ctx->hist.seq_arr_lock);
467*0Sstevel@tonic-gate 	}
468*0Sstevel@tonic-gate }
469