LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/asn1 - tasn_enc.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 128 207 61.8 %
Date: 2015-10-10 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /* tasn_enc.c */
       2             : /*
       3             :  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
       4             :  * 2000.
       5             :  */
       6             : /* ====================================================================
       7             :  * Copyright (c) 2000-2004 The OpenSSL Project.  All rights reserved.
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  *
      13             :  * 1. Redistributions of source code must retain the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer.
      15             :  *
      16             :  * 2. Redistributions in binary form must reproduce the above copyright
      17             :  *    notice, this list of conditions and the following disclaimer in
      18             :  *    the documentation and/or other materials provided with the
      19             :  *    distribution.
      20             :  *
      21             :  * 3. All advertising materials mentioning features or use of this
      22             :  *    software must display the following acknowledgment:
      23             :  *    "This product includes software developed by the OpenSSL Project
      24             :  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
      25             :  *
      26             :  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
      27             :  *    endorse or promote products derived from this software without
      28             :  *    prior written permission. For written permission, please contact
      29             :  *    licensing@OpenSSL.org.
      30             :  *
      31             :  * 5. Products derived from this software may not be called "OpenSSL"
      32             :  *    nor may "OpenSSL" appear in their names without prior written
      33             :  *    permission of the OpenSSL Project.
      34             :  *
      35             :  * 6. Redistributions of any form whatsoever must retain the following
      36             :  *    acknowledgment:
      37             :  *    "This product includes software developed by the OpenSSL Project
      38             :  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
      39             :  *
      40             :  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
      41             :  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      42             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
      43             :  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
      44             :  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      45             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      46             :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      47             :  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      48             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      49             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      50             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      51             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      52             :  * ====================================================================
      53             :  *
      54             :  * This product includes cryptographic software written by Eric Young
      55             :  * (eay@cryptsoft.com).  This product includes software written by Tim
      56             :  * Hudson (tjh@cryptsoft.com).
      57             :  *
      58             :  */
      59             : 
      60             : #include <stddef.h>
      61             : #include <string.h>
      62             : #include "cryptlib.h"
      63             : #include <openssl/asn1.h>
      64             : #include <openssl/asn1t.h>
      65             : #include <openssl/objects.h>
      66             : 
      67             : static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
      68             :                                  const ASN1_ITEM *it, int tag, int aclass);
      69             : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
      70             :                             int skcontlen, const ASN1_ITEM *item,
      71             :                             int do_sort, int iclass);
      72             : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
      73             :                                 const ASN1_TEMPLATE *tt, int tag, int aclass);
      74             : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
      75             :                                const ASN1_ITEM *it, int flags);
      76             : 
      77             : /*
      78             :  * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
      79             :  * indefinite length constructed encoding, where appropriate
      80             :  */
      81             : 
      82           0 : int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
      83             :                        const ASN1_ITEM *it)
      84             : {
      85           0 :     return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
      86             : }
      87             : 
      88       23478 : int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
      89             : {
      90       23478 :     return asn1_item_flags_i2d(val, out, it, 0);
      91             : }
      92             : 
      93             : /*
      94             :  * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
      95             :  * points to a buffer to output the data to. The new i2d has one additional
      96             :  * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
      97             :  * allocated and populated with the encoding.
      98             :  */
      99             : 
     100       23478 : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
     101             :                                const ASN1_ITEM *it, int flags)
     102             : {
     103       23478 :     if (out && !*out) {
     104             :         unsigned char *p, *buf;
     105             :         int len;
     106        2152 :         len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
     107        2152 :         if (len <= 0)
     108             :             return len;
     109        2152 :         buf = OPENSSL_malloc(len);
     110        2152 :         if (!buf)
     111             :             return -1;
     112        2152 :         p = buf;
     113        2152 :         ASN1_item_ex_i2d(&val, &p, it, -1, flags);
     114        2152 :         *out = buf;
     115        2152 :         return len;
     116             :     }
     117             : 
     118       21326 :     return ASN1_item_ex_i2d(&val, out, it, -1, flags);
     119             : }
     120             : 
     121             : /*
     122             :  * Encode an item, taking care of IMPLICIT tagging (if any). This function
     123             :  * performs the normal item handling: it can be used in external types.
     124             :  */
     125             : 
     126      256360 : int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     127             :                      const ASN1_ITEM *it, int tag, int aclass)
     128             : {
     129             :     const ASN1_TEMPLATE *tt = NULL;
     130             :     unsigned char *p = NULL;
     131             :     int i, seqcontlen, seqlen, ndef = 1;
     132             :     const ASN1_COMPAT_FUNCS *cf;
     133             :     const ASN1_EXTERN_FUNCS *ef;
     134      256360 :     const ASN1_AUX *aux = it->funcs;
     135             :     ASN1_aux_cb *asn1_cb = 0;
     136             : 
     137      256360 :     if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
     138             :         return 0;
     139             : 
     140      256360 :     if (aux && aux->asn1_cb)
     141             :         asn1_cb = aux->asn1_cb;
     142             : 
     143      256360 :     switch (it->itype) {
     144             : 
     145             :     case ASN1_ITYPE_PRIMITIVE:
     146      135866 :         if (it->templates)
     147       29384 :             return asn1_template_ex_i2d(pval, out, it->templates,
     148             :                                         tag, aclass);
     149      106482 :         return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
     150             :         break;
     151             : 
     152             :     case ASN1_ITYPE_MSTRING:
     153       58768 :         return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
     154             : 
     155             :     case ASN1_ITYPE_CHOICE:
     156           0 :         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
     157             :             return 0;
     158           0 :         i = asn1_get_choice_selector(pval, it);
     159           0 :         if ((i >= 0) && (i < it->tcount)) {
     160             :             ASN1_VALUE **pchval;
     161             :             const ASN1_TEMPLATE *chtt;
     162           0 :             chtt = it->templates + i;
     163           0 :             pchval = asn1_get_field_ptr(pval, chtt);
     164           0 :             return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
     165             :         }
     166             :         /* Fixme: error condition if selector out of range */
     167           0 :         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
     168             :             return 0;
     169             :         break;
     170             : 
     171             :     case ASN1_ITYPE_EXTERN:
     172             :         /* If new style i2d it does all the work */
     173             :         ef = it->funcs;
     174           0 :         return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
     175             : 
     176             :     case ASN1_ITYPE_COMPAT:
     177             :         /* old style hackery... */
     178             :         cf = it->funcs;
     179           0 :         if (out)
     180           0 :             p = *out;
     181           0 :         i = cf->asn1_i2d(*pval, out);
     182             :         /*
     183             :          * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
     184             :          * did the old code. Tags > 30 are very rare anyway.
     185             :          */
     186           0 :         if (out && (tag != -1))
     187           0 :             *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
     188           0 :         return i;
     189             : 
     190             :     case ASN1_ITYPE_NDEF_SEQUENCE:
     191             :         /* Use indefinite length constructed if requested */
     192           0 :         if (aclass & ASN1_TFLG_NDEF)
     193             :             ndef = 2;
     194             :         /* fall through */
     195             : 
     196             :     case ASN1_ITYPE_SEQUENCE:
     197       61726 :         i = asn1_enc_restore(&seqcontlen, out, pval, it);
     198             :         /* An error occurred */
     199       61726 :         if (i < 0)
     200             :             return 0;
     201             :         /* We have a valid cached encoding... */
     202       61726 :         if (i > 0)
     203        4970 :             return seqcontlen;
     204             :         /* Otherwise carry on */
     205       56756 :         seqcontlen = 0;
     206             :         /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
     207       56756 :         if (tag == -1) {
     208             :             tag = V_ASN1_SEQUENCE;
     209             :             /* Retain any other flags in aclass */
     210       56756 :             aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
     211             :                 | V_ASN1_UNIVERSAL;
     212             :         }
     213       56756 :         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
     214             :             return 0;
     215             :         /* First work out sequence content length */
     216      173088 :         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
     217             :             const ASN1_TEMPLATE *seqtt;
     218             :             ASN1_VALUE **pseqval;
     219      116332 :             seqtt = asn1_do_adb(pval, tt, 1);
     220      116332 :             if (!seqtt)
     221             :                 return 0;
     222      116332 :             pseqval = asn1_get_field_ptr(pval, seqtt);
     223             :             /* FIXME: check for errors in enhanced version */
     224      116332 :             seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
     225             :                                                -1, aclass);
     226             :         }
     227             : 
     228       56756 :         seqlen = ASN1_object_size(ndef, seqcontlen, tag);
     229       56756 :         if (!out)
     230             :             return seqlen;
     231             :         /* Output SEQUENCE header */
     232       19764 :         ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
     233       60702 :         for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
     234             :             const ASN1_TEMPLATE *seqtt;
     235             :             ASN1_VALUE **pseqval;
     236       40938 :             seqtt = asn1_do_adb(pval, tt, 1);
     237       40938 :             if (!seqtt)
     238             :                 return 0;
     239       40938 :             pseqval = asn1_get_field_ptr(pval, seqtt);
     240             :             /* FIXME: check for errors in enhanced version */
     241       40938 :             asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
     242             :         }
     243       19764 :         if (ndef == 2)
     244           0 :             ASN1_put_eoc(out);
     245       19764 :         if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
     246             :             return 0;
     247       19764 :         return seqlen;
     248             : 
     249             :     default:
     250             :         return 0;
     251             : 
     252             :     }
     253             :     return 0;
     254             : }
     255             : 
     256           0 : int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
     257             :                       const ASN1_TEMPLATE *tt)
     258             : {
     259           0 :     return asn1_template_ex_i2d(pval, out, tt, -1, 0);
     260             : }
     261             : 
     262      186654 : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     263             :                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
     264             : {
     265             :     int i, ret, flags, ttag, tclass, ndef;
     266      186654 :     flags = tt->flags;
     267             :     /*
     268             :      * Work out tag and class to use: tagging may come either from the
     269             :      * template or the arguments, not both because this would create
     270             :      * ambiguity. Additionally the iclass argument may contain some
     271             :      * additional flags which should be noted and passed down to other
     272             :      * levels.
     273             :      */
     274      186654 :     if (flags & ASN1_TFLG_TAG_MASK) {
     275             :         /* Error if argument and template tagging */
     276           0 :         if (tag != -1)
     277             :             /* FIXME: error code here */
     278             :             return -1;
     279             :         /* Get tagging from template */
     280           0 :         ttag = tt->tag;
     281           0 :         tclass = flags & ASN1_TFLG_TAG_CLASS;
     282      186654 :     } else if (tag != -1) {
     283             :         /* No template tagging, get from arguments */
     284             :         ttag = tag;
     285           0 :         tclass = iclass & ASN1_TFLG_TAG_CLASS;
     286             :     } else {
     287             :         ttag = -1;
     288             :         tclass = 0;
     289             :     }
     290             :     /*
     291             :      * Remove any class mask from iflag.
     292             :      */
     293      186654 :     iclass &= ~ASN1_TFLG_TAG_CLASS;
     294             : 
     295             :     /*
     296             :      * At this point 'ttag' contains the outer tag to use, 'tclass' is the
     297             :      * class and iclass is any flags passed to this function.
     298             :      */
     299             : 
     300             :     /* if template and arguments require ndef, use it */
     301      186654 :     if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
     302             :         ndef = 2;
     303             :     else
     304             :         ndef = 1;
     305             : 
     306      186654 :     if (flags & ASN1_TFLG_SK_MASK) {
     307             :         /* SET OF, SEQUENCE OF */
     308       29384 :         STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
     309             :         int isset, sktag, skaclass;
     310             :         int skcontlen, sklen;
     311             :         ASN1_VALUE *skitem;
     312             : 
     313       29384 :         if (!*pval)
     314             :             return 0;
     315             : 
     316       29384 :         if (flags & ASN1_TFLG_SET_OF) {
     317             :             isset = 1;
     318             :             /* 2 means we reorder */
     319       29384 :             if (flags & ASN1_TFLG_SEQUENCE_OF)
     320             :                 isset = 2;
     321             :         } else
     322             :             isset = 0;
     323             : 
     324             :         /*
     325             :          * Work out inner tag value: if EXPLICIT or no tagging use underlying
     326             :          * type.
     327             :          */
     328       29384 :         if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
     329             :             sktag = ttag;
     330             :             skaclass = tclass;
     331             :         } else {
     332             :             skaclass = V_ASN1_UNIVERSAL;
     333       29384 :             if (isset)
     334             :                 sktag = V_ASN1_SET;
     335             :             else
     336             :                 sktag = V_ASN1_SEQUENCE;
     337             :         }
     338             : 
     339             :         /* Determine total length of items */
     340             :         skcontlen = 0;
     341       58768 :         for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
     342       29384 :             skitem = sk_ASN1_VALUE_value(sk, i);
     343       29384 :             skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
     344       29384 :                                           ASN1_ITEM_ptr(tt->item),
     345             :                                           -1, iclass);
     346             :         }
     347       29384 :         sklen = ASN1_object_size(ndef, skcontlen, sktag);
     348             :         /* If EXPLICIT need length of surrounding tag */
     349       29384 :         if (flags & ASN1_TFLG_EXPTAG)
     350           0 :             ret = ASN1_object_size(ndef, sklen, ttag);
     351             :         else
     352             :             ret = sklen;
     353             : 
     354       29384 :         if (!out)
     355             :             return ret;
     356             : 
     357             :         /* Now encode this lot... */
     358             :         /* EXPLICIT tag */
     359       14692 :         if (flags & ASN1_TFLG_EXPTAG)
     360           0 :             ASN1_put_object(out, ndef, sklen, ttag, tclass);
     361             :         /* SET or SEQUENCE and IMPLICIT tag */
     362       14692 :         ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
     363             :         /* And the stuff itself */
     364       14692 :         asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
     365             :                          isset, iclass);
     366       14692 :         if (ndef == 2) {
     367           0 :             ASN1_put_eoc(out);
     368           0 :             if (flags & ASN1_TFLG_EXPTAG)
     369           0 :                 ASN1_put_eoc(out);
     370             :         }
     371             : 
     372       14692 :         return ret;
     373             :     }
     374             : 
     375      157270 :     if (flags & ASN1_TFLG_EXPTAG) {
     376             :         /* EXPLICIT tagging */
     377             :         /* Find length of tagged item */
     378           0 :         i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
     379           0 :         if (!i)
     380             :             return 0;
     381             :         /* Find length of EXPLICIT tag */
     382           0 :         ret = ASN1_object_size(ndef, i, ttag);
     383           0 :         if (out) {
     384             :             /* Output tag and item */
     385           0 :             ASN1_put_object(out, ndef, i, ttag, tclass);
     386           0 :             ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
     387           0 :             if (ndef == 2)
     388           0 :                 ASN1_put_eoc(out);
     389             :         }
     390           0 :         return ret;
     391             :     }
     392             : 
     393             :     /* Either normal or IMPLICIT tagging: combine class and flags */
     394      157270 :     return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
     395             :                             ttag, tclass | iclass);
     396             : 
     397             : }
     398             : 
     399             : /* Temporary structure used to hold DER encoding of items for SET OF */
     400             : 
     401             : typedef struct {
     402             :     unsigned char *data;
     403             :     int length;
     404             :     ASN1_VALUE *field;
     405             : } DER_ENC;
     406             : 
     407           0 : static int der_cmp(const void *a, const void *b)
     408             : {
     409             :     const DER_ENC *d1 = a, *d2 = b;
     410             :     int cmplen, i;
     411           0 :     cmplen = (d1->length < d2->length) ? d1->length : d2->length;
     412           0 :     i = memcmp(d1->data, d2->data, cmplen);
     413           0 :     if (i)
     414             :         return i;
     415           0 :     return d1->length - d2->length;
     416             : }
     417             : 
     418             : /* Output the content octets of SET OF or SEQUENCE OF */
     419             : 
     420       14692 : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
     421             :                             int skcontlen, const ASN1_ITEM *item,
     422             :                             int do_sort, int iclass)
     423             : {
     424             :     int i;
     425             :     ASN1_VALUE *skitem;
     426       14692 :     unsigned char *tmpdat = NULL, *p = NULL;
     427             :     DER_ENC *derlst = NULL, *tder;
     428       14692 :     if (do_sort) {
     429             :         /* Don't need to sort less than 2 items */
     430       14692 :         if (sk_ASN1_VALUE_num(sk) < 2)
     431             :             do_sort = 0;
     432             :         else {
     433           0 :             derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
     434             :                                     * sizeof(*derlst));
     435           0 :             if (!derlst)
     436             :                 return 0;
     437           0 :             tmpdat = OPENSSL_malloc(skcontlen);
     438           0 :             if (!tmpdat) {
     439           0 :                 OPENSSL_free(derlst);
     440           0 :                 return 0;
     441             :             }
     442             :         }
     443             :     }
     444             :     /* If not sorting just output each item */
     445       14692 :     if (!do_sort) {
     446       14692 :         for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
     447       14692 :             skitem = sk_ASN1_VALUE_value(sk, i);
     448       14692 :             ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
     449             :         }
     450             :         return 1;
     451             :     }
     452           0 :     p = tmpdat;
     453             : 
     454             :     /* Doing sort: build up a list of each member's DER encoding */
     455           0 :     for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
     456           0 :         skitem = sk_ASN1_VALUE_value(sk, i);
     457           0 :         tder->data = p;
     458           0 :         tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
     459           0 :         tder->field = skitem;
     460             :     }
     461             : 
     462             :     /* Now sort them */
     463           0 :     qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
     464             :     /* Output sorted DER encoding */
     465           0 :     p = *out;
     466           0 :     for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
     467           0 :         memcpy(p, tder->data, tder->length);
     468           0 :         p += tder->length;
     469             :     }
     470           0 :     *out = p;
     471             :     /* If do_sort is 2 then reorder the STACK */
     472           0 :     if (do_sort == 2) {
     473           0 :         for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
     474           0 :             (void)sk_ASN1_VALUE_set(sk, i, tder->field);
     475             :     }
     476           0 :     OPENSSL_free(derlst);
     477           0 :     OPENSSL_free(tmpdat);
     478           0 :     return 1;
     479             : }
     480             : 
     481      165250 : static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
     482             :                                  const ASN1_ITEM *it, int tag, int aclass)
     483             : {
     484             :     int len;
     485             :     int utype;
     486             :     int usetag;
     487             :     int ndef = 0;
     488             : 
     489      165250 :     utype = it->utype;
     490             : 
     491             :     /*
     492             :      * Get length of content octets and maybe find out the underlying type.
     493             :      */
     494             : 
     495      165250 :     len = asn1_ex_i2c(pval, NULL, &utype, it);
     496             : 
     497             :     /*
     498             :      * If SEQUENCE, SET or OTHER then header is included in pseudo content
     499             :      * octets so don't include tag+length. We need to check here because the
     500             :      * call to asn1_ex_i2c() could change utype.
     501             :      */
     502      165250 :     if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
     503             :         (utype == V_ASN1_OTHER))
     504             :         usetag = 0;
     505             :     else
     506             :         usetag = 1;
     507             : 
     508             :     /* -1 means omit type */
     509             : 
     510      165250 :     if (len == -1)
     511             :         return 0;
     512             : 
     513             :     /* -2 return is special meaning use ndef */
     514      165250 :     if (len == -2) {
     515             :         ndef = 2;
     516             :         len = 0;
     517             :     }
     518             : 
     519             :     /* If not implicitly tagged get tag from underlying type */
     520      165250 :     if (tag == -1)
     521             :         tag = utype;
     522             : 
     523             :     /* Output tag+length followed by content octets */
     524      165250 :     if (out) {
     525       43598 :         if (usetag)
     526       43598 :             ASN1_put_object(out, ndef, len, tag, aclass);
     527       43598 :         asn1_ex_i2c(pval, *out, &utype, it);
     528       43598 :         if (ndef)
     529           0 :             ASN1_put_eoc(out);
     530             :         else
     531       43598 :             *out += len;
     532             :     }
     533             : 
     534      165250 :     if (usetag)
     535      165250 :         return ASN1_object_size(ndef, len, tag);
     536             :     return len;
     537             : }
     538             : 
     539             : /* Produce content octets from a structure */
     540             : 
     541      208848 : int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
     542             :                 const ASN1_ITEM *it)
     543             : {
     544             :     ASN1_BOOLEAN *tbool = NULL;
     545             :     ASN1_STRING *strtmp;
     546             :     ASN1_OBJECT *otmp;
     547             :     int utype;
     548             :     const unsigned char *cont;
     549             :     unsigned char c;
     550             :     int len;
     551             :     const ASN1_PRIMITIVE_FUNCS *pf;
     552      208848 :     pf = it->funcs;
     553      208848 :     if (pf && pf->prim_i2c)
     554           0 :         return pf->prim_i2c(pval, cout, putype, it);
     555             : 
     556             :     /* Should type be omitted? */
     557      208848 :     if ((it->itype != ASN1_ITYPE_PRIMITIVE)
     558      135388 :         || (it->utype != V_ASN1_BOOLEAN)) {
     559      208848 :         if (!*pval)
     560             :             return -1;
     561             :     }
     562             : 
     563      208848 :     if (it->itype == ASN1_ITYPE_MSTRING) {
     564             :         /* If MSTRING type set the underlying type */
     565       73460 :         strtmp = (ASN1_STRING *)*pval;
     566       73460 :         utype = strtmp->type;
     567       73460 :         *putype = utype;
     568      135388 :     } else if (it->utype == V_ASN1_ANY) {
     569             :         /* If ANY set type and pointer to value */
     570             :         ASN1_TYPE *typ;
     571       12680 :         typ = (ASN1_TYPE *)*pval;
     572       12680 :         utype = typ->type;
     573       12680 :         *putype = utype;
     574       12680 :         pval = &typ->value.asn1_value;
     575             :     } else
     576      122708 :         utype = *putype;
     577             : 
     578      208848 :     switch (utype) {
     579             :     case V_ASN1_OBJECT:
     580       86140 :         otmp = (ASN1_OBJECT *)*pval;
     581       86140 :         cont = otmp->data;
     582       86140 :         len = otmp->length;
     583       86140 :         break;
     584             : 
     585             :     case V_ASN1_NULL:
     586             :         cont = NULL;
     587             :         len = 0;
     588             :         break;
     589             : 
     590             :     case V_ASN1_BOOLEAN:
     591             :         tbool = (ASN1_BOOLEAN *)pval;
     592           0 :         if (*tbool == -1)
     593             :             return -1;
     594           0 :         if (it->utype != V_ASN1_ANY) {
     595             :             /*
     596             :              * Default handling if value == size field then omit
     597             :              */
     598           0 :             if (*tbool && (it->size > 0))
     599             :                 return -1;
     600           0 :             if (!*tbool && !it->size)
     601             :                 return -1;
     602             :         }
     603           0 :         c = (unsigned char)*tbool;
     604             :         cont = &c;
     605             :         len = 1;
     606           0 :         break;
     607             : 
     608             :     case V_ASN1_BIT_STRING:
     609        5640 :         return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
     610        5640 :                                    cout ? &cout : NULL);
     611             :         break;
     612             : 
     613             :     case V_ASN1_INTEGER:
     614             :     case V_ASN1_NEG_INTEGER:
     615             :     case V_ASN1_ENUMERATED:
     616             :     case V_ASN1_NEG_ENUMERATED:
     617             :         /*
     618             :          * These are all have the same content format as ASN1_INTEGER
     619             :          */
     620       11744 :         return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
     621             :         break;
     622             : 
     623             :     case V_ASN1_OCTET_STRING:
     624             :     case V_ASN1_NUMERICSTRING:
     625             :     case V_ASN1_PRINTABLESTRING:
     626             :     case V_ASN1_T61STRING:
     627             :     case V_ASN1_VIDEOTEXSTRING:
     628             :     case V_ASN1_IA5STRING:
     629             :     case V_ASN1_UTCTIME:
     630             :     case V_ASN1_GENERALIZEDTIME:
     631             :     case V_ASN1_GRAPHICSTRING:
     632             :     case V_ASN1_VISIBLESTRING:
     633             :     case V_ASN1_GENERALSTRING:
     634             :     case V_ASN1_UNIVERSALSTRING:
     635             :     case V_ASN1_BMPSTRING:
     636             :     case V_ASN1_UTF8STRING:
     637             :     case V_ASN1_SEQUENCE:
     638             :     case V_ASN1_SET:
     639             :     default:
     640             :         /* All based on ASN1_STRING and handled the same */
     641       92644 :         strtmp = (ASN1_STRING *)*pval;
     642             :         /* Special handling for NDEF */
     643       92644 :         if ((it->size == ASN1_TFLG_NDEF)
     644           0 :             && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
     645           0 :             if (cout) {
     646           0 :                 strtmp->data = cout;
     647           0 :                 strtmp->length = 0;
     648             :             }
     649             :             /* Special return code */
     650             :             return -2;
     651             :         }
     652       92644 :         cont = strtmp->data;
     653       92644 :         len = strtmp->length;
     654             : 
     655       92644 :         break;
     656             : 
     657             :     }
     658      191464 :     if (cout && len)
     659       35248 :         memcpy(cout, cont, len);
     660      191464 :     return len;
     661             : }

Generated by: LCOV version 1.10