4b2784987a86991328fa2894a392509e38fffda5
[openssl.git] / crypto / asn1 / tasn_enc.c
1 /* tasn_enc.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59
60 #include <stddef.h>
61 #include <openssl/asn1.h>
62 #include <openssl/asn1t.h>
63 #include <openssl/objects.h>
64
65 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
66 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset);
67
68 /* Encode an ASN1 item, this is compatible with the
69  * standard 'i2d' function. 'out' points to 
70  * a buffer to output the data to, in future we will
71  * have more advanced versions that can output data
72  * a piece at a time and this will simply be a special
73  * case.
74  *
75  * The new i2d has one additional feature. If the output
76  * buffer is NULL (i.e. *out == NULL) then a buffer is
77  * allocated and populated with the encoding.
78  */
79
80
81 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
82 {
83         if(out && !*out) {
84                 unsigned char *p, *buf;
85                 int len;
86                 len = ASN1_item_ex_i2d(&val, NULL, it, -1, 0);
87                 if(len <= 0) return len;
88                 buf = OPENSSL_malloc(len);
89                 if(!buf) return -1;
90                 p = buf;
91                 ASN1_item_ex_i2d(&val, &p, it, -1, 0);
92                 *out = buf;
93                 return len;
94         }
95                 
96         return ASN1_item_ex_i2d(&val, out, it, -1, 0);
97 }
98
99 /* Encode an item, taking care of IMPLICIT tagging (if any).
100  * This function performs the normal item handling: it can be
101  * used in external types.
102  */
103
104 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
105 {
106         const ASN1_TEMPLATE *tt = NULL;
107         unsigned char *p = NULL;
108         int i, seqcontlen, seqlen;
109         ASN1_STRING *strtmp;
110         const ASN1_COMPAT_FUNCS *cf;
111         const ASN1_EXTERN_FUNCS *ef;
112         const ASN1_AUX *aux = it->funcs;
113         ASN1_aux_cb *asn1_cb;
114         if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return 0;
115         if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb;
116         else asn1_cb = 0;
117
118         switch(it->itype) {
119
120                 case ASN1_ITYPE_PRIMITIVE:
121                 if(it->templates)
122                         return ASN1_template_i2d(pval, out, it->templates);
123                 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
124                 break;
125
126                 case ASN1_ITYPE_MSTRING:
127                 strtmp = (ASN1_STRING *)*pval;
128                 return asn1_i2d_ex_primitive(pval, out, it, -1, 0);
129
130                 case ASN1_ITYPE_CHOICE:
131                 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
132                                 return 0;
133                 i = asn1_get_choice_selector(pval, it);
134                 if((i >= 0) && (i < it->tcount)) {
135                         ASN1_VALUE **pchval;
136                         const ASN1_TEMPLATE *chtt;
137                         chtt = it->templates + i;
138                         pchval = asn1_get_field_ptr(pval, chtt);
139                         return ASN1_template_i2d(pchval, out, chtt);
140                 } 
141                 /* Fixme: error condition if selector out of range */
142                 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
143                                 return 0;
144                 break;
145
146                 case ASN1_ITYPE_EXTERN:
147                 /* If new style i2d it does all the work */
148                 ef = it->funcs;
149                 return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
150
151                 case ASN1_ITYPE_COMPAT:
152                 /* old style hackery... */
153                 cf = it->funcs;
154                 if(out) p = *out;
155                 i = cf->asn1_i2d(*pval, out);
156                 /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
157                  * but so did the old code. Tags > 30 are very rare anyway.
158                  */
159                 if(out && (tag != -1))
160                         *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
161                 return i;
162                 
163                 case ASN1_ITYPE_SEQUENCE:
164                 i = asn1_enc_restore(&seqcontlen, out, pval, it);
165                 /* An error occurred */
166                 if(i < 0) return 0;
167                 /* We have a valid cached encoding... */
168                 if(i > 0) return seqcontlen;
169                 /* Otherwise carry on */
170                 seqcontlen = 0;
171                 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
172                 if(tag == -1) {
173                         tag = V_ASN1_SEQUENCE;
174                         aclass = V_ASN1_UNIVERSAL;
175                 }
176                 if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
177                                 return 0;
178                 /* First work out sequence content length */
179                 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
180                         const ASN1_TEMPLATE *seqtt;
181                         ASN1_VALUE **pseqval;
182                         seqtt = asn1_do_adb(pval, tt, 1);
183                         if(!seqtt) return 0;
184                         pseqval = asn1_get_field_ptr(pval, seqtt);
185                         /* FIXME: check for errors in enhanced version */
186                         /* FIXME: special handling of indefinite length encoding */
187                         seqcontlen += ASN1_template_i2d(pseqval, NULL, seqtt);
188                 }
189                 seqlen = ASN1_object_size(1, seqcontlen, tag);
190                 if(!out) return seqlen;
191                 /* Output SEQUENCE header */
192                 ASN1_put_object(out, 1, seqcontlen, tag, aclass);
193                 for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
194                         const ASN1_TEMPLATE *seqtt;
195                         ASN1_VALUE **pseqval;
196                         seqtt = asn1_do_adb(pval, tt, 1);
197                         if(!seqtt) return 0;
198                         pseqval = asn1_get_field_ptr(pval, seqtt);
199                         /* FIXME: check for errors in enhanced version */
200                         ASN1_template_i2d(pseqval, out, seqtt);
201                 }
202                 if(asn1_cb  && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
203                                 return 0;
204                 return seqlen;
205
206                 default:
207                 return 0;
208         }
209         return 0;
210 }
211
212 int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt)
213 {
214         int i, ret, flags, aclass;
215         flags = tt->flags;
216         aclass = flags & ASN1_TFLG_TAG_CLASS;
217         if(flags & ASN1_TFLG_SK_MASK) {
218                 /* SET OF, SEQUENCE OF */
219                 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
220                 int isset, sktag, skaclass;
221                 int skcontlen, sklen;
222                 ASN1_VALUE *skitem;
223                 if(!*pval) return 0;
224                 if(flags & ASN1_TFLG_SET_OF) {
225                         isset = 1;
226                         /* 2 means we reorder */
227                         if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2;
228                 } else isset = 0;
229                 /* First work out inner tag value */
230                 if(flags & ASN1_TFLG_IMPTAG) {
231                         sktag = tt->tag;
232                         skaclass = aclass;
233                 } else {
234                         skaclass = V_ASN1_UNIVERSAL;
235                         if(isset) sktag = V_ASN1_SET;
236                         else sktag = V_ASN1_SEQUENCE;
237                 }
238                 /* Now work out length of items */
239                 skcontlen = 0;
240                 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
241                         skitem = sk_ASN1_VALUE_value(sk, i);
242                         skcontlen += ASN1_item_ex_i2d(&skitem, NULL, tt->item, -1, 0);
243                 }
244                 sklen = ASN1_object_size(1, skcontlen, sktag);
245                 /* If EXPLICIT need length of surrounding tag */
246                 if(flags & ASN1_TFLG_EXPTAG)
247                         ret = ASN1_object_size(1, sklen, tt->tag);
248                 else ret = sklen;
249
250                 if(!out) return ret;
251
252                 /* Now encode this lot... */
253                 /* EXPLICIT tag */
254                 if(flags & ASN1_TFLG_EXPTAG)
255                         ASN1_put_object(out, 1, sklen, tt->tag, aclass);
256                 /* SET or SEQUENCE and IMPLICIT tag */
257                 ASN1_put_object(out, 1, skcontlen, sktag, skaclass);
258                 /* And finally the stuff itself */
259                 asn1_set_seq_out(sk, out, skcontlen, tt->item, isset);
260
261                 return ret;
262         }
263                         
264         if(flags & ASN1_TFLG_EXPTAG) {
265                 /* EXPLICIT tagging */
266                 /* Find length of tagged item */
267                 i = ASN1_item_ex_i2d(pval, NULL, tt->item, -1, 0);
268                 if(!i) return 0;
269                 /* Find length of EXPLICIT tag */
270                 ret = ASN1_object_size(1, i, tt->tag);
271                 if(out) {
272                         /* Output tag and item */
273                         ASN1_put_object(out, 1, i, tt->tag, aclass);
274                         ASN1_item_ex_i2d(pval, out, tt->item, -1, 0);
275                 }
276                 return ret;
277         }
278         if(flags & ASN1_TFLG_IMPTAG) {
279                 /* IMPLICIT tagging */
280                 return ASN1_item_ex_i2d(pval, out, tt->item, tt->tag, aclass);
281         }
282         /* Nothing special: treat as normal */
283         return ASN1_item_ex_i2d(pval, out, tt->item, -1, 0);
284 }
285
286 /* Temporary structure used to hold DER encoding of items for SET OF */
287
288 typedef struct {
289         unsigned char *data;
290         int length;
291         ASN1_VALUE *field;
292 } DER_ENC;
293
294 static int der_cmp(const void *a, const void *b)
295 {
296         const DER_ENC *d1 = a, *d2 = b;
297         int cmplen, i;
298         cmplen = (d1->length < d2->length) ? d1->length : d2->length;
299         i = memcmp(d1->data, d2->data, cmplen);
300         if(i) return i;
301         return d1->length - d2->length;
302 }
303
304 /* Output the content octets of SET OF or SEQUENCE OF */
305
306 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort)
307 {
308         int i;
309         ASN1_VALUE *skitem;
310         unsigned char *tmpdat, *p;
311         DER_ENC *derlst, *tder;
312         if(do_sort) {
313                 /* Don't need to sort less than 2 items */
314                 if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0;
315                 else {
316                         derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst));
317                         tmpdat = OPENSSL_malloc(skcontlen);
318                         if(!derlst || !tmpdat) return 0;
319                 }
320         }
321         /* If not sorting just output each item */
322         if(!do_sort) {
323                 for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
324                         skitem = sk_ASN1_VALUE_value(sk, i);
325                         ASN1_item_i2d(skitem, out, item);
326                 }
327                 return 1;
328         }
329         p = tmpdat;
330         /* Doing sort: build up a list of each member's DER encoding */
331         for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
332                 skitem = sk_ASN1_VALUE_value(sk, i);
333                 tder->data = p;
334                 tder->length = ASN1_item_i2d(skitem, &p, item);
335                 tder->field = skitem;
336         }
337         /* Now sort them */
338         qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
339         /* Output sorted DER encoding */        
340         p = *out;
341         for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
342                 memcpy(p, tder->data, tder->length);
343                 p += tder->length;
344         }
345         *out = p;
346         /* If do_sort is 2 then reorder the STACK */
347         if(do_sort == 2) {
348                 for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
349                         sk_ASN1_VALUE_set(sk, i, tder->field);
350         }
351         OPENSSL_free(derlst);
352         OPENSSL_free(tmpdat);
353         return 1;
354 }
355
356 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
357 {
358         int len;
359         int utype;
360         int usetag;
361
362         utype = it->utype;
363
364         /* Get length of content octets and maybe find
365          * out the underlying type.
366          */
367
368         len = asn1_ex_i2c(pval, NULL, &utype, it);
369
370         /* If SEQUENCE, SET or OTHER then header is
371          * included in pseudo content octets so don't
372          * include tag+length. We need to check here
373          * because the call to asn1_ex_i2c() could change
374          * utype.
375          */
376         if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
377            (utype == V_ASN1_OTHER))
378                 usetag = 0;
379         else usetag = 1;
380
381         /* -1 means omit type */
382
383         if(len == -1) return 0;
384
385         /* If not implicitly tagged get tag from underlying type */
386         if(tag == -1) tag = utype;
387
388         /* Output tag+length followed by content octets */
389         if(out) {
390                 if(usetag) ASN1_put_object(out, 0, len, tag, aclass);
391                 asn1_ex_i2c(pval, *out, &utype, it);
392                 *out += len;
393         }
394
395         if(usetag) return ASN1_object_size(0, len, tag);
396         return len;
397 }
398
399 /* Produce content octets from a structure */
400
401 int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it)
402 {
403         ASN1_BOOLEAN *tbool = NULL;
404         ASN1_STRING *strtmp;
405         ASN1_OBJECT *otmp;
406         int utype;
407         unsigned char *cont, c;
408         int len;
409         const ASN1_PRIMITIVE_FUNCS *pf;
410         pf = it->funcs;
411         if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it);
412
413         /* Should type be omitted? */
414         if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
415                 if(!*pval) return -1;
416         }
417
418         if(it->itype == ASN1_ITYPE_MSTRING) {
419                 /* If MSTRING type set the underlying type */
420                 strtmp = (ASN1_STRING *)*pval;
421                 utype = strtmp->type;
422                 *putype = utype;
423         } else if(it->utype == V_ASN1_ANY) {
424                 /* If ANY set type and pointer to value */
425                 ASN1_TYPE *typ;
426                 typ = (ASN1_TYPE *)*pval;
427                 utype = typ->type;
428                 *putype = utype;
429                 pval = (ASN1_VALUE **)&typ->value.ptr;
430         } else utype = *putype;
431
432         switch(utype) {
433                 case V_ASN1_OBJECT:
434                 otmp = (ASN1_OBJECT *)*pval;
435                 cont = otmp->data;
436                 len = otmp->length;
437                 break;
438
439                 case V_ASN1_NULL:
440                 cont = NULL;
441                 len = 0;
442                 break;
443
444                 case V_ASN1_BOOLEAN:
445                 tbool = (ASN1_BOOLEAN *)pval;
446                 if(*tbool == -1) return -1;
447                 /* Default handling if value == size field then omit */
448                 if(*tbool && (it->size > 0)) return -1;
449                 if(!*tbool && !it->size) return -1;
450                 c = (unsigned char)*tbool;
451                 cont = &c;
452                 len = 1;
453                 break;
454
455                 case V_ASN1_BIT_STRING:
456                 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
457                 break;
458
459                 case V_ASN1_INTEGER:
460                 case V_ASN1_NEG_INTEGER:
461                 case V_ASN1_ENUMERATED:
462                 case V_ASN1_NEG_ENUMERATED:
463                 /* These are all have the same content format
464                  * as ASN1_INTEGER
465                  */
466                 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
467                 break;
468
469                 case V_ASN1_OCTET_STRING:
470                 case V_ASN1_NUMERICSTRING:
471                 case V_ASN1_PRINTABLESTRING:
472                 case V_ASN1_T61STRING:
473                 case V_ASN1_VIDEOTEXSTRING:
474                 case V_ASN1_IA5STRING:
475                 case V_ASN1_UTCTIME:
476                 case V_ASN1_GENERALIZEDTIME:
477                 case V_ASN1_GRAPHICSTRING:
478                 case V_ASN1_VISIBLESTRING:
479                 case V_ASN1_GENERALSTRING:
480                 case V_ASN1_UNIVERSALSTRING:
481                 case V_ASN1_BMPSTRING:
482                 case V_ASN1_UTF8STRING:
483                 case V_ASN1_SEQUENCE:
484                 case V_ASN1_SET:
485                 default:
486                 /* All based on ASN1_STRING and handled the same */
487                 strtmp = (ASN1_STRING *)*pval;
488                 cont = strtmp->data;
489                 len = strtmp->length;
490
491                 break;
492
493         }
494         if(cout && len) memcpy(cout, cont, len);
495         return len;
496 }