xref: /onnv-gate/usr/src/common/openssl/crypto/asn1/tasn_utl.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* tasn_utl.c */
20Sstevel@tonic-gate /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
30Sstevel@tonic-gate  * project 2000.
40Sstevel@tonic-gate  */
50Sstevel@tonic-gate /* ====================================================================
6*2139Sjp161948  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
90Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
100Sstevel@tonic-gate  * are met:
110Sstevel@tonic-gate  *
120Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
130Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
140Sstevel@tonic-gate  *
150Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
160Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in
170Sstevel@tonic-gate  *    the documentation and/or other materials provided with the
180Sstevel@tonic-gate  *    distribution.
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this
210Sstevel@tonic-gate  *    software must display the following acknowledgment:
220Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
230Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
240Sstevel@tonic-gate  *
250Sstevel@tonic-gate  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
260Sstevel@tonic-gate  *    endorse or promote products derived from this software without
270Sstevel@tonic-gate  *    prior written permission. For written permission, please contact
280Sstevel@tonic-gate  *    licensing@OpenSSL.org.
290Sstevel@tonic-gate  *
300Sstevel@tonic-gate  * 5. Products derived from this software may not be called "OpenSSL"
310Sstevel@tonic-gate  *    nor may "OpenSSL" appear in their names without prior written
320Sstevel@tonic-gate  *    permission of the OpenSSL Project.
330Sstevel@tonic-gate  *
340Sstevel@tonic-gate  * 6. Redistributions of any form whatsoever must retain the following
350Sstevel@tonic-gate  *    acknowledgment:
360Sstevel@tonic-gate  *    "This product includes software developed by the OpenSSL Project
370Sstevel@tonic-gate  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
380Sstevel@tonic-gate  *
390Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
400Sstevel@tonic-gate  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
410Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
420Sstevel@tonic-gate  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
430Sstevel@tonic-gate  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
440Sstevel@tonic-gate  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
450Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
460Sstevel@tonic-gate  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
470Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
480Sstevel@tonic-gate  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
490Sstevel@tonic-gate  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
500Sstevel@tonic-gate  * OF THE POSSIBILITY OF SUCH DAMAGE.
510Sstevel@tonic-gate  * ====================================================================
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This product includes cryptographic software written by Eric Young
540Sstevel@tonic-gate  * (eay@cryptsoft.com).  This product includes software written by Tim
550Sstevel@tonic-gate  * Hudson (tjh@cryptsoft.com).
560Sstevel@tonic-gate  *
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #include <stddef.h>
610Sstevel@tonic-gate #include <string.h>
620Sstevel@tonic-gate #include <openssl/asn1.h>
630Sstevel@tonic-gate #include <openssl/asn1t.h>
640Sstevel@tonic-gate #include <openssl/objects.h>
650Sstevel@tonic-gate #include <openssl/err.h>
660Sstevel@tonic-gate 
670Sstevel@tonic-gate /* Utility functions for manipulating fields and offsets */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate /* Add 'offset' to 'addr' */
700Sstevel@tonic-gate #define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /* Given an ASN1_ITEM CHOICE type return
730Sstevel@tonic-gate  * the selector value
740Sstevel@tonic-gate  */
750Sstevel@tonic-gate 
asn1_get_choice_selector(ASN1_VALUE ** pval,const ASN1_ITEM * it)760Sstevel@tonic-gate int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it)
77*2139Sjp161948 	{
780Sstevel@tonic-gate 	int *sel = offset2ptr(*pval, it->utype);
790Sstevel@tonic-gate 	return *sel;
80*2139Sjp161948 	}
810Sstevel@tonic-gate 
820Sstevel@tonic-gate /* Given an ASN1_ITEM CHOICE type set
830Sstevel@tonic-gate  * the selector value, return old value.
840Sstevel@tonic-gate  */
850Sstevel@tonic-gate 
asn1_set_choice_selector(ASN1_VALUE ** pval,int value,const ASN1_ITEM * it)860Sstevel@tonic-gate int asn1_set_choice_selector(ASN1_VALUE **pval, int value, const ASN1_ITEM *it)
87*2139Sjp161948 	{
880Sstevel@tonic-gate 	int *sel, ret;
890Sstevel@tonic-gate 	sel = offset2ptr(*pval, it->utype);
900Sstevel@tonic-gate 	ret = *sel;
910Sstevel@tonic-gate 	*sel = value;
920Sstevel@tonic-gate 	return ret;
93*2139Sjp161948 	}
940Sstevel@tonic-gate 
950Sstevel@tonic-gate /* Do reference counting. The value 'op' decides what to do.
960Sstevel@tonic-gate  * if it is +1 then the count is incremented. If op is 0 count is
970Sstevel@tonic-gate  * set to 1. If op is -1 count is decremented and the return value
980Sstevel@tonic-gate  * is the current refrence count or 0 if no reference count exists.
990Sstevel@tonic-gate  */
1000Sstevel@tonic-gate 
asn1_do_lock(ASN1_VALUE ** pval,int op,const ASN1_ITEM * it)1010Sstevel@tonic-gate int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it)
102*2139Sjp161948 	{
1030Sstevel@tonic-gate 	const ASN1_AUX *aux;
1040Sstevel@tonic-gate 	int *lck, ret;
105*2139Sjp161948 	if ((it->itype != ASN1_ITYPE_SEQUENCE)
106*2139Sjp161948 	   && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE))
107*2139Sjp161948 		return 0;
1080Sstevel@tonic-gate 	aux = it->funcs;
109*2139Sjp161948 	if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT))
110*2139Sjp161948 		return 0;
1110Sstevel@tonic-gate 	lck = offset2ptr(*pval, aux->ref_offset);
112*2139Sjp161948 	if (op == 0)
113*2139Sjp161948 		{
1140Sstevel@tonic-gate 		*lck = 1;
1150Sstevel@tonic-gate 		return 1;
116*2139Sjp161948 		}
1170Sstevel@tonic-gate 	ret = CRYPTO_add(lck, op, aux->ref_lock);
1180Sstevel@tonic-gate #ifdef REF_PRINT
1190Sstevel@tonic-gate 	fprintf(stderr, "%s: Reference Count: %d\n", it->sname, *lck);
1200Sstevel@tonic-gate #endif
1210Sstevel@tonic-gate #ifdef REF_CHECK
122*2139Sjp161948 	if (ret < 0)
1230Sstevel@tonic-gate 		fprintf(stderr, "%s, bad reference count\n", it->sname);
1240Sstevel@tonic-gate #endif
1250Sstevel@tonic-gate 	return ret;
126*2139Sjp161948 	}
1270Sstevel@tonic-gate 
asn1_get_enc_ptr(ASN1_VALUE ** pval,const ASN1_ITEM * it)1280Sstevel@tonic-gate static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it)
129*2139Sjp161948 	{
1300Sstevel@tonic-gate 	const ASN1_AUX *aux;
131*2139Sjp161948 	if (!pval || !*pval)
132*2139Sjp161948 		return NULL;
1330Sstevel@tonic-gate 	aux = it->funcs;
134*2139Sjp161948 	if (!aux || !(aux->flags & ASN1_AFLG_ENCODING))
135*2139Sjp161948 		return NULL;
1360Sstevel@tonic-gate 	return offset2ptr(*pval, aux->enc_offset);
137*2139Sjp161948 	}
1380Sstevel@tonic-gate 
asn1_enc_init(ASN1_VALUE ** pval,const ASN1_ITEM * it)1390Sstevel@tonic-gate void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it)
140*2139Sjp161948 	{
1410Sstevel@tonic-gate 	ASN1_ENCODING *enc;
1420Sstevel@tonic-gate 	enc = asn1_get_enc_ptr(pval, it);
143*2139Sjp161948 	if (enc)
144*2139Sjp161948 		{
1450Sstevel@tonic-gate 		enc->enc = NULL;
1460Sstevel@tonic-gate 		enc->len = 0;
1470Sstevel@tonic-gate 		enc->modified = 1;
148*2139Sjp161948 		}
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
asn1_enc_free(ASN1_VALUE ** pval,const ASN1_ITEM * it)1510Sstevel@tonic-gate void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
152*2139Sjp161948 	{
1530Sstevel@tonic-gate 	ASN1_ENCODING *enc;
1540Sstevel@tonic-gate 	enc = asn1_get_enc_ptr(pval, it);
155*2139Sjp161948 	if (enc)
156*2139Sjp161948 		{
157*2139Sjp161948 		if (enc->enc)
158*2139Sjp161948 			OPENSSL_free(enc->enc);
1590Sstevel@tonic-gate 		enc->enc = NULL;
1600Sstevel@tonic-gate 		enc->len = 0;
1610Sstevel@tonic-gate 		enc->modified = 1;
162*2139Sjp161948 		}
1630Sstevel@tonic-gate 	}
1640Sstevel@tonic-gate 
asn1_enc_save(ASN1_VALUE ** pval,const unsigned char * in,int inlen,const ASN1_ITEM * it)165*2139Sjp161948 int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen,
166*2139Sjp161948 							 const ASN1_ITEM *it)
167*2139Sjp161948 	{
1680Sstevel@tonic-gate 	ASN1_ENCODING *enc;
1690Sstevel@tonic-gate 	enc = asn1_get_enc_ptr(pval, it);
170*2139Sjp161948 	if (!enc)
171*2139Sjp161948 		return 1;
1720Sstevel@tonic-gate 
173*2139Sjp161948 	if (enc->enc)
174*2139Sjp161948 		OPENSSL_free(enc->enc);
1750Sstevel@tonic-gate 	enc->enc = OPENSSL_malloc(inlen);
176*2139Sjp161948 	if (!enc->enc)
177*2139Sjp161948 		return 0;
1780Sstevel@tonic-gate 	memcpy(enc->enc, in, inlen);
1790Sstevel@tonic-gate 	enc->len = inlen;
1800Sstevel@tonic-gate 	enc->modified = 0;
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 	return 1;
183*2139Sjp161948 	}
1840Sstevel@tonic-gate 
asn1_enc_restore(int * len,unsigned char ** out,ASN1_VALUE ** pval,const ASN1_ITEM * it)185*2139Sjp161948 int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval,
186*2139Sjp161948 							const ASN1_ITEM *it)
187*2139Sjp161948 	{
1880Sstevel@tonic-gate 	ASN1_ENCODING *enc;
1890Sstevel@tonic-gate 	enc = asn1_get_enc_ptr(pval, it);
190*2139Sjp161948 	if (!enc || enc->modified)
191*2139Sjp161948 		return 0;
192*2139Sjp161948 	if (out)
193*2139Sjp161948 		{
1940Sstevel@tonic-gate 		memcpy(*out, enc->enc, enc->len);
1950Sstevel@tonic-gate 		*out += enc->len;
196*2139Sjp161948 		}
197*2139Sjp161948 	if (len)
198*2139Sjp161948 		*len = enc->len;
199*2139Sjp161948 	return 1;
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate /* Given an ASN1_TEMPLATE get a pointer to a field */
asn1_get_field_ptr(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt)2030Sstevel@tonic-gate ASN1_VALUE ** asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
204*2139Sjp161948 	{
2050Sstevel@tonic-gate 	ASN1_VALUE **pvaltmp;
206*2139Sjp161948 	if (tt->flags & ASN1_TFLG_COMBINE)
207*2139Sjp161948 		return pval;
2080Sstevel@tonic-gate 	pvaltmp = offset2ptr(*pval, tt->offset);
2090Sstevel@tonic-gate 	/* NOTE for BOOLEAN types the field is just a plain
2100Sstevel@tonic-gate  	 * int so we can't return int **, so settle for
2110Sstevel@tonic-gate 	 * (int *).
2120Sstevel@tonic-gate 	 */
2130Sstevel@tonic-gate 	return pvaltmp;
214*2139Sjp161948 	}
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate /* Handle ANY DEFINED BY template, find the selector, look up
2170Sstevel@tonic-gate  * the relevant ASN1_TEMPLATE in the table and return it.
2180Sstevel@tonic-gate  */
2190Sstevel@tonic-gate 
asn1_do_adb(ASN1_VALUE ** pval,const ASN1_TEMPLATE * tt,int nullerr)220*2139Sjp161948 const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt,
221*2139Sjp161948 								int nullerr)
222*2139Sjp161948 	{
2230Sstevel@tonic-gate 	const ASN1_ADB *adb;
2240Sstevel@tonic-gate 	const ASN1_ADB_TABLE *atbl;
2250Sstevel@tonic-gate 	long selector;
2260Sstevel@tonic-gate 	ASN1_VALUE **sfld;
2270Sstevel@tonic-gate 	int i;
228*2139Sjp161948 	if (!(tt->flags & ASN1_TFLG_ADB_MASK))
229*2139Sjp161948 		return tt;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 	/* Else ANY DEFINED BY ... get the table */
2320Sstevel@tonic-gate 	adb = ASN1_ADB_ptr(tt->item);
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	/* Get the selector field */
2350Sstevel@tonic-gate 	sfld = offset2ptr(*pval, adb->offset);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	/* Check if NULL */
238*2139Sjp161948 	if (!sfld)
239*2139Sjp161948 		{
240*2139Sjp161948 		if (!adb->null_tt)
241*2139Sjp161948 			goto err;
2420Sstevel@tonic-gate 		return adb->null_tt;
243*2139Sjp161948 		}
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	/* Convert type to a long:
2460Sstevel@tonic-gate 	 * NB: don't check for NID_undef here because it
2470Sstevel@tonic-gate 	 * might be a legitimate value in the table
2480Sstevel@tonic-gate 	 */
249*2139Sjp161948 	if (tt->flags & ASN1_TFLG_ADB_OID)
2500Sstevel@tonic-gate 		selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld);
2510Sstevel@tonic-gate 	else
2520Sstevel@tonic-gate 		selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/* Try to find matching entry in table
2550Sstevel@tonic-gate 	 * Maybe should check application types first to
2560Sstevel@tonic-gate 	 * allow application override? Might also be useful
2570Sstevel@tonic-gate 	 * to have a flag which indicates table is sorted and
2580Sstevel@tonic-gate 	 * we can do a binary search. For now stick to a
2590Sstevel@tonic-gate 	 * linear search.
2600Sstevel@tonic-gate 	 */
2610Sstevel@tonic-gate 
262*2139Sjp161948 	for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++)
263*2139Sjp161948 		if (atbl->value == selector)
264*2139Sjp161948 			return &atbl->tt;
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	/* FIXME: need to search application table too */
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 	/* No match, return default type */
269*2139Sjp161948 	if (!adb->default_tt)
270*2139Sjp161948 		goto err;
2710Sstevel@tonic-gate 	return adb->default_tt;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	err:
2740Sstevel@tonic-gate 	/* FIXME: should log the value or OID of unsupported type */
275*2139Sjp161948 	if (nullerr)
276*2139Sjp161948 		ASN1err(ASN1_F_ASN1_DO_ADB,
277*2139Sjp161948 			ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE);
2780Sstevel@tonic-gate 	return NULL;
279*2139Sjp161948 	}
280