xref: /onnv-gate/usr/src/common/openssl/crypto/asn1/tasn_enc.c (revision 2139:6243c3338933)
10Sstevel@tonic-gate /* tasn_enc.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>
62*2139Sjp161948 #include "cryptlib.h"
630Sstevel@tonic-gate #include <openssl/asn1.h>
640Sstevel@tonic-gate #include <openssl/asn1t.h>
650Sstevel@tonic-gate #include <openssl/objects.h>
660Sstevel@tonic-gate 
67*2139Sjp161948 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
68*2139Sjp161948 					const ASN1_ITEM *it,
69*2139Sjp161948 					int tag, int aclass);
70*2139Sjp161948 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
71*2139Sjp161948 					int skcontlen, const ASN1_ITEM *item,
72*2139Sjp161948 					int do_sort, int iclass);
73*2139Sjp161948 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
74*2139Sjp161948 					const ASN1_TEMPLATE *tt,
75*2139Sjp161948 					int tag, int aclass);
76*2139Sjp161948 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
77*2139Sjp161948 					const ASN1_ITEM *it, int flags);
780Sstevel@tonic-gate 
79*2139Sjp161948 /* Top level i2d equivalents: the 'ndef' variant instructs the encoder
80*2139Sjp161948  * to use indefinite length constructed encoding, where appropriate
81*2139Sjp161948  */
82*2139Sjp161948 
ASN1_item_ndef_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)83*2139Sjp161948 int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
84*2139Sjp161948 						const ASN1_ITEM *it)
85*2139Sjp161948 	{
86*2139Sjp161948 	return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
87*2139Sjp161948 	}
88*2139Sjp161948 
ASN1_item_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it)89*2139Sjp161948 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
90*2139Sjp161948 	{
91*2139Sjp161948 	return asn1_item_flags_i2d(val, out, it, 0);
92*2139Sjp161948 	}
93*2139Sjp161948 
94*2139Sjp161948 /* Encode an ASN1 item, this is use by the
950Sstevel@tonic-gate  * standard 'i2d' function. 'out' points to
96*2139Sjp161948  * a buffer to output the data to.
970Sstevel@tonic-gate  *
980Sstevel@tonic-gate  * The new i2d has one additional feature. If the output
990Sstevel@tonic-gate  * buffer is NULL (i.e. *out == NULL) then a buffer is
1000Sstevel@tonic-gate  * allocated and populated with the encoding.
1010Sstevel@tonic-gate  */
1020Sstevel@tonic-gate 
asn1_item_flags_i2d(ASN1_VALUE * val,unsigned char ** out,const ASN1_ITEM * it,int flags)103*2139Sjp161948 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
104*2139Sjp161948 					const ASN1_ITEM *it, int flags)
105*2139Sjp161948 	{
106*2139Sjp161948 	if (out && !*out)
107*2139Sjp161948 		{
1080Sstevel@tonic-gate 		unsigned char *p, *buf;
1090Sstevel@tonic-gate 		int len;
110*2139Sjp161948 		len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
111*2139Sjp161948 		if (len <= 0)
112*2139Sjp161948 			return len;
1130Sstevel@tonic-gate 		buf = OPENSSL_malloc(len);
114*2139Sjp161948 		if (!buf)
115*2139Sjp161948 			return -1;
1160Sstevel@tonic-gate 		p = buf;
117*2139Sjp161948 		ASN1_item_ex_i2d(&val, &p, it, -1, flags);
1180Sstevel@tonic-gate 		*out = buf;
1190Sstevel@tonic-gate 		return len;
120*2139Sjp161948 		}
121*2139Sjp161948 
122*2139Sjp161948 	return ASN1_item_ex_i2d(&val, out, it, -1, flags);
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate /* Encode an item, taking care of IMPLICIT tagging (if any).
1260Sstevel@tonic-gate  * This function performs the normal item handling: it can be
1270Sstevel@tonic-gate  * used in external types.
1280Sstevel@tonic-gate  */
1290Sstevel@tonic-gate 
ASN1_item_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)130*2139Sjp161948 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
131*2139Sjp161948 			const ASN1_ITEM *it, int tag, int aclass)
132*2139Sjp161948 	{
1330Sstevel@tonic-gate 	const ASN1_TEMPLATE *tt = NULL;
1340Sstevel@tonic-gate 	unsigned char *p = NULL;
135*2139Sjp161948 	int i, seqcontlen, seqlen, ndef = 1;
1360Sstevel@tonic-gate 	const ASN1_COMPAT_FUNCS *cf;
1370Sstevel@tonic-gate 	const ASN1_EXTERN_FUNCS *ef;
1380Sstevel@tonic-gate 	const ASN1_AUX *aux = it->funcs;
139*2139Sjp161948 	ASN1_aux_cb *asn1_cb = 0;
140*2139Sjp161948 
141*2139Sjp161948 	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
142*2139Sjp161948 		return 0;
1430Sstevel@tonic-gate 
144*2139Sjp161948 	if (aux && aux->asn1_cb)
145*2139Sjp161948 		 asn1_cb = aux->asn1_cb;
146*2139Sjp161948 
147*2139Sjp161948 	switch(it->itype)
148*2139Sjp161948 		{
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 		case ASN1_ITYPE_PRIMITIVE:
151*2139Sjp161948 		if (it->templates)
152*2139Sjp161948 			return asn1_template_ex_i2d(pval, out, it->templates,
153*2139Sjp161948 								tag, aclass);
1540Sstevel@tonic-gate 		return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
1550Sstevel@tonic-gate 		break;
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 		case ASN1_ITYPE_MSTRING:
158*2139Sjp161948 		return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 		case ASN1_ITYPE_CHOICE:
161*2139Sjp161948 		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
1620Sstevel@tonic-gate 				return 0;
1630Sstevel@tonic-gate 		i = asn1_get_choice_selector(pval, it);
164*2139Sjp161948 		if ((i >= 0) && (i < it->tcount))
165*2139Sjp161948 			{
1660Sstevel@tonic-gate 			ASN1_VALUE **pchval;
1670Sstevel@tonic-gate 			const ASN1_TEMPLATE *chtt;
1680Sstevel@tonic-gate 			chtt = it->templates + i;
1690Sstevel@tonic-gate 			pchval = asn1_get_field_ptr(pval, chtt);
170*2139Sjp161948 			return asn1_template_ex_i2d(pchval, out, chtt,
171*2139Sjp161948 								-1, aclass);
172*2139Sjp161948 			}
1730Sstevel@tonic-gate 		/* Fixme: error condition if selector out of range */
174*2139Sjp161948 		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
1750Sstevel@tonic-gate 				return 0;
1760Sstevel@tonic-gate 		break;
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		case ASN1_ITYPE_EXTERN:
1790Sstevel@tonic-gate 		/* If new style i2d it does all the work */
1800Sstevel@tonic-gate 		ef = it->funcs;
1810Sstevel@tonic-gate 		return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 		case ASN1_ITYPE_COMPAT:
1840Sstevel@tonic-gate 		/* old style hackery... */
1850Sstevel@tonic-gate 		cf = it->funcs;
186*2139Sjp161948 		if (out)
187*2139Sjp161948 			p = *out;
1880Sstevel@tonic-gate 		i = cf->asn1_i2d(*pval, out);
1890Sstevel@tonic-gate 		/* Fixup for IMPLICIT tag: note this messes up for tags > 30,
1900Sstevel@tonic-gate 		 * but so did the old code. Tags > 30 are very rare anyway.
1910Sstevel@tonic-gate 		 */
192*2139Sjp161948 		if (out && (tag != -1))
1930Sstevel@tonic-gate 			*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
1940Sstevel@tonic-gate 		return i;
1950Sstevel@tonic-gate 
196*2139Sjp161948 		case ASN1_ITYPE_NDEF_SEQUENCE:
197*2139Sjp161948 		/* Use indefinite length constructed if requested */
198*2139Sjp161948 		if (aclass & ASN1_TFLG_NDEF) ndef = 2;
199*2139Sjp161948 		/* fall through */
200*2139Sjp161948 
2010Sstevel@tonic-gate 		case ASN1_ITYPE_SEQUENCE:
2020Sstevel@tonic-gate 		i = asn1_enc_restore(&seqcontlen, out, pval, it);
2030Sstevel@tonic-gate 		/* An error occurred */
204*2139Sjp161948 		if (i < 0)
205*2139Sjp161948 			return 0;
2060Sstevel@tonic-gate 		/* We have a valid cached encoding... */
207*2139Sjp161948 		if (i > 0)
208*2139Sjp161948 			return seqcontlen;
2090Sstevel@tonic-gate 		/* Otherwise carry on */
2100Sstevel@tonic-gate 		seqcontlen = 0;
2110Sstevel@tonic-gate 		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
212*2139Sjp161948 		if (tag == -1)
213*2139Sjp161948 			{
2140Sstevel@tonic-gate 			tag = V_ASN1_SEQUENCE;
215*2139Sjp161948 			/* Retain any other flags in aclass */
216*2139Sjp161948 			aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
217*2139Sjp161948 					| V_ASN1_UNIVERSAL;
218*2139Sjp161948 			}
219*2139Sjp161948 		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
2200Sstevel@tonic-gate 				return 0;
2210Sstevel@tonic-gate 		/* First work out sequence content length */
222*2139Sjp161948 		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
223*2139Sjp161948 			{
2240Sstevel@tonic-gate 			const ASN1_TEMPLATE *seqtt;
2250Sstevel@tonic-gate 			ASN1_VALUE **pseqval;
2260Sstevel@tonic-gate 			seqtt = asn1_do_adb(pval, tt, 1);
227*2139Sjp161948 			if (!seqtt)
228*2139Sjp161948 				return 0;
2290Sstevel@tonic-gate 			pseqval = asn1_get_field_ptr(pval, seqtt);
2300Sstevel@tonic-gate 			/* FIXME: check for errors in enhanced version */
231*2139Sjp161948 			seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
232*2139Sjp161948 								-1, aclass);
233*2139Sjp161948 			}
234*2139Sjp161948 
235*2139Sjp161948 		seqlen = ASN1_object_size(ndef, seqcontlen, tag);
236*2139Sjp161948 		if (!out)
237*2139Sjp161948 			return seqlen;
2380Sstevel@tonic-gate 		/* Output SEQUENCE header */
239*2139Sjp161948 		ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
240*2139Sjp161948 		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
241*2139Sjp161948 			{
2420Sstevel@tonic-gate 			const ASN1_TEMPLATE *seqtt;
2430Sstevel@tonic-gate 			ASN1_VALUE **pseqval;
2440Sstevel@tonic-gate 			seqtt = asn1_do_adb(pval, tt, 1);
245*2139Sjp161948 			if (!seqtt)
246*2139Sjp161948 				return 0;
2470Sstevel@tonic-gate 			pseqval = asn1_get_field_ptr(pval, seqtt);
2480Sstevel@tonic-gate 			/* FIXME: check for errors in enhanced version */
249*2139Sjp161948 			asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
250*2139Sjp161948 			}
251*2139Sjp161948 		if (ndef == 2)
252*2139Sjp161948 			ASN1_put_eoc(out);
253*2139Sjp161948 		if (asn1_cb  && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
2540Sstevel@tonic-gate 				return 0;
2550Sstevel@tonic-gate 		return seqlen;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 		default:
2580Sstevel@tonic-gate 		return 0;
259*2139Sjp161948 
260*2139Sjp161948 		}
2610Sstevel@tonic-gate 	return 0;
262*2139Sjp161948 	}
263*2139Sjp161948 
ASN1_template_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt)264*2139Sjp161948 int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
265*2139Sjp161948 							const ASN1_TEMPLATE *tt)
266*2139Sjp161948 	{
267*2139Sjp161948 	return asn1_template_ex_i2d(pval, out, tt, -1, 0);
268*2139Sjp161948 	}
2690Sstevel@tonic-gate 
asn1_template_ex_i2d(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_TEMPLATE * tt,int tag,int iclass)270*2139Sjp161948 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
271*2139Sjp161948 				const ASN1_TEMPLATE *tt, int tag, int iclass)
272*2139Sjp161948 	{
273*2139Sjp161948 	int i, ret, flags, ttag, tclass, ndef;
2740Sstevel@tonic-gate 	flags = tt->flags;
275*2139Sjp161948 	/* Work out tag and class to use: tagging may come
276*2139Sjp161948 	 * either from the template or the arguments, not both
277*2139Sjp161948 	 * because this would create ambiguity. Additionally
278*2139Sjp161948 	 * the iclass argument may contain some additional flags
279*2139Sjp161948 	 * which should be noted and passed down to other levels.
280*2139Sjp161948 	 */
281*2139Sjp161948 	if (flags & ASN1_TFLG_TAG_MASK)
282*2139Sjp161948 		{
283*2139Sjp161948 		/* Error if argument and template tagging */
284*2139Sjp161948 		if (tag != -1)
285*2139Sjp161948 			/* FIXME: error code here */
286*2139Sjp161948 			return -1;
287*2139Sjp161948 		/* Get tagging from template */
288*2139Sjp161948 		ttag = tt->tag;
289*2139Sjp161948 		tclass = flags & ASN1_TFLG_TAG_CLASS;
290*2139Sjp161948 		}
291*2139Sjp161948 	else if (tag != -1)
292*2139Sjp161948 		{
293*2139Sjp161948 		/* No template tagging, get from arguments */
294*2139Sjp161948 		ttag = tag;
295*2139Sjp161948 		tclass = iclass & ASN1_TFLG_TAG_CLASS;
296*2139Sjp161948 		}
297*2139Sjp161948 	else
298*2139Sjp161948 		{
299*2139Sjp161948 		ttag = -1;
300*2139Sjp161948 		tclass = 0;
301*2139Sjp161948 		}
302*2139Sjp161948 	/*
303*2139Sjp161948 	 * Remove any class mask from iflag.
304*2139Sjp161948 	 */
305*2139Sjp161948 	iclass &= ~ASN1_TFLG_TAG_CLASS;
306*2139Sjp161948 
307*2139Sjp161948 	/* At this point 'ttag' contains the outer tag to use,
308*2139Sjp161948 	 * 'tclass' is the class and iclass is any flags passed
309*2139Sjp161948 	 * to this function.
310*2139Sjp161948 	 */
311*2139Sjp161948 
312*2139Sjp161948 	/* if template and arguments require ndef, use it */
313*2139Sjp161948 	if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
314*2139Sjp161948 		ndef = 2;
315*2139Sjp161948 	else ndef = 1;
316*2139Sjp161948 
317*2139Sjp161948 	if (flags & ASN1_TFLG_SK_MASK)
318*2139Sjp161948 		{
3190Sstevel@tonic-gate 		/* SET OF, SEQUENCE OF */
3200Sstevel@tonic-gate 		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
3210Sstevel@tonic-gate 		int isset, sktag, skaclass;
3220Sstevel@tonic-gate 		int skcontlen, sklen;
3230Sstevel@tonic-gate 		ASN1_VALUE *skitem;
324*2139Sjp161948 
325*2139Sjp161948 		if (!*pval)
326*2139Sjp161948 			return 0;
327*2139Sjp161948 
328*2139Sjp161948 		if (flags & ASN1_TFLG_SET_OF)
329*2139Sjp161948 			{
3300Sstevel@tonic-gate 			isset = 1;
3310Sstevel@tonic-gate 			/* 2 means we reorder */
332*2139Sjp161948 			if (flags & ASN1_TFLG_SEQUENCE_OF)
333*2139Sjp161948 				isset = 2;
334*2139Sjp161948 			}
335*2139Sjp161948 		else isset = 0;
336*2139Sjp161948 
337*2139Sjp161948 		/* Work out inner tag value: if EXPLICIT
338*2139Sjp161948 		 * or no tagging use underlying type.
339*2139Sjp161948 		 */
340*2139Sjp161948 		if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
341*2139Sjp161948 			{
342*2139Sjp161948 			sktag = ttag;
343*2139Sjp161948 			skaclass = tclass;
344*2139Sjp161948 			}
345*2139Sjp161948 		else
346*2139Sjp161948 			{
3470Sstevel@tonic-gate 			skaclass = V_ASN1_UNIVERSAL;
348*2139Sjp161948 			if (isset)
349*2139Sjp161948 				sktag = V_ASN1_SET;
3500Sstevel@tonic-gate 			else sktag = V_ASN1_SEQUENCE;
351*2139Sjp161948 			}
352*2139Sjp161948 
353*2139Sjp161948 		/* Determine total length of items */
3540Sstevel@tonic-gate 		skcontlen = 0;
355*2139Sjp161948 		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
356*2139Sjp161948 			{
3570Sstevel@tonic-gate 			skitem = sk_ASN1_VALUE_value(sk, i);
358*2139Sjp161948 			skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
359*2139Sjp161948 						ASN1_ITEM_ptr(tt->item),
360*2139Sjp161948 							-1, iclass);
361*2139Sjp161948 			}
362*2139Sjp161948 		sklen = ASN1_object_size(ndef, skcontlen, sktag);
3630Sstevel@tonic-gate 		/* If EXPLICIT need length of surrounding tag */
364*2139Sjp161948 		if (flags & ASN1_TFLG_EXPTAG)
365*2139Sjp161948 			ret = ASN1_object_size(ndef, sklen, ttag);
3660Sstevel@tonic-gate 		else ret = sklen;
3670Sstevel@tonic-gate 
368*2139Sjp161948 		if (!out)
369*2139Sjp161948 			return ret;
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 		/* Now encode this lot... */
3720Sstevel@tonic-gate 		/* EXPLICIT tag */
373*2139Sjp161948 		if (flags & ASN1_TFLG_EXPTAG)
374*2139Sjp161948 			ASN1_put_object(out, ndef, sklen, ttag, tclass);
3750Sstevel@tonic-gate 		/* SET or SEQUENCE and IMPLICIT tag */
376*2139Sjp161948 		ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
377*2139Sjp161948 		/* And the stuff itself */
378*2139Sjp161948 		asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
379*2139Sjp161948 								isset, iclass);
380*2139Sjp161948 		if (ndef == 2)
381*2139Sjp161948 			{
382*2139Sjp161948 			ASN1_put_eoc(out);
383*2139Sjp161948 			if (flags & ASN1_TFLG_EXPTAG)
384*2139Sjp161948 				ASN1_put_eoc(out);
385*2139Sjp161948 			}
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 		return ret;
388*2139Sjp161948 		}
389*2139Sjp161948 
390*2139Sjp161948 	if (flags & ASN1_TFLG_EXPTAG)
391*2139Sjp161948 		{
3920Sstevel@tonic-gate 		/* EXPLICIT tagging */
3930Sstevel@tonic-gate 		/* Find length of tagged item */
394*2139Sjp161948 		i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
395*2139Sjp161948 								-1, iclass);
396*2139Sjp161948 		if (!i)
397*2139Sjp161948 			return 0;
3980Sstevel@tonic-gate 		/* Find length of EXPLICIT tag */
399*2139Sjp161948 		ret = ASN1_object_size(ndef, i, ttag);
400*2139Sjp161948 		if (out)
401*2139Sjp161948 			{
4020Sstevel@tonic-gate 			/* Output tag and item */
403*2139Sjp161948 			ASN1_put_object(out, ndef, i, ttag, tclass);
404*2139Sjp161948 			ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
405*2139Sjp161948 								-1, iclass);
406*2139Sjp161948 			if (ndef == 2)
407*2139Sjp161948 				ASN1_put_eoc(out);
408*2139Sjp161948 			}
409*2139Sjp161948 		return ret;
4100Sstevel@tonic-gate 		}
411*2139Sjp161948 
412*2139Sjp161948 	/* Either normal or IMPLICIT tagging: combine class and flags */
413*2139Sjp161948 	return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
414*2139Sjp161948 						ttag, tclass | iclass);
415*2139Sjp161948 
4160Sstevel@tonic-gate }
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate /* Temporary structure used to hold DER encoding of items for SET OF */
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate typedef	struct {
4210Sstevel@tonic-gate 	unsigned char *data;
4220Sstevel@tonic-gate 	int length;
4230Sstevel@tonic-gate 	ASN1_VALUE *field;
4240Sstevel@tonic-gate } DER_ENC;
4250Sstevel@tonic-gate 
der_cmp(const void * a,const void * b)4260Sstevel@tonic-gate static int der_cmp(const void *a, const void *b)
427*2139Sjp161948 	{
4280Sstevel@tonic-gate 	const DER_ENC *d1 = a, *d2 = b;
4290Sstevel@tonic-gate 	int cmplen, i;
4300Sstevel@tonic-gate 	cmplen = (d1->length < d2->length) ? d1->length : d2->length;
4310Sstevel@tonic-gate 	i = memcmp(d1->data, d2->data, cmplen);
432*2139Sjp161948 	if (i)
433*2139Sjp161948 		return i;
4340Sstevel@tonic-gate 	return d1->length - d2->length;
435*2139Sjp161948 	}
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate /* Output the content octets of SET OF or SEQUENCE OF */
4380Sstevel@tonic-gate 
asn1_set_seq_out(STACK_OF (ASN1_VALUE)* sk,unsigned char ** out,int skcontlen,const ASN1_ITEM * item,int do_sort,int iclass)439*2139Sjp161948 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
440*2139Sjp161948 					int skcontlen, const ASN1_ITEM *item,
441*2139Sjp161948 					int do_sort, int iclass)
442*2139Sjp161948 	{
4430Sstevel@tonic-gate 	int i;
4440Sstevel@tonic-gate 	ASN1_VALUE *skitem;
4450Sstevel@tonic-gate 	unsigned char *tmpdat = NULL, *p = NULL;
4460Sstevel@tonic-gate 	DER_ENC *derlst = NULL, *tder;
447*2139Sjp161948 	if (do_sort)
448*2139Sjp161948 		 {
4490Sstevel@tonic-gate 		/* Don't need to sort less than 2 items */
450*2139Sjp161948 		if (sk_ASN1_VALUE_num(sk) < 2)
451*2139Sjp161948 			do_sort = 0;
452*2139Sjp161948 		else
453*2139Sjp161948 			{
454*2139Sjp161948 			derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
455*2139Sjp161948 						* sizeof(*derlst));
4560Sstevel@tonic-gate 			tmpdat = OPENSSL_malloc(skcontlen);
457*2139Sjp161948 			if (!derlst || !tmpdat)
458*2139Sjp161948 				return 0;
459*2139Sjp161948 			}
4600Sstevel@tonic-gate 		}
4610Sstevel@tonic-gate 	/* If not sorting just output each item */
462*2139Sjp161948 	if (!do_sort)
463*2139Sjp161948 		{
464*2139Sjp161948 		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
465*2139Sjp161948 			{
4660Sstevel@tonic-gate 			skitem = sk_ASN1_VALUE_value(sk, i);
467*2139Sjp161948 			ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
468*2139Sjp161948 			}
469*2139Sjp161948 		return 1;
4700Sstevel@tonic-gate 		}
4710Sstevel@tonic-gate 	p = tmpdat;
472*2139Sjp161948 
4730Sstevel@tonic-gate 	/* Doing sort: build up a list of each member's DER encoding */
474*2139Sjp161948 	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
475*2139Sjp161948 		{
4760Sstevel@tonic-gate 		skitem = sk_ASN1_VALUE_value(sk, i);
4770Sstevel@tonic-gate 		tder->data = p;
478*2139Sjp161948 		tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
4790Sstevel@tonic-gate 		tder->field = skitem;
480*2139Sjp161948 		}
481*2139Sjp161948 
4820Sstevel@tonic-gate 	/* Now sort them */
4830Sstevel@tonic-gate 	qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
4840Sstevel@tonic-gate 	/* Output sorted DER encoding */
4850Sstevel@tonic-gate 	p = *out;
486*2139Sjp161948 	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
487*2139Sjp161948 		{
4880Sstevel@tonic-gate 		memcpy(p, tder->data, tder->length);
4890Sstevel@tonic-gate 		p += tder->length;
490*2139Sjp161948 		}
4910Sstevel@tonic-gate 	*out = p;
4920Sstevel@tonic-gate 	/* If do_sort is 2 then reorder the STACK */
493*2139Sjp161948 	if (do_sort == 2)
494*2139Sjp161948 		{
495*2139Sjp161948 		for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
496*2139Sjp161948 							i++, tder++)
4970Sstevel@tonic-gate 			sk_ASN1_VALUE_set(sk, i, tder->field);
498*2139Sjp161948 		}
4990Sstevel@tonic-gate 	OPENSSL_free(derlst);
5000Sstevel@tonic-gate 	OPENSSL_free(tmpdat);
5010Sstevel@tonic-gate 	return 1;
502*2139Sjp161948 	}
5030Sstevel@tonic-gate 
asn1_i2d_ex_primitive(ASN1_VALUE ** pval,unsigned char ** out,const ASN1_ITEM * it,int tag,int aclass)504*2139Sjp161948 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
505*2139Sjp161948 				const ASN1_ITEM *it, int tag, int aclass)
506*2139Sjp161948 	{
5070Sstevel@tonic-gate 	int len;
5080Sstevel@tonic-gate 	int utype;
5090Sstevel@tonic-gate 	int usetag;
510*2139Sjp161948 	int ndef = 0;
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 	utype = it->utype;
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 	/* Get length of content octets and maybe find
5150Sstevel@tonic-gate 	 * out the underlying type.
5160Sstevel@tonic-gate 	 */
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	len = asn1_ex_i2c(pval, NULL, &utype, it);
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	/* If SEQUENCE, SET or OTHER then header is
5210Sstevel@tonic-gate 	 * included in pseudo content octets so don't
5220Sstevel@tonic-gate 	 * include tag+length. We need to check here
5230Sstevel@tonic-gate 	 * because the call to asn1_ex_i2c() could change
5240Sstevel@tonic-gate 	 * utype.
5250Sstevel@tonic-gate 	 */
526*2139Sjp161948 	if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
5270Sstevel@tonic-gate 	   (utype == V_ASN1_OTHER))
5280Sstevel@tonic-gate 		usetag = 0;
5290Sstevel@tonic-gate 	else usetag = 1;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	/* -1 means omit type */
5320Sstevel@tonic-gate 
533*2139Sjp161948 	if (len == -1)
534*2139Sjp161948 		return 0;
535*2139Sjp161948 
536*2139Sjp161948 	/* -2 return is special meaning use ndef */
537*2139Sjp161948 	if (len == -2)
538*2139Sjp161948 		{
539*2139Sjp161948 		ndef = 2;
540*2139Sjp161948 		len = 0;
541*2139Sjp161948 		}
5420Sstevel@tonic-gate 
5430Sstevel@tonic-gate 	/* If not implicitly tagged get tag from underlying type */
544*2139Sjp161948 	if (tag == -1) tag = utype;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 	/* Output tag+length followed by content octets */
547*2139Sjp161948 	if (out)
548*2139Sjp161948 		{
549*2139Sjp161948 		if (usetag)
550*2139Sjp161948 			ASN1_put_object(out, ndef, len, tag, aclass);
5510Sstevel@tonic-gate 		asn1_ex_i2c(pval, *out, &utype, it);
552*2139Sjp161948 		if (ndef)
553*2139Sjp161948 			ASN1_put_eoc(out);
554*2139Sjp161948 		else
555*2139Sjp161948 			*out += len;
556*2139Sjp161948 		}
557*2139Sjp161948 
558*2139Sjp161948 	if (usetag)
559*2139Sjp161948 		return ASN1_object_size(ndef, len, tag);
560*2139Sjp161948 	return len;
5610Sstevel@tonic-gate 	}
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate /* Produce content octets from a structure */
5640Sstevel@tonic-gate 
asn1_ex_i2c(ASN1_VALUE ** pval,unsigned char * cout,int * putype,const ASN1_ITEM * it)565*2139Sjp161948 int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
566*2139Sjp161948 				const ASN1_ITEM *it)
567*2139Sjp161948 	{
5680Sstevel@tonic-gate 	ASN1_BOOLEAN *tbool = NULL;
5690Sstevel@tonic-gate 	ASN1_STRING *strtmp;
5700Sstevel@tonic-gate 	ASN1_OBJECT *otmp;
5710Sstevel@tonic-gate 	int utype;
5720Sstevel@tonic-gate 	unsigned char *cont, c;
5730Sstevel@tonic-gate 	int len;
5740Sstevel@tonic-gate 	const ASN1_PRIMITIVE_FUNCS *pf;
5750Sstevel@tonic-gate 	pf = it->funcs;
576*2139Sjp161948 	if (pf && pf->prim_i2c)
577*2139Sjp161948 		return pf->prim_i2c(pval, cout, putype, it);
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	/* Should type be omitted? */
580*2139Sjp161948 	if ((it->itype != ASN1_ITYPE_PRIMITIVE)
581*2139Sjp161948 		|| (it->utype != V_ASN1_BOOLEAN))
582*2139Sjp161948 		{
583*2139Sjp161948 		if (!*pval) return -1;
584*2139Sjp161948 		}
5850Sstevel@tonic-gate 
586*2139Sjp161948 	if (it->itype == ASN1_ITYPE_MSTRING)
587*2139Sjp161948 		{
5880Sstevel@tonic-gate 		/* If MSTRING type set the underlying type */
5890Sstevel@tonic-gate 		strtmp = (ASN1_STRING *)*pval;
5900Sstevel@tonic-gate 		utype = strtmp->type;
5910Sstevel@tonic-gate 		*putype = utype;
592*2139Sjp161948 		}
593*2139Sjp161948 	else if (it->utype == V_ASN1_ANY)
594*2139Sjp161948 		{
5950Sstevel@tonic-gate 		/* If ANY set type and pointer to value */
5960Sstevel@tonic-gate 		ASN1_TYPE *typ;
5970Sstevel@tonic-gate 		typ = (ASN1_TYPE *)*pval;
5980Sstevel@tonic-gate 		utype = typ->type;
5990Sstevel@tonic-gate 		*putype = utype;
6000Sstevel@tonic-gate 		pval = (ASN1_VALUE **)&typ->value.ptr;
601*2139Sjp161948 		}
602*2139Sjp161948 	else utype = *putype;
6030Sstevel@tonic-gate 
604*2139Sjp161948 	switch(utype)
605*2139Sjp161948 		{
6060Sstevel@tonic-gate 		case V_ASN1_OBJECT:
6070Sstevel@tonic-gate 		otmp = (ASN1_OBJECT *)*pval;
6080Sstevel@tonic-gate 		cont = otmp->data;
6090Sstevel@tonic-gate 		len = otmp->length;
6100Sstevel@tonic-gate 		break;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 		case V_ASN1_NULL:
6130Sstevel@tonic-gate 		cont = NULL;
6140Sstevel@tonic-gate 		len = 0;
6150Sstevel@tonic-gate 		break;
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 		case V_ASN1_BOOLEAN:
6180Sstevel@tonic-gate 		tbool = (ASN1_BOOLEAN *)pval;
619*2139Sjp161948 		if (*tbool == -1)
620*2139Sjp161948 			return -1;
6210Sstevel@tonic-gate 		/* Default handling if value == size field then omit */
622*2139Sjp161948 		if (*tbool && (it->size > 0))
623*2139Sjp161948 			return -1;
624*2139Sjp161948 		if (!*tbool && !it->size)
625*2139Sjp161948 			return -1;
6260Sstevel@tonic-gate 		c = (unsigned char)*tbool;
6270Sstevel@tonic-gate 		cont = &c;
6280Sstevel@tonic-gate 		len = 1;
6290Sstevel@tonic-gate 		break;
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 		case V_ASN1_BIT_STRING:
632*2139Sjp161948 		return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
633*2139Sjp161948 							cout ? &cout : NULL);
6340Sstevel@tonic-gate 		break;
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 		case V_ASN1_INTEGER:
6370Sstevel@tonic-gate 		case V_ASN1_NEG_INTEGER:
6380Sstevel@tonic-gate 		case V_ASN1_ENUMERATED:
6390Sstevel@tonic-gate 		case V_ASN1_NEG_ENUMERATED:
6400Sstevel@tonic-gate 		/* These are all have the same content format
6410Sstevel@tonic-gate 		 * as ASN1_INTEGER
6420Sstevel@tonic-gate 		 */
643*2139Sjp161948 		return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
644*2139Sjp161948 							cout ? &cout : NULL);
6450Sstevel@tonic-gate 		break;
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		case V_ASN1_OCTET_STRING:
6480Sstevel@tonic-gate 		case V_ASN1_NUMERICSTRING:
6490Sstevel@tonic-gate 		case V_ASN1_PRINTABLESTRING:
6500Sstevel@tonic-gate 		case V_ASN1_T61STRING:
6510Sstevel@tonic-gate 		case V_ASN1_VIDEOTEXSTRING:
6520Sstevel@tonic-gate 		case V_ASN1_IA5STRING:
6530Sstevel@tonic-gate 		case V_ASN1_UTCTIME:
6540Sstevel@tonic-gate 		case V_ASN1_GENERALIZEDTIME:
6550Sstevel@tonic-gate 		case V_ASN1_GRAPHICSTRING:
6560Sstevel@tonic-gate 		case V_ASN1_VISIBLESTRING:
6570Sstevel@tonic-gate 		case V_ASN1_GENERALSTRING:
6580Sstevel@tonic-gate 		case V_ASN1_UNIVERSALSTRING:
6590Sstevel@tonic-gate 		case V_ASN1_BMPSTRING:
6600Sstevel@tonic-gate 		case V_ASN1_UTF8STRING:
6610Sstevel@tonic-gate 		case V_ASN1_SEQUENCE:
6620Sstevel@tonic-gate 		case V_ASN1_SET:
6630Sstevel@tonic-gate 		default:
6640Sstevel@tonic-gate 		/* All based on ASN1_STRING and handled the same */
6650Sstevel@tonic-gate 		strtmp = (ASN1_STRING *)*pval;
666*2139Sjp161948 		/* Special handling for NDEF */
667*2139Sjp161948 		if ((it->size == ASN1_TFLG_NDEF)
668*2139Sjp161948 			&& (strtmp->flags & ASN1_STRING_FLAG_NDEF))
669*2139Sjp161948 			{
670*2139Sjp161948 			if (cout)
671*2139Sjp161948 				{
672*2139Sjp161948 				strtmp->data = cout;
673*2139Sjp161948 				strtmp->length = 0;
674*2139Sjp161948 				}
675*2139Sjp161948 			/* Special return code */
676*2139Sjp161948 			return -2;
677*2139Sjp161948 			}
6780Sstevel@tonic-gate 		cont = strtmp->data;
6790Sstevel@tonic-gate 		len = strtmp->length;
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 		break;
6820Sstevel@tonic-gate 
683*2139Sjp161948 		}
684*2139Sjp161948 	if (cout && len)
685*2139Sjp161948 		memcpy(cout, cont, len);
686*2139Sjp161948 	return len;
6870Sstevel@tonic-gate 	}
688