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