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