LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/asn1 - der_get.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 241 460 52.4 %
Date: 2024-04-21 15:09:00 Functions: 19 27 70.4 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "der_locl.h"
      35             : 
      36             : /*
      37             :  * All decoding functions take a pointer `p' to first position in
      38             :  * which to read, from the left, `len' which means the maximum number
      39             :  * of characters we are able to read, `ret' were the value will be
      40             :  * returned and `size' where the number of used bytes is stored.
      41             :  * Either 0 or an error code is returned.
      42             :  */
      43             : 
      44             : int ASN1CALL
      45     7139590 : der_get_unsigned (const unsigned char *p, size_t len,
      46             :                   unsigned *ret, size_t *size)
      47             : {
      48     7139590 :     unsigned val = 0;
      49     7139590 :     size_t oldlen = len;
      50             : 
      51     7139590 :     if (len == sizeof(val) + 1 && p[0] == 0)
      52             :         ;
      53     7115562 :     else if (len > sizeof(val))
      54           0 :         return ASN1_OVERRUN;
      55             : 
      56    19765118 :     while (len--)
      57    12625528 :         val = val * 256 + *p++;
      58     7139590 :     *ret = val;
      59     7139590 :     if(size) *size = oldlen;
      60     6890119 :     return 0;
      61             : }
      62             : 
      63             : int ASN1CALL
      64           0 : der_get_unsigned64 (const unsigned char *p, size_t len,
      65             :                    uint64_t *ret, size_t *size)
      66             : {
      67           0 :     uint64_t val = 0;
      68           0 :     size_t oldlen = len;
      69             : 
      70           0 :     if (len == sizeof(val) + 1 && p[0] == 0)
      71             :        ;
      72           0 :     else if (len > sizeof(val))
      73           0 :         return ASN1_OVERRUN;
      74             : 
      75           0 :     while (len--)
      76           0 :         val = val * 256 + *p++;
      77           0 :     *ret = val;
      78           0 :     if(size) *size = oldlen;
      79           0 :     return 0;
      80             : }
      81             : 
      82             : int ASN1CALL
      83     5804021 : der_get_integer (const unsigned char *p, size_t len,
      84             :                  int *ret, size_t *size)
      85             : {
      86     5804021 :     int val = 0;
      87     5804021 :     size_t oldlen = len;
      88             : 
      89     5804021 :     if (len == sizeof(val) + 1 && (p[0] == 0 || p[0] == 0xff))
      90             :         ;
      91     5804021 :     else if (len > sizeof(val))
      92           0 :         return ASN1_OVERRUN;
      93             : 
      94             :     /* We assume we're on a twos-complement platform */
      95     5804021 :     if (len > 0) {
      96     5804021 :         val = (signed char)*p++;
      97     7481341 :         while (--len)
      98     1677320 :             val = val * 256 + *p++;
      99             :     }
     100     5804021 :     *ret = val;
     101     5804021 :     if(size) *size = oldlen;
     102     5596854 :     return 0;
     103             : }
     104             : 
     105             : int ASN1CALL
     106           0 : der_get_integer64 (const unsigned char *p, size_t len,
     107             :                    int64_t *ret, size_t *size)
     108             : {
     109           0 :     int64_t val = 0;
     110           0 :     size_t oldlen = len;
     111             : 
     112           0 :     if (len > sizeof(val))
     113           0 :         return ASN1_OVERRUN;
     114             : 
     115             :     /* We assume we're on a twos-complement platform */
     116           0 :     if (len > 0) {
     117           0 :        val = (signed char)*p++;
     118           0 :        while (--len)
     119           0 :            val = val * 256 + *p++;
     120             :     }
     121           0 :     *ret = val;
     122           0 :     if(size) *size = oldlen;
     123           0 :     return 0;
     124             : }
     125             : 
     126             : 
     127             : int ASN1CALL
     128    33075379 : der_get_length (const unsigned char *p, size_t len,
     129             :                 size_t *val, size_t *size)
     130             : {
     131     1172736 :     size_t v;
     132             : 
     133    33075379 :     if (len <= 0)
     134           0 :         return ASN1_OVERRUN;
     135    33075379 :     --len;
     136    33075379 :     v = *p++;
     137    33075379 :     if (v < 128) {
     138    26035289 :         *val = v;
     139    26035289 :         if(size) *size = 1;
     140             :     } else {
     141      245948 :         int e;
     142      245948 :         size_t l;
     143      245948 :         unsigned tmp;
     144             : 
     145     7040090 :         if(v == 0x80){
     146           0 :             *val = ASN1_INDEFINITE;
     147           0 :             if(size) *size = 1;
     148           0 :             return 0;
     149             :         }
     150     7040090 :         v &= 0x7F;
     151     7040090 :         if (len < v)
     152           0 :             return ASN1_OVERRUN;
     153     7040090 :         e = der_get_unsigned (p, v, &tmp, &l);
     154     7040090 :         if(e) return e;
     155     7040090 :         *val = tmp;
     156     7040090 :         if(size) *size = l + 1;
     157             :     }
     158    31902643 :     return 0;
     159             : }
     160             : 
     161             : int ASN1CALL
     162        1296 : der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
     163             : {
     164        1296 :     if(len < 1)
     165           0 :         return ASN1_OVERRUN;
     166        1296 :     if(*p != 0)
     167        1287 :         *data = 1;
     168             :     else
     169           9 :         *data = 0;
     170        1296 :     *size = 1;
     171        1296 :     return 0;
     172             : }
     173             : 
     174             : int ASN1CALL
     175     2448502 : der_get_general_string (const unsigned char *p, size_t len,
     176             :                         heim_general_string *str, size_t *size)
     177             : {
     178       88353 :     const unsigned char *p1;
     179       88353 :     char *s;
     180             : 
     181     2448502 :     assert(p != NULL);
     182             : 
     183     2448502 :     if (size)
     184     2448502 :         *size = 0;
     185             : 
     186     2448502 :     p1 = memchr(p, 0, len);
     187     2448502 :     if (p1 != NULL) {
     188             :         /*
     189             :          * Allow trailing NULs. We allow this since MIT Kerberos sends
     190             :          * an strings in the NEED_PREAUTH case that includes a
     191             :          * trailing NUL.
     192             :          */
     193           0 :         while ((size_t)(p1 - p) < len && *p1 == '\0')
     194           0 :             p1++;
     195           0 :         if ((size_t)(p1 - p) != len) {
     196           0 :             *str = NULL;
     197           0 :             return ASN1_BAD_CHARACTER;
     198             :         }
     199             :     }
     200     2448502 :     if (len == SIZE_MAX) {
     201           0 :         *str = NULL;
     202           0 :         return ASN1_BAD_LENGTH;
     203             :     }
     204             : 
     205     2448502 :     *str = s = malloc (len + 1);
     206     2448502 :     if (s == NULL)
     207           0 :         return ENOMEM;
     208     2448502 :     memcpy (s, p, len);
     209     2448502 :     s[len] = '\0';
     210             : 
     211     2448502 :     if(size) *size = len;
     212     2360149 :     return 0;
     213             : }
     214             : 
     215             : int ASN1CALL
     216        3074 : der_get_utf8string (const unsigned char *p, size_t len,
     217             :                     heim_utf8_string *str, size_t *size)
     218             : {
     219        3074 :     return der_get_general_string(p, len, str, size);
     220             : }
     221             : 
     222             : #define gen_data_zero(_data) \
     223             :         do { (_data)->length = 0; (_data)->data = NULL; } while(0)
     224             : 
     225             : int ASN1CALL
     226        2249 : der_get_printable_string(const unsigned char *p, size_t len,
     227             :                          heim_printable_string *str, size_t *size)
     228             : {
     229        2249 :     assert(p != NULL);
     230             : 
     231        2249 :     if (size)
     232        2249 :         *size = 0;
     233             : 
     234        2249 :     if (len == SIZE_MAX) {
     235           0 :         gen_data_zero(str);
     236           0 :         return ASN1_BAD_LENGTH;
     237             :     }
     238        2249 :     str->length = len;
     239        2249 :     str->data = malloc(len + 1);
     240        2249 :     if (str->data == NULL) {
     241           0 :         gen_data_zero(str);
     242           0 :         return ENOMEM;
     243             :     }
     244             : 
     245        2249 :     memcpy(str->data, p, len);
     246        2249 :     ((char *)str->data)[len] = '\0';
     247        2249 :     if(size) *size = len;
     248        2113 :     return 0;
     249             : }
     250             : 
     251             : int ASN1CALL
     252        1295 : der_get_ia5_string(const unsigned char *p, size_t len,
     253             :                    heim_ia5_string *str, size_t *size)
     254             : {
     255        1295 :     return der_get_printable_string(p, len, str, size);
     256             : }
     257             : 
     258             : int ASN1CALL
     259           0 : der_get_bmp_string (const unsigned char *p, size_t len,
     260             :                     heim_bmp_string *data, size_t *size)
     261             : {
     262           0 :     size_t i;
     263             : 
     264           0 :     assert(p != NULL);
     265             : 
     266           0 :     if (size)
     267           0 :         *size = 0;
     268             : 
     269           0 :     if (len & 1) {
     270           0 :         gen_data_zero(data);
     271           0 :         return ASN1_BAD_FORMAT;
     272             :     }
     273           0 :     data->length = len / 2;
     274           0 :     if (data->length > UINT_MAX/sizeof(data->data[0])) {
     275           0 :         gen_data_zero(data);
     276           0 :         return ERANGE;
     277             :     }
     278           0 :     data->data = malloc(data->length * sizeof(data->data[0]));
     279           0 :     if (data->data == NULL && data->length != 0) {
     280           0 :         gen_data_zero(data);
     281           0 :         return ENOMEM;
     282             :     }
     283             : 
     284           0 :     for (i = 0; i < data->length; i++) {
     285           0 :         data->data[i] = (p[0] << 8) | p[1];
     286           0 :         p += 2;
     287             :         /* check for NUL in the middle of the string */
     288           0 :         if (data->data[i] == 0 && i != (data->length - 1)) {
     289           0 :             free(data->data);
     290           0 :             gen_data_zero(data);
     291           0 :             return ASN1_BAD_CHARACTER;
     292             :         }
     293             :     }
     294           0 :     if (size) *size = len;
     295             : 
     296           0 :     return 0;
     297             : }
     298             : 
     299             : int ASN1CALL
     300           0 : der_get_universal_string (const unsigned char *p, size_t len,
     301             :                           heim_universal_string *data, size_t *size)
     302             : {
     303           0 :     size_t i;
     304             : 
     305           0 :     assert(p != NULL);
     306             : 
     307           0 :     if (size)
     308           0 :         *size = 0;
     309             : 
     310           0 :     if (len & 3) {
     311           0 :         gen_data_zero(data);
     312           0 :         return ASN1_BAD_FORMAT;
     313             :     }
     314           0 :     data->length = len / 4;
     315           0 :     if (data->length > UINT_MAX/sizeof(data->data[0])) {
     316           0 :         gen_data_zero(data);
     317           0 :         return ERANGE;
     318             :     }
     319           0 :     data->data = malloc(data->length * sizeof(data->data[0]));
     320           0 :     if (data->data == NULL && data->length != 0) {
     321           0 :         gen_data_zero(data);
     322           0 :         return ENOMEM;
     323             :     }
     324             : 
     325           0 :     for (i = 0; i < data->length; i++) {
     326           0 :         data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
     327           0 :         p += 4;
     328             :         /* check for NUL in the middle of the string */
     329           0 :         if (data->data[i] == 0 && i != (data->length - 1)) {
     330           0 :             free(data->data);
     331           0 :             gen_data_zero(data);
     332           0 :             return ASN1_BAD_CHARACTER;
     333             :         }
     334             :     }
     335           0 :     if (size) *size = len;
     336           0 :     return 0;
     337             : }
     338             : 
     339             : int ASN1CALL
     340           0 : der_get_visible_string (const unsigned char *p, size_t len,
     341             :                         heim_visible_string *str, size_t *size)
     342             : {
     343           0 :     return der_get_general_string(p, len, str, size);
     344             : }
     345             : 
     346             : int ASN1CALL
     347     2104136 : der_get_octet_string (const unsigned char *p, size_t len,
     348             :                       heim_octet_string *data, size_t *size)
     349             : {
     350     2104136 :     assert(p != NULL);
     351             : 
     352     2104136 :     if (size)
     353     2104136 :         *size = 0;
     354             : 
     355     2104136 :     if (len == 0)
     356      240554 :         data->data = malloc(1);
     357             :     else
     358     1863582 :         data->data = malloc(len);
     359     2104136 :     if (data->data == NULL) {
     360           0 :         data->length = 0;
     361           0 :         return ENOMEM;
     362             :     }
     363     2104136 :     data->length = len;
     364     2104136 :     memcpy (data->data, p, len);
     365     2104136 :     if (size)
     366     2104136 :         *size = len;
     367     2029265 :     return 0;
     368             : }
     369             : 
     370             : int ASN1CALL
     371           0 : der_get_octet_string_ber (const unsigned char *p, size_t len,
     372             :                           heim_octet_string *data, size_t *size)
     373             : {
     374           0 :     int e;
     375           0 :     Der_type type;
     376           0 :     Der_class cls;
     377           0 :     unsigned int tag, depth = 0;
     378           0 :     size_t l, datalen, oldlen = len;
     379             : 
     380           0 :     assert(p != NULL);
     381             : 
     382           0 :     if (size)
     383           0 :         *size = 0;
     384             : 
     385           0 :     data->length = 0;
     386           0 :     data->data = NULL;
     387             : 
     388           0 :     while (len) {
     389           0 :         e = der_get_tag (p, len, &cls, &type, &tag, &l);
     390           0 :         if (e) goto out;
     391           0 :         if (cls != ASN1_C_UNIV) {
     392           0 :             e = ASN1_BAD_ID;
     393           0 :             goto out;
     394             :         }
     395           0 :         if (type == PRIM && tag == UT_EndOfContent) {
     396           0 :             if (depth == 0)
     397           0 :                 break;
     398           0 :             depth--;
     399             :         }
     400           0 :         if (tag != UT_OctetString) {
     401           0 :             e = ASN1_BAD_ID;
     402           0 :             goto out;
     403             :         }
     404             : 
     405           0 :         p += l;
     406           0 :         len -= l;
     407           0 :         e = der_get_length (p, len, &datalen, &l);
     408           0 :         if (e) goto out;
     409           0 :         p += l;
     410           0 :         len -= l;
     411             : 
     412           0 :         if (datalen > len)
     413           0 :             return ASN1_OVERRUN;
     414             : 
     415           0 :         if (type == PRIM && datalen) {
     416           0 :             void *ptr;
     417             : 
     418           0 :             ptr = realloc(data->data, data->length + datalen);
     419           0 :             if (ptr == NULL) {
     420           0 :                 e = ENOMEM;
     421           0 :                 goto out;
     422             :             }
     423           0 :             data->data = ptr;
     424           0 :             memcpy(((unsigned char *)data->data) + data->length, p, datalen);
     425           0 :             data->length += datalen;
     426           0 :         } else if (type != PRIM)
     427           0 :             depth++;
     428             : 
     429           0 :         p += datalen;
     430           0 :         len -= datalen;
     431             :     }
     432           0 :     if (depth != 0)
     433           0 :         return ASN1_INDEF_OVERRUN;
     434           0 :     if(size) *size = oldlen - len;
     435           0 :     return 0;
     436           0 :  out:
     437           0 :     free(data->data);
     438           0 :     data->data = NULL;
     439           0 :     data->length = 0;
     440           0 :     return e;
     441             : }
     442             : 
     443             : 
     444             : int ASN1CALL
     445        1769 : der_get_heim_integer (const unsigned char *p, size_t len,
     446             :                       heim_integer *data, size_t *size)
     447             : {
     448        1769 :     data->length = 0;
     449        1769 :     data->negative = 0;
     450        1769 :     data->data = NULL;
     451             : 
     452        1769 :     if (size)
     453        1769 :         *size = 0;
     454             : 
     455        1769 :     if (len == 0)
     456           0 :         return 0;
     457             : 
     458        1769 :     assert(p != NULL);
     459             : 
     460        1769 :     if (p[0] & 0x80) {
     461           0 :         unsigned char *q;
     462          59 :         int carry = 1;
     463             : 
     464             : 
     465             :         /*
     466             :          * A negative number.  It's going to be a twos complement byte array.
     467             :          * We're going to leave the positive value in `data->data', but set the
     468             :          * `data->negative' flag.  That means we need to negate the
     469             :          * twos-complement integer received.
     470             :          */
     471          59 :         data->negative = 1;
     472          59 :         data->length = len;
     473             : 
     474          59 :         if (p[0] == 0xff) {
     475           0 :             if (data->length == 1) {
     476             :                 /* One byte of all ones == -1 */
     477           0 :                 q = data->data = malloc(1);
     478           0 :                 *q = 1;
     479           0 :                 data->length = 1;
     480           0 :                 if (size)
     481           0 :                     *size = 1;
     482           0 :                 return 0;
     483             :             }
     484             : 
     485           0 :             p++;
     486           0 :             data->length--;
     487             : 
     488             :             /*
     489             :              * We could check if the next byte's high bit is set, which would
     490             :              * be an error ("illegal padding" in OpenSSL).  However, this would
     491             :              * mean failing to accept certificates made by certain CAs that
     492             :              * would read 8 bytes of RNG into a buffer, slap on length 8, then
     493             :              * slap on the tag [UNIVERSAL INTEGER], and make that the
     494             :              * serialNumber field's encoding, which then fails to parse in
     495             :              * around 1 in 256 certificates.
     496             :              *
     497             :              * So let's not.
     498             :              *
     499             :              * if (p[0] & 0x80)
     500             :              *     return ASN1_PARSE_ERROR; // or a new error code
     501             :              */
     502             :         }
     503          59 :         data->data = malloc(data->length);
     504          59 :         if (data->data == NULL) {
     505           0 :             data->length = 0;
     506           0 :             if (size)
     507           0 :                 *size = 0;
     508           0 :             return ENOMEM;
     509             :         }
     510             : 
     511             :         /*
     512             :          * Note that if `data->length' were zero, this would be UB because we
     513             :          * underflow if data->length is zero even though we wouldn't actually
     514             :          * dereference the byte before data->data.  Thus we check above for
     515             :          * that.
     516             :          */
     517          59 :         q = &((unsigned char*)data->data)[data->length - 1];
     518          59 :         p += data->length - 1;
     519         295 :         while (q >= (unsigned char*)data->data) {
     520             :             /* *p XOR 0xff -> ~*p; we're dealing with twos complement */
     521         236 :             *q = *p ^ 0xff;
     522         236 :             if (carry)
     523          59 :                 carry = !++*q;
     524         236 :             p--;
     525         236 :             q--;
     526             :         }
     527             :     } else {
     528        1710 :         data->negative = 0;
     529        1710 :         data->length = len;
     530             : 
     531        1710 :         if (p[0] == 0) {
     532         775 :             p++;
     533         775 :             data->length--;
     534             :         }
     535        1710 :         data->data = malloc(data->length);
     536        1710 :         if (data->data == NULL && data->length != 0) {
     537           0 :             data->length = 0;
     538           0 :             if (size)
     539           0 :                 *size = 0;
     540           0 :             return ENOMEM;
     541             :         }
     542        1710 :         memcpy(data->data, p, data->length);
     543             :     }
     544        1769 :     if (size)
     545        1769 :         *size = len;
     546        1673 :     return 0;
     547             : }
     548             : 
     549             : static int
     550     1022797 : generalizedtime2time (const char *s, time_t *t)
     551             : {
     552       35787 :     struct tm tm;
     553             : 
     554     1022797 :     memset(&tm, 0, sizeof(tm));
     555     1022797 :     if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
     556             :                 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
     557             :                 &tm.tm_min, &tm.tm_sec) != 6) {
     558         763 :         if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ",
     559             :                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
     560             :                     &tm.tm_min, &tm.tm_sec) != 6)
     561           0 :             return ASN1_BAD_TIMEFORMAT;
     562         763 :         if (tm.tm_year < 50)
     563         763 :             tm.tm_year += 2000;
     564             :         else
     565           0 :             tm.tm_year += 1900;
     566             :     }
     567     1022797 :     tm.tm_year -= 1900;
     568     1022797 :     tm.tm_mon -= 1;
     569     1022797 :     *t = _der_timegm (&tm);
     570     1022797 :     return 0;
     571             : }
     572             : 
     573             : static int ASN1CALL
     574     1022797 : der_get_time (const unsigned char *p, size_t len,
     575             :               time_t *data, size_t *size)
     576             : {
     577       35787 :     char *times;
     578       35787 :     int e;
     579             : 
     580     1022797 :     assert(p != NULL);
     581             : 
     582     1022797 :     if (size)
     583     1022797 :         *size = 0;
     584             : 
     585     1022797 :     if (len == SIZE_MAX || len == 0)
     586           0 :         return ASN1_BAD_LENGTH;
     587             : 
     588     1022797 :     times = malloc(len + 1);
     589     1022797 :     if (times == NULL)
     590           0 :         return ENOMEM;
     591     1022797 :     memcpy(times, p, len);
     592     1022797 :     times[len] = '\0';
     593     1022797 :     e = generalizedtime2time(times, data);
     594     1022797 :     free (times);
     595     1022797 :     if(size) *size = len;
     596      987010 :     return e;
     597             : }
     598             : 
     599             : int ASN1CALL
     600     1022034 : der_get_generalized_time (const unsigned char *p, size_t len,
     601             :                           time_t *data, size_t *size)
     602             : {
     603     1022034 :     return der_get_time(p, len, data, size);
     604             : }
     605             : 
     606             : int ASN1CALL
     607         763 : der_get_utctime (const unsigned char *p, size_t len,
     608             :                           time_t *data, size_t *size)
     609             : {
     610         763 :     return der_get_time(p, len, data, size);
     611             : }
     612             : 
     613             : int ASN1CALL
     614       77860 : der_get_oid (const unsigned char *p, size_t len,
     615             :              heim_oid *data, size_t *size)
     616             : {
     617        3115 :     size_t n;
     618       77860 :     size_t oldlen = len;
     619             : 
     620       77860 :     assert(p != NULL);
     621             : 
     622       77860 :     if (size)
     623       30200 :         *size = 0;
     624             : 
     625       77860 :     if (len < 1)
     626           0 :         return ASN1_OVERRUN;
     627             : 
     628       77860 :     if (len == SIZE_MAX)
     629           0 :         return ASN1_BAD_LENGTH;
     630             : 
     631       77860 :     if (len + 1 > UINT_MAX/sizeof(data->components[0]))
     632           0 :         return ERANGE;
     633             : 
     634       77860 :     data->components = malloc((len + 1) * sizeof(data->components[0]));
     635       77860 :     if (data->components == NULL) {
     636           0 :         data->length = 0;
     637           0 :         return ENOMEM;
     638             :     }
     639       77860 :     data->components[0] = (*p) / 40;
     640       77860 :     data->components[1] = (*p) % 40;
     641       77860 :     --len;
     642       77860 :     ++p;
     643      427735 :     for (n = 2; len > 0; ++n) {
     644      336213 :         unsigned u = 0, u1;
     645             : 
     646       19076 :         do {
     647      490538 :             --len;
     648      490538 :             u1 = u * 128 + (*p++ % 128);
     649             :             /* check that we don't overflow the element */
     650      490538 :             if (u1 < u) {
     651           0 :                 der_free_oid(data);
     652           0 :                 return ASN1_OVERRUN;
     653             :             }
     654      490538 :             u = u1;
     655      490538 :         } while (len > 0 && p[-1] & 0x80);
     656      349875 :         data->components[n] = u;
     657             :     }
     658       77860 :     if (n > 2 && p[-1] & 0x80) {
     659           0 :         der_free_oid (data);
     660           0 :         return ASN1_OVERRUN;
     661             :     }
     662       77860 :     data->length = n;
     663       77860 :     if (size)
     664       30200 :         *size = oldlen;
     665       74745 :     return 0;
     666             : }
     667             : 
     668             : int ASN1CALL
     669    34722650 : der_get_tag (const unsigned char *p, size_t len,
     670             :              Der_class *cls, Der_type *type,
     671             :              unsigned int *tag, size_t *size)
     672             : {
     673    34722650 :     size_t ret = 0;
     674             : 
     675    34722650 :     if (size)
     676    34722650 :         *size = 0;
     677             : 
     678    34722650 :     if (len < 1)
     679      507185 :         return ASN1_MISSING_FIELD;
     680             : 
     681    34198163 :     assert(p != NULL);
     682             : 
     683    34198163 :     *cls = (Der_class)(((*p) >> 6) & 0x03);
     684    34198163 :     *type = (Der_type)(((*p) >> 5) & 0x01);
     685    34198163 :     *tag = (*p) & 0x1f;
     686    34198163 :     p++; len--; ret++;
     687    34198163 :     if(*tag == 0x1f) {
     688           0 :         unsigned int continuation;
     689           0 :         unsigned int tag1;
     690           0 :         *tag = 0;
     691           0 :         do {
     692           0 :             if(len < 1)
     693           0 :                 return ASN1_OVERRUN;
     694           0 :             continuation = *p & 128;
     695           0 :             tag1 = *tag * 128 + (*p % 128);
     696             :             /* check that we don't overflow the tag */
     697           0 :             if (tag1 < *tag)
     698           0 :                 return ASN1_OVERFLOW;
     699           0 :             *tag = tag1;
     700           0 :             p++; len--; ret++;
     701           0 :         } while(continuation);
     702             :     }
     703    34198163 :     if(size) *size = ret;
     704    32981090 :     return 0;
     705             : }
     706             : 
     707             : int ASN1CALL
     708           0 : der_match_tag (const unsigned char *p, size_t len,
     709             :                Der_class cls, Der_type type,
     710             :                unsigned int tag, size_t *size)
     711             : {
     712           0 :     Der_type thistype;
     713           0 :     int e;
     714             : 
     715           0 :     e = der_match_tag2(p, len, cls, &thistype, tag, size);
     716           0 :     if (e) return e;
     717           0 :     if (thistype != type) return ASN1_BAD_ID;
     718           0 :     return 0;
     719             : }
     720             : 
     721             : int ASN1CALL
     722    34719825 : der_match_tag2 (const unsigned char *p, size_t len,
     723             :                 Der_class cls, Der_type *type,
     724             :                 unsigned int tag, size_t *size)
     725             : {
     726     1234303 :     size_t l;
     727     1234303 :     Der_class thisclass;
     728     1234303 :     unsigned int thistag;
     729     1234303 :     int e;
     730             : 
     731    34719825 :     if (size)
     732    34719825 :         *size = 0;
     733             : 
     734    34719825 :     e = der_get_tag(p, len, &thisclass, type, &thistag, &l);
     735    34719825 :     if (e) return e;
     736             :     /*
     737             :      * We do depend on ASN1_BAD_ID being returned in places where we're
     738             :      * essentially implementing an application-level CHOICE where we try to
     739             :      * decode one way then the other.  In Heimdal this happens only in lib/hdb/
     740             :      * where we try to decode a blob as an hdb_entry, then as an
     741             :      * hdb_entry_alias.  Applications should really not depend on this.
     742             :      */
     743    34195572 :     if (cls != thisclass && (cls == ASN1_C_APPL || thisclass == ASN1_C_APPL))
     744           0 :         return ASN1_BAD_ID;
     745    34195572 :     if (cls != thisclass || tag != thistag)
     746     1299874 :         return ASN1_MISSING_FIELD;
     747    32847413 :     if (size) *size = l;
     748    31678697 :     return 0;
     749             : }
     750             : 
     751             : /*
     752             :  * Returns 0 if the encoded data at `p' of length `len' starts with the tag of
     753             :  * class `cls`, type `type', and tag value `tag', and puts the length of the
     754             :  * payload (i.e., the length of V in TLV, not the length of TLV) in
     755             :  * `*length_ret', and the size of the whole thing (the TLV) in `*size' if
     756             :  * `size' is not NULL.
     757             :  *
     758             :  * Else returns an error.
     759             :  */
     760             : int ASN1CALL
     761    34719825 : der_match_tag_and_length (const unsigned char *p, size_t len,
     762             :                           Der_class cls, Der_type *type, unsigned int tag,
     763             :                           size_t *length_ret, size_t *size)
     764             : {
     765    34719825 :     size_t l, ret = 0;
     766     1234303 :     int e;
     767             : 
     768    34719825 :     e = der_match_tag2 (p, len, cls, type, tag, &l);
     769    34719825 :     if (e) return e;
     770    32847413 :     p += l;
     771    32847413 :     len -= l;
     772    32847413 :     ret += l;
     773    32847413 :     e = der_get_length (p, len, length_ret, &l);
     774    32847413 :     if (e) return e;
     775    32847413 :     if(size) *size = ret + l;
     776    31678697 :     return 0;
     777             : }
     778             : 
     779             : 
     780             : 
     781             : /*
     782             :  * Old versions of DCE was based on a very early beta of the MIT code,
     783             :  * which used MAVROS for ASN.1 encoding. MAVROS had the interesting
     784             :  * feature that it encoded data in the forward direction, which has
     785             :  * it's problems, since you have no idea how long the data will be
     786             :  * until after you're done. MAVROS solved this by reserving one byte
     787             :  * for length, and later, if the actual length was longer, it reverted
     788             :  * to indefinite, BER style, lengths. The version of MAVROS used by
     789             :  * the DCE people could apparently generate correct X.509 DER encodings, and
     790             :  * did this by making space for the length after encoding, but
     791             :  * unfortunately this feature wasn't used with Kerberos.
     792             :  */
     793             : 
     794             : int
     795           0 : _heim_fix_dce(size_t reallen, size_t *len)
     796             : {
     797           0 :     if(reallen == ASN1_INDEFINITE)
     798           0 :         return 1;
     799           0 :     if(*len < reallen)
     800           0 :         return -1;
     801           0 :     *len = reallen;
     802           0 :     return 0;
     803             : }
     804             : 
     805             : int ASN1CALL
     806         748 : der_get_bit_string (const unsigned char *p, size_t len,
     807             :                     heim_bit_string *data, size_t *size)
     808             : {
     809         748 :     assert(p != NULL);
     810             : 
     811         748 :     if (size)
     812         748 :         *size = 0;
     813             : 
     814         748 :     if (len < 1)
     815           0 :         return ASN1_OVERRUN;
     816         748 :     if (p[0] > 7)
     817           0 :         return ASN1_BAD_FORMAT;
     818         748 :     if (len - 1 == 0 && p[0] != 0)
     819           0 :         return ASN1_BAD_FORMAT;
     820             :     /* check if any of the three upper bits are set
     821             :      * any of them will cause a interger overrun */
     822         748 :     if ((len - 1) >> (sizeof(len) * 8 - 3))
     823           0 :         return ASN1_OVERRUN;
     824             :     /*
     825             :      * If there is data to copy, do that now.
     826             :      */
     827         748 :     if (len - 1 > 0) {
     828         748 :         data->length = (len - 1) * 8;
     829         748 :         data->data = malloc(len - 1);
     830         748 :         if (data->data == NULL) {
     831           0 :             data->length = 0;
     832           0 :             return ENOMEM;
     833             :         }
     834         748 :         memcpy (data->data, p + 1, len - 1);
     835         748 :         data->length -= p[0];
     836             :     } else {
     837           0 :         data->data = NULL;
     838           0 :         data->length = 0;
     839             :     }
     840         748 :     if(size) *size = len;
     841         708 :     return 0;
     842             : }

Generated by: LCOV version 1.14