LCOV - code coverage report
Current view: top level - asn1 - tasn_enc.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 216 234 92.3 %
Date: 2014-08-02 Functions: 9 10 90.0 %
Branches: 166 196 84.7 %

           Branch data     Line data    Source code
       1                 :            : /* tasn_enc.c */
       2                 :            : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
       3                 :            :  * project 2000.
       4                 :            :  */
       5                 :            : /* ====================================================================
       6                 :            :  * Copyright (c) 2000-2004 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 <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,
      69                 :            :                                         int tag, int aclass);
      70                 :            : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
      71                 :            :                                         int skcontlen, const ASN1_ITEM *item,
      72                 :            :                                         int do_sort, int iclass);
      73                 :            : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
      74                 :            :                                         const ASN1_TEMPLATE *tt,
      75                 :            :                                         int tag, int aclass);
      76                 :            : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
      77                 :            :                                         const ASN1_ITEM *it, int flags);
      78                 :            : 
      79                 :            : /* Top level i2d equivalents: the 'ndef' variant instructs the encoder
      80                 :            :  * to use indefinite length constructed encoding, where appropriate
      81                 :            :  */
      82                 :            : 
      83                 :        172 : int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
      84                 :            :                                                 const ASN1_ITEM *it)
      85                 :            :         {
      86                 :        172 :         return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
      87                 :            :         }
      88                 :            : 
      89                 :      51383 : int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
      90                 :            :         {
      91                 :      51383 :         return asn1_item_flags_i2d(val, out, it, 0);
      92                 :            :         }
      93                 :            : 
      94                 :            : /* Encode an ASN1 item, this is use by the
      95                 :            :  * standard 'i2d' function. 'out' points to 
      96                 :            :  * a buffer to output the data to.
      97                 :            :  *
      98                 :            :  * The new i2d has one additional feature. If the output
      99                 :            :  * buffer is NULL (i.e. *out == NULL) then a buffer is
     100                 :            :  * allocated and populated with the encoding.
     101                 :            :  */
     102                 :            : 
     103                 :      51555 : static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
     104                 :            :                                         const ASN1_ITEM *it, int flags)
     105                 :            :         {
     106 [ +  + ][ +  + ]:      51555 :         if (out && !*out)
     107                 :            :                 {
     108                 :            :                 unsigned char *p, *buf;
     109                 :            :                 int len;
     110                 :       6603 :                 len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
     111         [ +  - ]:       6603 :                 if (len <= 0)
     112                 :            :                         return len;
     113                 :       6603 :                 buf = OPENSSL_malloc(len);
     114         [ +  - ]:       6603 :                 if (!buf)
     115                 :            :                         return -1;
     116                 :       6603 :                 p = buf;
     117                 :       6603 :                 ASN1_item_ex_i2d(&val, &p, it, -1, flags);
     118                 :       6603 :                 *out = buf;
     119                 :       6603 :                 return len;
     120                 :            :                 }
     121                 :            : 
     122                 :      44952 :         return ASN1_item_ex_i2d(&val, out, it, -1, flags);
     123                 :            :         }
     124                 :            : 
     125                 :            : /* Encode an item, taking care of IMPLICIT tagging (if any).
     126                 :            :  * This function performs the normal item handling: it can be
     127                 :            :  * used in external types.
     128                 :            :  */
     129                 :            : 
     130                 :     907819 : int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     131                 :            :                         const ASN1_ITEM *it, int tag, int aclass)
     132                 :            :         {
     133                 :     907819 :         const ASN1_TEMPLATE *tt = NULL;
     134                 :     907819 :         unsigned char *p = NULL;
     135                 :     907819 :         int i, seqcontlen, seqlen, ndef = 1;
     136                 :            :         const ASN1_COMPAT_FUNCS *cf;
     137                 :            :         const ASN1_EXTERN_FUNCS *ef;
     138                 :     907819 :         const ASN1_AUX *aux = it->funcs;
     139                 :     907819 :         ASN1_aux_cb *asn1_cb = 0;
     140                 :            : 
     141 [ +  + ][ +  + ]:     907819 :         if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
     142                 :            :                 return 0;
     143                 :            : 
     144 [ +  + ][ +  + ]:     907575 :         if (aux && aux->asn1_cb)
     145                 :      18204 :                  asn1_cb = aux->asn1_cb;
     146                 :            : 
     147   [ +  +  +  +  :     907575 :         switch(it->itype)
             -  +  +  - ]
     148                 :            :                 {
     149                 :            : 
     150                 :            :                 case ASN1_ITYPE_PRIMITIVE:
     151         [ +  + ]:     464060 :                 if (it->templates)
     152                 :     103677 :                         return asn1_template_ex_i2d(pval, out, it->templates,
     153                 :            :                                                                 tag, aclass);
     154                 :     360383 :                 return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
     155                 :            :                 break;
     156                 :            : 
     157                 :            :                 case ASN1_ITYPE_MSTRING:
     158                 :     206190 :                 return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
     159                 :            : 
     160                 :            :                 case ASN1_ITYPE_CHOICE:
     161 [ +  + ][ +  - ]:       9203 :                 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
     162                 :            :                                 return 0;
     163                 :       9203 :                 i = asn1_get_choice_selector(pval, it);
     164 [ +  - ][ +  - ]:       9203 :                 if ((i >= 0) && (i < it->tcount))
     165                 :            :                         {
     166                 :            :                         ASN1_VALUE **pchval;
     167                 :            :                         const ASN1_TEMPLATE *chtt;
     168                 :       9203 :                         chtt = it->templates + i;
     169                 :       9203 :                         pchval = asn1_get_field_ptr(pval, chtt);
     170                 :       9203 :                         return asn1_template_ex_i2d(pchval, out, chtt,
     171                 :            :                                                                 -1, aclass);
     172                 :            :                         }
     173                 :            :                 /* Fixme: error condition if selector out of range */
     174         [ #  # ]:          0 :                 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
     175                 :            :                                 return 0;
     176                 :            :                 break;
     177                 :            : 
     178                 :            :                 case ASN1_ITYPE_EXTERN:
     179                 :            :                 /* If new style i2d it does all the work */
     180                 :       3198 :                 ef = it->funcs;
     181                 :       3198 :                 return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
     182                 :            : 
     183                 :            :                 case ASN1_ITYPE_COMPAT:
     184                 :            :                 /* old style hackery... */
     185                 :          0 :                 cf = it->funcs;
     186         [ #  # ]:          0 :                 if (out)
     187                 :          0 :                         p = *out;
     188                 :          0 :                 i = cf->asn1_i2d(*pval, out);
     189                 :            :                 /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
     190                 :            :                  * but so did the old code. Tags > 30 are very rare anyway.
     191                 :            :                  */
     192         [ #  # ]:          0 :                 if (out && (tag != -1))
     193                 :          0 :                         *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
     194                 :          0 :                 return i;
     195                 :            :                 
     196                 :            :                 case ASN1_ITYPE_NDEF_SEQUENCE:
     197                 :            :                 /* Use indefinite length constructed if requested */
     198         [ +  + ]:       1377 :                 if (aclass & ASN1_TFLG_NDEF) ndef = 2;
     199                 :            :                 /* fall through */
     200                 :            : 
     201                 :            :                 case ASN1_ITYPE_SEQUENCE:
     202                 :     224924 :                 i = asn1_enc_restore(&seqcontlen, out, pval, it);
     203                 :            :                 /* An error occurred */
     204         [ +  - ]:     224924 :                 if (i < 0)
     205                 :            :                         return 0;
     206                 :            :                 /* We have a valid cached encoding... */
     207         [ +  + ]:     224924 :                 if (i > 0)
     208                 :      20090 :                         return seqcontlen;
     209                 :            :                 /* Otherwise carry on */
     210                 :     204834 :                 seqcontlen = 0;
     211                 :            :                 /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
     212         [ +  + ]:     204834 :                 if (tag == -1)
     213                 :            :                         {
     214                 :     204698 :                         tag = V_ASN1_SEQUENCE;
     215                 :            :                         /* Retain any other flags in aclass */
     216                 :     204698 :                         aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
     217                 :            :                                         | V_ASN1_UNIVERSAL;
     218                 :            :                         }
     219 [ +  + ][ +  - ]:     204834 :                 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
     220                 :            :                                 return 0;
     221                 :            :                 /* First work out sequence content length */
     222         [ +  + ]:     637296 :                 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
     223                 :            :                         {
     224                 :            :                         const ASN1_TEMPLATE *seqtt;
     225                 :            :                         ASN1_VALUE **pseqval;
     226                 :     432462 :                         seqtt = asn1_do_adb(pval, tt, 1);
     227         [ +  - ]:     432462 :                         if (!seqtt)
     228                 :            :                                 return 0;
     229                 :     432462 :                         pseqval = asn1_get_field_ptr(pval, seqtt);
     230                 :            :                         /* FIXME: check for errors in enhanced version */
     231                 :     432462 :                         seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
     232                 :            :                                                                 -1, aclass);
     233                 :            :                         }
     234                 :            : 
     235                 :     204834 :                 seqlen = ASN1_object_size(ndef, seqcontlen, tag);
     236         [ +  + ]:     204834 :                 if (!out)
     237                 :            :                         return seqlen;
     238                 :            :                 /* Output SEQUENCE header */
     239                 :      68106 :                 ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
     240         [ +  + ]:     212557 :                 for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
     241                 :            :                         {
     242                 :            :                         const ASN1_TEMPLATE *seqtt;
     243                 :            :                         ASN1_VALUE **pseqval;
     244                 :     144451 :                         seqtt = asn1_do_adb(pval, tt, 1);
     245         [ +  - ]:     144451 :                         if (!seqtt)
     246                 :            :                                 return 0;
     247                 :     144451 :                         pseqval = asn1_get_field_ptr(pval, seqtt);
     248                 :            :                         /* FIXME: check for errors in enhanced version */
     249                 :     144451 :                         asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
     250                 :            :                         }
     251         [ +  + ]:      68106 :                 if (ndef == 2)
     252                 :        254 :                         ASN1_put_eoc(out);
     253 [ +  + ][ +  - ]:      68106 :                 if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
     254                 :            :                                 return 0;
     255                 :      68106 :                 return seqlen;
     256                 :            : 
     257                 :            :                 default:
     258                 :            :                 return 0;
     259                 :            : 
     260                 :            :                 }
     261                 :            :         return 0;
     262                 :            :         }
     263                 :            : 
     264                 :          0 : int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
     265                 :            :                                                         const ASN1_TEMPLATE *tt)
     266                 :            :         {
     267                 :          0 :         return asn1_template_ex_i2d(pval, out, tt, -1, 0);
     268                 :            :         }
     269                 :            : 
     270                 :     689793 : static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
     271                 :            :                                 const ASN1_TEMPLATE *tt, int tag, int iclass)
     272                 :            :         {
     273                 :            :         int i, ret, flags, ttag, tclass, ndef;
     274                 :     689793 :         flags = tt->flags;
     275                 :            :         /* Work out tag and class to use: tagging may come
     276                 :            :          * either from the template or the arguments, not both
     277                 :            :          * because this would create ambiguity. Additionally
     278                 :            :          * the iclass argument may contain some additional flags
     279                 :            :          * which should be noted and passed down to other levels.
     280                 :            :          */
     281         [ +  + ]:     689793 :         if (flags & ASN1_TFLG_TAG_MASK)
     282                 :            :                 {
     283                 :            :                 /* Error if argument and template tagging */
     284         [ +  - ]:       7064 :                 if (tag != -1)
     285                 :            :                         /* FIXME: error code here */
     286                 :            :                         return -1;
     287                 :            :                 /* Get tagging from template */
     288                 :       7064 :                 ttag = tt->tag;
     289                 :       7064 :                 tclass = flags & ASN1_TFLG_TAG_CLASS;
     290                 :            :                 }
     291         [ -  + ]:     682729 :         else if (tag != -1)
     292                 :            :                 {
     293                 :            :                 /* No template tagging, get from arguments */
     294                 :          0 :                 ttag = tag;
     295                 :          0 :                 tclass = iclass & ASN1_TFLG_TAG_CLASS;
     296                 :            :                 }
     297                 :            :         else
     298                 :            :                 {
     299                 :            :                 ttag = -1;
     300                 :            :                 tclass = 0;
     301                 :            :                 }
     302                 :            :         /* 
     303                 :            :          * Remove any class mask from iflag.
     304                 :            :          */
     305                 :     689793 :         iclass &= ~ASN1_TFLG_TAG_CLASS;
     306                 :            : 
     307                 :            :         /* At this point 'ttag' contains the outer tag to use,
     308                 :            :          * 'tclass' is the class and iclass is any flags passed
     309                 :            :          * to this function.
     310                 :            :          */
     311                 :            : 
     312                 :            :         /* if template and arguments require ndef, use it */
     313 [ +  + ][ +  + ]:     689793 :         if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
     314                 :            :                 ndef = 2;
     315                 :     689331 :         else ndef = 1;
     316                 :            : 
     317         [ +  + ]:     689793 :         if (flags & ASN1_TFLG_SK_MASK)
     318                 :            :                 {
     319                 :            :                 /* SET OF, SEQUENCE OF */
     320                 :     114818 :                 STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
     321                 :            :                 int isset, sktag, skaclass;
     322                 :            :                 int skcontlen, sklen;
     323                 :            :                 ASN1_VALUE *skitem;
     324                 :            : 
     325         [ +  + ]:     114818 :                 if (!*pval)
     326                 :            :                         return 0;
     327                 :            : 
     328         [ +  + ]:     112494 :                 if (flags & ASN1_TFLG_SET_OF)
     329                 :            :                         {
     330                 :     110577 :                         isset = 1;
     331                 :            :                         /* 2 means we reorder */
     332         [ +  + ]:     110577 :                         if (flags & ASN1_TFLG_SEQUENCE_OF)
     333                 :        144 :                                 isset = 2;
     334                 :            :                         }
     335                 :            :                 else isset = 0;
     336                 :            : 
     337                 :            :                 /* Work out inner tag value: if EXPLICIT
     338                 :            :                  * or no tagging use underlying type.
     339                 :            :                  */
     340 [ +  + ][ +  + ]:     112494 :                 if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
     341                 :            :                         {
     342                 :            :                         sktag = ttag;
     343                 :            :                         skaclass = tclass;
     344                 :            :                         }
     345                 :            :                 else
     346                 :            :                         {
     347                 :     111040 :                         skaclass = V_ASN1_UNIVERSAL;
     348         [ +  + ]:     111040 :                         if (isset)
     349                 :            :                                 sktag = V_ASN1_SET;
     350                 :       1328 :                         else sktag = V_ASN1_SEQUENCE;
     351                 :            :                         }
     352                 :            : 
     353                 :            :                 /* Determine total length of items */
     354                 :     112494 :                 skcontlen = 0;
     355         [ +  + ]:     230709 :                 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
     356                 :            :                         {
     357                 :     118215 :                         skitem = sk_ASN1_VALUE_value(sk, i);
     358                 :     118215 :                         skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
     359                 :     118215 :                                                 ASN1_ITEM_ptr(tt->item),
     360                 :            :                                                         -1, iclass);
     361                 :            :                         }
     362                 :     112494 :                 sklen = ASN1_object_size(ndef, skcontlen, sktag);
     363                 :            :                 /* If EXPLICIT need length of surrounding tag */
     364         [ +  + ]:     112494 :                 if (flags & ASN1_TFLG_EXPTAG)
     365                 :         71 :                         ret = ASN1_object_size(ndef, sklen, ttag);
     366                 :            :                 else ret = sklen;
     367                 :            : 
     368         [ +  + ]:     112494 :                 if (!out)
     369                 :            :                         return ret;
     370                 :            : 
     371                 :            :                 /* Now encode this lot... */
     372                 :            :                 /* EXPLICIT tag */
     373         [ +  + ]:      53173 :                 if (flags & ASN1_TFLG_EXPTAG)
     374                 :         20 :                         ASN1_put_object(out, ndef, sklen, ttag, tclass);
     375                 :            :                 /* SET or SEQUENCE and IMPLICIT tag */
     376                 :      53173 :                 ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
     377                 :            :                 /* And the stuff itself */
     378                 :      53173 :                 asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
     379                 :            :                                                                 isset, iclass);
     380         [ -  + ]:      53173 :                 if (ndef == 2)
     381                 :            :                         {
     382                 :          0 :                         ASN1_put_eoc(out);
     383         [ #  # ]:          0 :                         if (flags & ASN1_TFLG_EXPTAG)
     384                 :          0 :                                 ASN1_put_eoc(out);
     385                 :            :                         }
     386                 :            : 
     387                 :     114818 :                 return ret;
     388                 :            :                 }
     389                 :            : 
     390         [ +  + ]:     574975 :         if (flags & ASN1_TFLG_EXPTAG)
     391                 :            :                 {
     392                 :            :                 /* EXPLICIT tagging */
     393                 :            :                 /* Find length of tagged item */
     394                 :       1666 :                 i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
     395                 :            :                                                                 -1, iclass);
     396         [ +  + ]:       1666 :                 if (!i)
     397                 :            :                         return 0;
     398                 :            :                 /* Find length of EXPLICIT tag */
     399                 :       1313 :                 ret = ASN1_object_size(ndef, i, ttag);
     400         [ +  + ]:       1313 :                 if (out)
     401                 :            :                         {
     402                 :            :                         /* Output tag and item */
     403                 :        330 :                         ASN1_put_object(out, ndef, i, ttag, tclass);
     404                 :        330 :                         ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
     405                 :            :                                                                 -1, iclass);
     406         [ +  + ]:        330 :                         if (ndef == 2)
     407                 :        120 :                                 ASN1_put_eoc(out);
     408                 :            :                         }
     409                 :       1313 :                 return ret;
     410                 :            :                 }
     411                 :            : 
     412                 :            :         /* Either normal or IMPLICIT tagging: combine class and flags */
     413                 :     573309 :         return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
     414                 :            :                                                 ttag, tclass | iclass);
     415                 :            : 
     416                 :            : }
     417                 :            : 
     418                 :            : /* Temporary structure used to hold DER encoding of items for SET OF */
     419                 :            : 
     420                 :            : typedef struct {
     421                 :            :         unsigned char *data;
     422                 :            :         int length;
     423                 :            :         ASN1_VALUE *field;
     424                 :            : } DER_ENC;
     425                 :            : 
     426                 :        768 : static int der_cmp(const void *a, const void *b)
     427                 :            :         {
     428                 :        768 :         const DER_ENC *d1 = a, *d2 = b;
     429                 :            :         int cmplen, i;
     430                 :        768 :         cmplen = (d1->length < d2->length) ? d1->length : d2->length;
     431                 :        768 :         i = memcmp(d1->data, d2->data, cmplen);
     432         [ -  + ]:        768 :         if (i)
     433                 :            :                 return i;
     434                 :          0 :         return d1->length - d2->length;
     435                 :            :         }
     436                 :            : 
     437                 :            : /* Output the content octets of SET OF or SEQUENCE OF */
     438                 :            : 
     439                 :      53173 : static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
     440                 :            :                                         int skcontlen, const ASN1_ITEM *item,
     441                 :            :                                         int do_sort, int iclass)
     442                 :            :         {
     443                 :            :         int i;
     444                 :            :         ASN1_VALUE *skitem;
     445                 :      53173 :         unsigned char *tmpdat = NULL, *p = NULL;
     446                 :      53173 :         DER_ENC *derlst = NULL, *tder;
     447         [ +  + ]:      53173 :         if (do_sort)
     448                 :            :                  {
     449                 :            :                 /* Don't need to sort less than 2 items */
     450         [ +  + ]:      52419 :                 if (sk_ASN1_VALUE_num(sk) < 2)
     451                 :            :                         do_sort = 0;
     452                 :            :                 else
     453                 :            :                         {
     454                 :        218 :                         derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
     455                 :            :                                                 * sizeof(*derlst));
     456         [ +  - ]:        218 :                         if (!derlst)
     457                 :            :                                 return 0;
     458                 :        218 :                         tmpdat = OPENSSL_malloc(skcontlen);
     459         [ -  + ]:        218 :                         if (!tmpdat)
     460                 :            :                                 {
     461                 :          0 :                                 OPENSSL_free(derlst);
     462                 :          0 :                                 return 0;
     463                 :            :                                 }
     464                 :            :                         }
     465                 :            :                 }
     466                 :            :         /* If not sorting just output each item */
     467         [ +  + ]:      53173 :         if (!do_sort)
     468                 :            :                 {
     469         [ +  + ]:     107229 :                 for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
     470                 :            :                         {
     471                 :      54274 :                         skitem = sk_ASN1_VALUE_value(sk, i);
     472                 :      54274 :                         ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
     473                 :            :                         }
     474                 :            :                 return 1;
     475                 :            :                 }
     476                 :        218 :         p = tmpdat;
     477                 :            : 
     478                 :            :         /* Doing sort: build up a list of each member's DER encoding */
     479         [ +  + ]:       1013 :         for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
     480                 :            :                 {
     481                 :        795 :                 skitem = sk_ASN1_VALUE_value(sk, i);
     482                 :        795 :                 tder->data = p;
     483                 :        795 :                 tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
     484                 :        795 :                 tder->field = skitem;
     485                 :            :                 }
     486                 :            : 
     487                 :            :         /* Now sort them */
     488                 :        218 :         qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
     489                 :            :         /* Output sorted DER encoding */        
     490                 :        218 :         p = *out;
     491         [ +  + ]:       1013 :         for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
     492                 :            :                 {
     493                 :        795 :                 memcpy(p, tder->data, tder->length);
     494                 :        795 :                 p += tder->length;
     495                 :            :                 }
     496                 :        218 :         *out = p;
     497                 :            :         /* If do_sort is 2 then reorder the STACK */
     498         [ +  + ]:        218 :         if (do_sort == 2)
     499                 :            :                 {
     500         [ +  + ]:        359 :                 for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
     501                 :        287 :                                                         i++, tder++)
     502                 :        287 :                         (void)sk_ASN1_VALUE_set(sk, i, tder->field);
     503                 :            :                 }
     504                 :        218 :         OPENSSL_free(derlst);
     505                 :        218 :         OPENSSL_free(tmpdat);
     506                 :        218 :         return 1;
     507                 :            :         }
     508                 :            : 
     509                 :     566573 : static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
     510                 :            :                                 const ASN1_ITEM *it, int tag, int aclass)
     511                 :            :         {
     512                 :            :         int len;
     513                 :            :         int utype;
     514                 :            :         int usetag;
     515                 :     566573 :         int ndef = 0;
     516                 :            : 
     517                 :     566573 :         utype = it->utype;
     518                 :            : 
     519                 :            :         /* Get length of content octets and maybe find
     520                 :            :          * out the underlying type.
     521                 :            :          */
     522                 :            : 
     523                 :     566573 :         len = asn1_ex_i2c(pval, NULL, &utype, it);
     524                 :            : 
     525                 :            :         /* If SEQUENCE, SET or OTHER then header is
     526                 :            :          * included in pseudo content octets so don't
     527                 :            :          * include tag+length. We need to check here
     528                 :            :          * because the call to asn1_ex_i2c() could change
     529                 :            :          * utype.
     530                 :            :          */
     531         [ +  + ]:     566573 :         if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
     532                 :            :            (utype == V_ASN1_OTHER))
     533                 :            :                 usetag = 0;
     534                 :     564253 :         else usetag = 1;
     535                 :            : 
     536                 :            :         /* -1 means omit type */
     537                 :            : 
     538         [ +  + ]:     566573 :         if (len == -1)
     539                 :            :                 return 0;
     540                 :            : 
     541                 :            :         /* -2 return is special meaning use ndef */
     542         [ +  + ]:     561480 :         if (len == -2)
     543                 :            :                 {
     544                 :        546 :                 ndef = 2;
     545                 :        546 :                 len = 0;
     546                 :            :                 }
     547                 :            : 
     548                 :            :         /* If not implicitly tagged get tag from underlying type */
     549         [ +  + ]:     561480 :         if (tag == -1) tag = utype;
     550                 :            : 
     551                 :            :         /* Output tag+length followed by content octets */
     552         [ +  + ]:     561480 :         if (out)
     553                 :            :                 {
     554         [ +  + ]:     142158 :                 if (usetag)
     555                 :     141811 :                         ASN1_put_object(out, ndef, len, tag, aclass);
     556                 :     142158 :                 asn1_ex_i2c(pval, *out, &utype, it);
     557         [ +  + ]:     142158 :                 if (ndef)
     558                 :         86 :                         ASN1_put_eoc(out);
     559                 :            :                 else
     560                 :     142072 :                         *out += len;
     561                 :            :                 }
     562                 :            : 
     563         [ +  + ]:     561480 :         if (usetag)
     564                 :     559160 :                 return ASN1_object_size(ndef, len, tag);
     565                 :            :         return len;
     566                 :            :         }
     567                 :            : 
     568                 :            : /* Produce content octets from a structure */
     569                 :            : 
     570                 :     708731 : int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
     571                 :            :                                 const ASN1_ITEM *it)
     572                 :            :         {
     573                 :     708731 :         ASN1_BOOLEAN *tbool = NULL;
     574                 :            :         ASN1_STRING *strtmp;
     575                 :            :         ASN1_OBJECT *otmp;
     576                 :            :         int utype;
     577                 :            :         const unsigned char *cont;
     578                 :            :         unsigned char c;
     579                 :            :         int len;
     580                 :            :         const ASN1_PRIMITIVE_FUNCS *pf;
     581                 :     708731 :         pf = it->funcs;
     582 [ +  + ][ +  - ]:     708731 :         if (pf && pf->prim_i2c)
     583                 :       4038 :                 return pf->prim_i2c(pval, cout, putype, it);
     584                 :            : 
     585                 :            :         /* Should type be omitted? */
     586         [ +  + ]:     704693 :         if ((it->itype != ASN1_ITYPE_PRIMITIVE)
     587         [ +  + ]:     446961 :                 || (it->utype != V_ASN1_BOOLEAN))
     588                 :            :                 {
     589         [ +  + ]:     703913 :                 if (!*pval) return -1;
     590                 :            :                 }
     591                 :            : 
     592         [ +  + ]:     700200 :         if (it->itype == ASN1_ITYPE_MSTRING)
     593                 :            :                 {
     594                 :            :                 /* If MSTRING type set the underlying type */
     595                 :     257732 :                 strtmp = (ASN1_STRING *)*pval;
     596                 :     257732 :                 utype = strtmp->type;
     597                 :     257732 :                 *putype = utype;
     598                 :            :                 }
     599         [ +  + ]:     442468 :         else if (it->utype == V_ASN1_ANY)
     600                 :            :                 {
     601                 :            :                 /* If ANY set type and pointer to value */
     602                 :            :                 ASN1_TYPE *typ;
     603                 :      45014 :                 typ = (ASN1_TYPE *)*pval;
     604                 :      45014 :                 utype = typ->type;
     605                 :      45014 :                 *putype = utype;
     606                 :      45014 :                 pval = &typ->value.asn1_value;
     607                 :            :                 }
     608                 :     397454 :         else utype = *putype;
     609                 :            : 
     610   [ +  +  +  +  :     700200 :         switch(utype)
                   +  + ]
     611                 :            :                 {
     612                 :            :                 case V_ASN1_OBJECT:
     613                 :     309926 :                 otmp = (ASN1_OBJECT *)*pval;
     614                 :     309926 :                 cont = otmp->data;
     615                 :     309926 :                 len = otmp->length;
     616                 :     309926 :                 break;
     617                 :            : 
     618                 :            :                 case V_ASN1_NULL:
     619                 :            :                 cont = NULL;
     620                 :            :                 len = 0;
     621                 :            :                 break;
     622                 :            : 
     623                 :            :                 case V_ASN1_BOOLEAN:
     624                 :        780 :                 tbool = (ASN1_BOOLEAN *)pval;
     625         [ +  + ]:        780 :                 if (*tbool == -1)
     626                 :            :                         return -1;
     627         [ +  - ]:        222 :                 if (it->utype != V_ASN1_ANY)
     628                 :            :                         {
     629                 :            :                         /* Default handling if value == size field then omit */
     630 [ +  + ][ +  - ]:        222 :                         if (*tbool && (it->size > 0))
     631                 :            :                                 return -1;
     632 [ +  + ][ -  + ]:        222 :                         if (!*tbool && !it->size)
     633                 :            :                                 return -1;
     634                 :            :                         }
     635                 :        180 :                 c = (unsigned char)*tbool;
     636                 :        180 :                 cont = &c;
     637                 :        180 :                 len = 1;
     638                 :        180 :                 break;
     639                 :            : 
     640                 :            :                 case V_ASN1_BIT_STRING:
     641         [ +  + ]:      24813 :                 return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
     642                 :      24813 :                                                         cout ? &cout : NULL);
     643                 :            :                 break;
     644                 :            : 
     645                 :            :                 case V_ASN1_INTEGER:
     646                 :            :                 case V_ASN1_NEG_INTEGER:
     647                 :            :                 case V_ASN1_ENUMERATED:
     648                 :            :                 case V_ASN1_NEG_ENUMERATED:
     649                 :            :                 /* These are all have the same content format
     650                 :            :                  * as ASN1_INTEGER
     651                 :            :                  */
     652         [ +  + ]:      31145 :                 return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
     653                 :      31145 :                                                         cout ? &cout : NULL);
     654                 :            :                 break;
     655                 :            : 
     656                 :            :                 case V_ASN1_OCTET_STRING:
     657                 :            :                 case V_ASN1_NUMERICSTRING:
     658                 :            :                 case V_ASN1_PRINTABLESTRING:
     659                 :            :                 case V_ASN1_T61STRING:
     660                 :            :                 case V_ASN1_VIDEOTEXSTRING:
     661                 :            :                 case V_ASN1_IA5STRING:
     662                 :            :                 case V_ASN1_UTCTIME:
     663                 :            :                 case V_ASN1_GENERALIZEDTIME:
     664                 :            :                 case V_ASN1_GRAPHICSTRING:
     665                 :            :                 case V_ASN1_VISIBLESTRING:
     666                 :            :                 case V_ASN1_GENERALSTRING:
     667                 :            :                 case V_ASN1_UNIVERSALSTRING:
     668                 :            :                 case V_ASN1_BMPSTRING:
     669                 :            :                 case V_ASN1_UTF8STRING:
     670                 :            :                 case V_ASN1_SEQUENCE:
     671                 :            :                 case V_ASN1_SET:
     672                 :            :                 default:
     673                 :            :                 /* All based on ASN1_STRING and handled the same */
     674                 :     298576 :                 strtmp = (ASN1_STRING *)*pval;
     675                 :            :                 /* Special handling for NDEF */
     676         [ +  + ]:     298576 :                 if ((it->size == ASN1_TFLG_NDEF)
     677         [ +  + ]:        768 :                         && (strtmp->flags & ASN1_STRING_FLAG_NDEF))
     678                 :            :                         {
     679         [ +  + ]:        632 :                         if (cout)
     680                 :            :                                 {
     681                 :         86 :                                 strtmp->data = cout;
     682                 :         86 :                                 strtmp->length = 0;
     683                 :            :                                 }
     684                 :            :                         /* Special return code */
     685                 :            :                         return -2;
     686                 :            :                         }
     687                 :     297944 :                 cont = strtmp->data;
     688                 :     297944 :                 len = strtmp->length;
     689                 :            : 
     690                 :     297944 :                 break;
     691                 :            : 
     692                 :            :                 }
     693 [ +  + ][ +  + ]:     643010 :         if (cout && len)
     694                 :     119556 :                 memcpy(cout, cont, len);
     695                 :     643010 :         return len;
     696                 :            :         }

Generated by: LCOV version 1.9