1*0Sstevel@tonic-gate /* crypto/evp/p_lib.c */
2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3*0Sstevel@tonic-gate  * All rights reserved.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * This package is an SSL implementation written
6*0Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
7*0Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
10*0Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
11*0Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
12*0Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13*0Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
14*0Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
17*0Sstevel@tonic-gate  * the code are not to be removed.
18*0Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
19*0Sstevel@tonic-gate  * as the author of the parts of the library used.
20*0Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
21*0Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
24*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
25*0Sstevel@tonic-gate  * are met:
26*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
27*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
28*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
29*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
30*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
31*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
32*0Sstevel@tonic-gate  *    must display the following acknowledgement:
33*0Sstevel@tonic-gate  *    "This product includes cryptographic software written by
34*0Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
35*0Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
36*0Sstevel@tonic-gate  *    being used are not cryptographic related :-).
37*0Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
38*0Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
39*0Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40*0Sstevel@tonic-gate  *
41*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42*0Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*0Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*0Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*0Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*0Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*0Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*0Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*0Sstevel@tonic-gate  * SUCH DAMAGE.
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
54*0Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55*0Sstevel@tonic-gate  * copied and put under another distribution licence
56*0Sstevel@tonic-gate  * [including the GNU Public Licence.]
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #include <stdio.h>
60*0Sstevel@tonic-gate #include "cryptlib.h"
61*0Sstevel@tonic-gate #include <openssl/objects.h>
62*0Sstevel@tonic-gate #include <openssl/evp.h>
63*0Sstevel@tonic-gate #include <openssl/asn1_mac.h>
64*0Sstevel@tonic-gate #include <openssl/x509.h>
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static void EVP_PKEY_free_it(EVP_PKEY *x);
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate int EVP_PKEY_bits(EVP_PKEY *pkey)
69*0Sstevel@tonic-gate 	{
70*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
71*0Sstevel@tonic-gate 	if (pkey->type == EVP_PKEY_RSA)
72*0Sstevel@tonic-gate 		return(BN_num_bits(pkey->pkey.rsa->n));
73*0Sstevel@tonic-gate 	else
74*0Sstevel@tonic-gate #endif
75*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
76*0Sstevel@tonic-gate 		if (pkey->type == EVP_PKEY_DSA)
77*0Sstevel@tonic-gate 		return(BN_num_bits(pkey->pkey.dsa->p));
78*0Sstevel@tonic-gate #endif
79*0Sstevel@tonic-gate 	return(0);
80*0Sstevel@tonic-gate 	}
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate int EVP_PKEY_size(EVP_PKEY *pkey)
83*0Sstevel@tonic-gate 	{
84*0Sstevel@tonic-gate 	if (pkey == NULL)
85*0Sstevel@tonic-gate 		return(0);
86*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
87*0Sstevel@tonic-gate 	if (pkey->type == EVP_PKEY_RSA)
88*0Sstevel@tonic-gate 		return(RSA_size(pkey->pkey.rsa));
89*0Sstevel@tonic-gate 	else
90*0Sstevel@tonic-gate #endif
91*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
92*0Sstevel@tonic-gate 		if (pkey->type == EVP_PKEY_DSA)
93*0Sstevel@tonic-gate 		return(DSA_size(pkey->pkey.dsa));
94*0Sstevel@tonic-gate #endif
95*0Sstevel@tonic-gate 	return(0);
96*0Sstevel@tonic-gate 	}
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
99*0Sstevel@tonic-gate 	{
100*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
101*0Sstevel@tonic-gate 	if (pkey->type == EVP_PKEY_DSA)
102*0Sstevel@tonic-gate 		{
103*0Sstevel@tonic-gate 		int ret=pkey->save_parameters;
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 		if (mode >= 0)
106*0Sstevel@tonic-gate 			pkey->save_parameters=mode;
107*0Sstevel@tonic-gate 		return(ret);
108*0Sstevel@tonic-gate 		}
109*0Sstevel@tonic-gate #endif
110*0Sstevel@tonic-gate 	return(0);
111*0Sstevel@tonic-gate 	}
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate int EVP_PKEY_copy_parameters(EVP_PKEY *to, EVP_PKEY *from)
114*0Sstevel@tonic-gate 	{
115*0Sstevel@tonic-gate 	if (to->type != from->type)
116*0Sstevel@tonic-gate 		{
117*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_DIFFERENT_KEY_TYPES);
118*0Sstevel@tonic-gate 		goto err;
119*0Sstevel@tonic-gate 		}
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	if (EVP_PKEY_missing_parameters(from))
122*0Sstevel@tonic-gate 		{
123*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS,EVP_R_MISSING_PARAMETERS);
124*0Sstevel@tonic-gate 		goto err;
125*0Sstevel@tonic-gate 		}
126*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
127*0Sstevel@tonic-gate 	if (to->type == EVP_PKEY_DSA)
128*0Sstevel@tonic-gate 		{
129*0Sstevel@tonic-gate 		BIGNUM *a;
130*0Sstevel@tonic-gate 
131*0Sstevel@tonic-gate 		if ((a=BN_dup(from->pkey.dsa->p)) == NULL) goto err;
132*0Sstevel@tonic-gate 		if (to->pkey.dsa->p != NULL) BN_free(to->pkey.dsa->p);
133*0Sstevel@tonic-gate 		to->pkey.dsa->p=a;
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 		if ((a=BN_dup(from->pkey.dsa->q)) == NULL) goto err;
136*0Sstevel@tonic-gate 		if (to->pkey.dsa->q != NULL) BN_free(to->pkey.dsa->q);
137*0Sstevel@tonic-gate 		to->pkey.dsa->q=a;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 		if ((a=BN_dup(from->pkey.dsa->g)) == NULL) goto err;
140*0Sstevel@tonic-gate 		if (to->pkey.dsa->g != NULL) BN_free(to->pkey.dsa->g);
141*0Sstevel@tonic-gate 		to->pkey.dsa->g=a;
142*0Sstevel@tonic-gate 		}
143*0Sstevel@tonic-gate #endif
144*0Sstevel@tonic-gate 	return(1);
145*0Sstevel@tonic-gate err:
146*0Sstevel@tonic-gate 	return(0);
147*0Sstevel@tonic-gate 	}
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate int EVP_PKEY_missing_parameters(EVP_PKEY *pkey)
150*0Sstevel@tonic-gate 	{
151*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
152*0Sstevel@tonic-gate 	if (pkey->type == EVP_PKEY_DSA)
153*0Sstevel@tonic-gate 		{
154*0Sstevel@tonic-gate 		DSA *dsa;
155*0Sstevel@tonic-gate 
156*0Sstevel@tonic-gate 		dsa=pkey->pkey.dsa;
157*0Sstevel@tonic-gate 		if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
158*0Sstevel@tonic-gate 			return(1);
159*0Sstevel@tonic-gate 		}
160*0Sstevel@tonic-gate #endif
161*0Sstevel@tonic-gate 	return(0);
162*0Sstevel@tonic-gate 	}
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate int EVP_PKEY_cmp_parameters(EVP_PKEY *a, EVP_PKEY *b)
165*0Sstevel@tonic-gate 	{
166*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
167*0Sstevel@tonic-gate 	if ((a->type == EVP_PKEY_DSA) && (b->type == EVP_PKEY_DSA))
168*0Sstevel@tonic-gate 		{
169*0Sstevel@tonic-gate 		if (	BN_cmp(a->pkey.dsa->p,b->pkey.dsa->p) ||
170*0Sstevel@tonic-gate 			BN_cmp(a->pkey.dsa->q,b->pkey.dsa->q) ||
171*0Sstevel@tonic-gate 			BN_cmp(a->pkey.dsa->g,b->pkey.dsa->g))
172*0Sstevel@tonic-gate 			return(0);
173*0Sstevel@tonic-gate 		else
174*0Sstevel@tonic-gate 			return(1);
175*0Sstevel@tonic-gate 		}
176*0Sstevel@tonic-gate #endif
177*0Sstevel@tonic-gate 	return(-1);
178*0Sstevel@tonic-gate 	}
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate EVP_PKEY *EVP_PKEY_new(void)
181*0Sstevel@tonic-gate 	{
182*0Sstevel@tonic-gate 	EVP_PKEY *ret;
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	ret=(EVP_PKEY *)OPENSSL_malloc(sizeof(EVP_PKEY));
185*0Sstevel@tonic-gate 	if (ret == NULL)
186*0Sstevel@tonic-gate 		{
187*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_NEW,ERR_R_MALLOC_FAILURE);
188*0Sstevel@tonic-gate 		return(NULL);
189*0Sstevel@tonic-gate 		}
190*0Sstevel@tonic-gate 	ret->type=EVP_PKEY_NONE;
191*0Sstevel@tonic-gate 	ret->references=1;
192*0Sstevel@tonic-gate 	ret->pkey.ptr=NULL;
193*0Sstevel@tonic-gate 	ret->attributes=NULL;
194*0Sstevel@tonic-gate 	ret->save_parameters=1;
195*0Sstevel@tonic-gate 	return(ret);
196*0Sstevel@tonic-gate 	}
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate int EVP_PKEY_assign(EVP_PKEY *pkey, int type, char *key)
199*0Sstevel@tonic-gate 	{
200*0Sstevel@tonic-gate 	if (pkey == NULL) return(0);
201*0Sstevel@tonic-gate 	if (pkey->pkey.ptr != NULL)
202*0Sstevel@tonic-gate 		EVP_PKEY_free_it(pkey);
203*0Sstevel@tonic-gate 	pkey->type=EVP_PKEY_type(type);
204*0Sstevel@tonic-gate 	pkey->save_type=type;
205*0Sstevel@tonic-gate 	pkey->pkey.ptr=key;
206*0Sstevel@tonic-gate 	return(key != NULL);
207*0Sstevel@tonic-gate 	}
208*0Sstevel@tonic-gate 
209*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
210*0Sstevel@tonic-gate int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
211*0Sstevel@tonic-gate {
212*0Sstevel@tonic-gate 	int ret = EVP_PKEY_assign_RSA(pkey, key);
213*0Sstevel@tonic-gate 	if(ret)
214*0Sstevel@tonic-gate 		RSA_up_ref(key);
215*0Sstevel@tonic-gate 	return ret;
216*0Sstevel@tonic-gate }
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
219*0Sstevel@tonic-gate 	{
220*0Sstevel@tonic-gate 	if(pkey->type != EVP_PKEY_RSA) {
221*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_GET1_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
222*0Sstevel@tonic-gate 		return NULL;
223*0Sstevel@tonic-gate 	}
224*0Sstevel@tonic-gate 	RSA_up_ref(pkey->pkey.rsa);
225*0Sstevel@tonic-gate 	return pkey->pkey.rsa;
226*0Sstevel@tonic-gate }
227*0Sstevel@tonic-gate #endif
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
230*0Sstevel@tonic-gate int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
231*0Sstevel@tonic-gate {
232*0Sstevel@tonic-gate 	int ret = EVP_PKEY_assign_DSA(pkey, key);
233*0Sstevel@tonic-gate 	if(ret)
234*0Sstevel@tonic-gate 		DSA_up_ref(key);
235*0Sstevel@tonic-gate 	return ret;
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
239*0Sstevel@tonic-gate 	{
240*0Sstevel@tonic-gate 	if(pkey->type != EVP_PKEY_DSA) {
241*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_GET1_DSA, EVP_R_EXPECTING_A_DSA_KEY);
242*0Sstevel@tonic-gate 		return NULL;
243*0Sstevel@tonic-gate 	}
244*0Sstevel@tonic-gate 	DSA_up_ref(pkey->pkey.dsa);
245*0Sstevel@tonic-gate 	return pkey->pkey.dsa;
246*0Sstevel@tonic-gate }
247*0Sstevel@tonic-gate #endif
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate 	int ret = EVP_PKEY_assign_DH(pkey, key);
254*0Sstevel@tonic-gate 	if(ret)
255*0Sstevel@tonic-gate 		DH_up_ref(key);
256*0Sstevel@tonic-gate 	return ret;
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
260*0Sstevel@tonic-gate 	{
261*0Sstevel@tonic-gate 	if(pkey->type != EVP_PKEY_DH) {
262*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_PKEY_GET1_DH, EVP_R_EXPECTING_A_DH_KEY);
263*0Sstevel@tonic-gate 		return NULL;
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 	DH_up_ref(pkey->pkey.dh);
266*0Sstevel@tonic-gate 	return pkey->pkey.dh;
267*0Sstevel@tonic-gate }
268*0Sstevel@tonic-gate #endif
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate int EVP_PKEY_type(int type)
271*0Sstevel@tonic-gate 	{
272*0Sstevel@tonic-gate 	switch (type)
273*0Sstevel@tonic-gate 		{
274*0Sstevel@tonic-gate 	case EVP_PKEY_RSA:
275*0Sstevel@tonic-gate 	case EVP_PKEY_RSA2:
276*0Sstevel@tonic-gate 		return(EVP_PKEY_RSA);
277*0Sstevel@tonic-gate 	case EVP_PKEY_DSA:
278*0Sstevel@tonic-gate 	case EVP_PKEY_DSA1:
279*0Sstevel@tonic-gate 	case EVP_PKEY_DSA2:
280*0Sstevel@tonic-gate 	case EVP_PKEY_DSA3:
281*0Sstevel@tonic-gate 	case EVP_PKEY_DSA4:
282*0Sstevel@tonic-gate 		return(EVP_PKEY_DSA);
283*0Sstevel@tonic-gate 	case EVP_PKEY_DH:
284*0Sstevel@tonic-gate 		return(EVP_PKEY_DH);
285*0Sstevel@tonic-gate 	default:
286*0Sstevel@tonic-gate 		return(NID_undef);
287*0Sstevel@tonic-gate 		}
288*0Sstevel@tonic-gate 	}
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate void EVP_PKEY_free(EVP_PKEY *x)
291*0Sstevel@tonic-gate 	{
292*0Sstevel@tonic-gate 	int i;
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate 	if (x == NULL) return;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	i=CRYPTO_add(&x->references,-1,CRYPTO_LOCK_EVP_PKEY);
297*0Sstevel@tonic-gate #ifdef REF_PRINT
298*0Sstevel@tonic-gate 	REF_PRINT("EVP_PKEY",x);
299*0Sstevel@tonic-gate #endif
300*0Sstevel@tonic-gate 	if (i > 0) return;
301*0Sstevel@tonic-gate #ifdef REF_CHECK
302*0Sstevel@tonic-gate 	if (i < 0)
303*0Sstevel@tonic-gate 		{
304*0Sstevel@tonic-gate 		fprintf(stderr,"EVP_PKEY_free, bad reference count\n");
305*0Sstevel@tonic-gate 		abort();
306*0Sstevel@tonic-gate 		}
307*0Sstevel@tonic-gate #endif
308*0Sstevel@tonic-gate 	EVP_PKEY_free_it(x);
309*0Sstevel@tonic-gate 	OPENSSL_free(x);
310*0Sstevel@tonic-gate 	}
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate static void EVP_PKEY_free_it(EVP_PKEY *x)
313*0Sstevel@tonic-gate 	{
314*0Sstevel@tonic-gate 	switch (x->type)
315*0Sstevel@tonic-gate 		{
316*0Sstevel@tonic-gate #ifndef OPENSSL_NO_RSA
317*0Sstevel@tonic-gate 	case EVP_PKEY_RSA:
318*0Sstevel@tonic-gate 	case EVP_PKEY_RSA2:
319*0Sstevel@tonic-gate 		RSA_free(x->pkey.rsa);
320*0Sstevel@tonic-gate 		break;
321*0Sstevel@tonic-gate #endif
322*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DSA
323*0Sstevel@tonic-gate 	case EVP_PKEY_DSA:
324*0Sstevel@tonic-gate 	case EVP_PKEY_DSA2:
325*0Sstevel@tonic-gate 	case EVP_PKEY_DSA3:
326*0Sstevel@tonic-gate 	case EVP_PKEY_DSA4:
327*0Sstevel@tonic-gate 		DSA_free(x->pkey.dsa);
328*0Sstevel@tonic-gate 		break;
329*0Sstevel@tonic-gate #endif
330*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DH
331*0Sstevel@tonic-gate 	case EVP_PKEY_DH:
332*0Sstevel@tonic-gate 		DH_free(x->pkey.dh);
333*0Sstevel@tonic-gate 		break;
334*0Sstevel@tonic-gate #endif
335*0Sstevel@tonic-gate 		}
336*0Sstevel@tonic-gate 	}
337*0Sstevel@tonic-gate 
338