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 v4-17-test 1498b464 Lines: 223 424 52.6 %
Date: 2024-06-13 04:01:37 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     5245777 : der_get_unsigned (const unsigned char *p, size_t len,
      46             :                   unsigned *ret, size_t *size)
      47             : {
      48     5245777 :     unsigned val = 0;
      49     5245777 :     size_t oldlen = len;
      50             : 
      51     5245777 :     if (len == sizeof(val) + 1 && p[0] == 0)
      52             :         ;
      53     5229092 :     else if (len > sizeof(val))
      54           0 :         return ASN1_OVERRUN;
      55             : 
      56    19733413 :     while (len--)
      57     9241859 :         val = val * 256 + *p++;
      58     5245777 :     *ret = val;
      59     5245777 :     if(size) *size = oldlen;
      60     5245777 :     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     4184027 : der_get_integer (const unsigned char *p, size_t len,
      84             :                  int *ret, size_t *size)
      85             : {
      86     4184027 :     int val = 0;
      87     4184027 :     size_t oldlen = len;
      88             : 
      89     4184027 :     if (len > sizeof(val))
      90           0 :         return ASN1_OVERRUN;
      91             : 
      92     4184027 :     if (len > 0) {
      93     4184027 :         val = (signed char)*p++;
      94     9582965 :         while (--len)
      95     1214911 :             val = val * 256 + *p++;
      96             :     }
      97     4184027 :     *ret = val;
      98     4184027 :     if(size) *size = oldlen;
      99     4184027 :     return 0;
     100             : }
     101             : 
     102             : int ASN1CALL
     103           0 : der_get_integer64 (const unsigned char *p, size_t len,
     104             :                    int64_t *ret, size_t *size)
     105             : {
     106           0 :     int64_t val = 0;
     107           0 :     size_t oldlen = len;
     108             : 
     109           0 :     if (len > sizeof(val))
     110           0 :         return ASN1_OVERRUN;
     111             : 
     112           0 :     if (len > 0) {
     113           0 :        val = (signed char)*p++;
     114           0 :        while (--len)
     115           0 :            val = val * 256 + *p++;
     116             :     }
     117           0 :     *ret = val;
     118           0 :     if(size) *size = oldlen;
     119           0 :     return 0;
     120             : }
     121             : 
     122             : 
     123             : int ASN1CALL
     124    23870769 : der_get_length (const unsigned char *p, size_t len,
     125             :                 size_t *val, size_t *size)
     126             : {
     127             :     size_t v;
     128             : 
     129    23870769 :     if (len <= 0)
     130           0 :         return ASN1_OVERRUN;
     131    23870769 :     --len;
     132    23870769 :     v = *p++;
     133    23870769 :     if (v < 128) {
     134    18698234 :         *val = v;
     135    18698234 :         if(size) *size = 1;
     136             :     } else {
     137             :         int e;
     138             :         size_t l;
     139             :         unsigned tmp;
     140             : 
     141     5172535 :         if(v == 0x80){
     142           0 :             *val = ASN1_INDEFINITE;
     143           0 :             if(size) *size = 1;
     144           0 :             return 0;
     145             :         }
     146     5172535 :         v &= 0x7F;
     147     5172535 :         if (len < v)
     148           0 :             return ASN1_OVERRUN;
     149     5172535 :         e = der_get_unsigned (p, v, &tmp, &l);
     150     5172535 :         if(e) return e;
     151     5172535 :         *val = tmp;
     152     5172535 :         if(size) *size = l + 1;
     153             :     }
     154    23870769 :     return 0;
     155             : }
     156             : 
     157             : int ASN1CALL
     158         619 : der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
     159             : {
     160         619 :     if(len < 1)
     161           0 :         return ASN1_OVERRUN;
     162         619 :     if(*p != 0)
     163         619 :         *data = 1;
     164             :     else
     165           0 :         *data = 0;
     166         619 :     *size = 1;
     167         619 :     return 0;
     168             : }
     169             : 
     170             : int ASN1CALL
     171     1747715 : der_get_general_string (const unsigned char *p, size_t len,
     172             :                         heim_general_string *str, size_t *size)
     173             : {
     174             :     const unsigned char *p1;
     175             :     char *s;
     176             : 
     177     1747715 :     assert(p != NULL);
     178             : 
     179     1747715 :     if (size)
     180     1747715 :         *size = 0;
     181             : 
     182     1747715 :     p1 = memchr(p, 0, len);
     183     1747715 :     if (p1 != NULL) {
     184             :         /*
     185             :          * Allow trailing NULs. We allow this since MIT Kerberos sends
     186             :          * an strings in the NEED_PREAUTH case that includes a
     187             :          * trailing NUL.
     188             :          */
     189           0 :         while ((size_t)(p1 - p) < len && *p1 == '\0')
     190           0 :             p1++;
     191           0 :         if ((size_t)(p1 - p) != len) {
     192           0 :             *str = NULL;
     193           0 :             return ASN1_BAD_CHARACTER;
     194             :         }
     195             :     }
     196     1747715 :     if (len == SIZE_MAX) {
     197           0 :         *str = NULL;
     198           0 :         return ASN1_BAD_LENGTH;
     199             :     }
     200             : 
     201     1747715 :     *str = s = malloc (len + 1);
     202     1747715 :     if (s == NULL)
     203           0 :         return ENOMEM;
     204     1747715 :     memcpy (s, p, len);
     205     1747715 :     s[len] = '\0';
     206             : 
     207     1747715 :     if(size) *size = len;
     208     1747715 :     return 0;
     209             : }
     210             : 
     211             : int ASN1CALL
     212         963 : der_get_utf8string (const unsigned char *p, size_t len,
     213             :                     heim_utf8_string *str, size_t *size)
     214             : {
     215         963 :     return der_get_general_string(p, len, str, size);
     216             : }
     217             : 
     218             : #define gen_data_zero(_data) \
     219             :         do { (_data)->length = 0; (_data)->data = NULL; } while(0)
     220             : 
     221             : int ASN1CALL
     222        1006 : der_get_printable_string(const unsigned char *p, size_t len,
     223             :                          heim_printable_string *str, size_t *size)
     224             : {
     225        1006 :     assert(p != NULL);
     226             : 
     227        1006 :     if (size)
     228        1006 :         *size = 0;
     229             : 
     230        1006 :     if (len == SIZE_MAX) {
     231           0 :         gen_data_zero(str);
     232           0 :         return ASN1_BAD_LENGTH;
     233             :     }
     234        1006 :     str->length = len;
     235        1006 :     str->data = malloc(len + 1);
     236        1006 :     if (str->data == NULL) {
     237           0 :         gen_data_zero(str);
     238           0 :         return ENOMEM;
     239             :     }
     240             : 
     241        1006 :     memcpy(str->data, p, len);
     242        1006 :     ((char *)str->data)[len] = '\0';
     243        1006 :     if(size) *size = len;
     244        1006 :     return 0;
     245             : }
     246             : 
     247             : int ASN1CALL
     248         500 : der_get_ia5_string(const unsigned char *p, size_t len,
     249             :                    heim_ia5_string *str, size_t *size)
     250             : {
     251         500 :     return der_get_printable_string(p, len, str, size);
     252             : }
     253             : 
     254             : int ASN1CALL
     255           0 : der_get_bmp_string (const unsigned char *p, size_t len,
     256             :                     heim_bmp_string *data, size_t *size)
     257             : {
     258             :     size_t i;
     259             : 
     260           0 :     assert(p != NULL);
     261             : 
     262           0 :     if (size)
     263           0 :         *size = 0;
     264             : 
     265           0 :     if (len & 1) {
     266           0 :         gen_data_zero(data);
     267           0 :         return ASN1_BAD_FORMAT;
     268             :     }
     269           0 :     data->length = len / 2;
     270           0 :     if (data->length > UINT_MAX/sizeof(data->data[0])) {
     271           0 :         gen_data_zero(data);
     272           0 :         return ERANGE;
     273             :     }
     274           0 :     data->data = malloc(data->length * sizeof(data->data[0]));
     275           0 :     if (data->data == NULL && data->length != 0) {
     276           0 :         gen_data_zero(data);
     277           0 :         return ENOMEM;
     278             :     }
     279             : 
     280           0 :     for (i = 0; i < data->length; i++) {
     281           0 :         data->data[i] = (p[0] << 8) | p[1];
     282           0 :         p += 2;
     283             :         /* check for NUL in the middle of the string */
     284           0 :         if (data->data[i] == 0 && i != (data->length - 1)) {
     285           0 :             free(data->data);
     286           0 :             gen_data_zero(data);
     287           0 :             return ASN1_BAD_CHARACTER;
     288             :         }
     289             :     }
     290           0 :     if (size) *size = len;
     291             : 
     292           0 :     return 0;
     293             : }
     294             : 
     295             : int ASN1CALL
     296           0 : der_get_universal_string (const unsigned char *p, size_t len,
     297             :                           heim_universal_string *data, size_t *size)
     298             : {
     299             :     size_t i;
     300             : 
     301           0 :     assert(p != NULL);
     302             : 
     303           0 :     if (size)
     304           0 :         *size = 0;
     305             : 
     306           0 :     if (len & 3) {
     307           0 :         gen_data_zero(data);
     308           0 :         return ASN1_BAD_FORMAT;
     309             :     }
     310           0 :     data->length = len / 4;
     311           0 :     if (data->length > UINT_MAX/sizeof(data->data[0])) {
     312           0 :         gen_data_zero(data);
     313           0 :         return ERANGE;
     314             :     }
     315           0 :     data->data = malloc(data->length * sizeof(data->data[0]));
     316           0 :     if (data->data == NULL && data->length != 0) {
     317           0 :         gen_data_zero(data);
     318           0 :         return ENOMEM;
     319             :     }
     320             : 
     321           0 :     for (i = 0; i < data->length; i++) {
     322           0 :         data->data[i] = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
     323           0 :         p += 4;
     324             :         /* check for NUL in the middle of the string */
     325           0 :         if (data->data[i] == 0 && i != (data->length - 1)) {
     326           0 :             free(data->data);
     327           0 :             gen_data_zero(data);
     328           0 :             return ASN1_BAD_CHARACTER;
     329             :         }
     330             :     }
     331           0 :     if (size) *size = len;
     332           0 :     return 0;
     333             : }
     334             : 
     335             : int ASN1CALL
     336           0 : der_get_visible_string (const unsigned char *p, size_t len,
     337             :                         heim_visible_string *str, size_t *size)
     338             : {
     339           0 :     return der_get_general_string(p, len, str, size);
     340             : }
     341             : 
     342             : int ASN1CALL
     343     1535371 : der_get_octet_string (const unsigned char *p, size_t len,
     344             :                       heim_octet_string *data, size_t *size)
     345             : {
     346     1535371 :     assert(p != NULL);
     347             : 
     348     1535371 :     if (size)
     349     1535371 :         *size = 0;
     350             : 
     351     1535371 :     if (len == 0)
     352      188249 :         data->data = malloc(1);
     353             :     else
     354     1347122 :         data->data = malloc(len);
     355     1535371 :     if (data->data == NULL) {
     356           0 :         data->length = 0;
     357           0 :         return ENOMEM;
     358             :     }
     359     1535371 :     data->length = len;
     360     1535371 :     memcpy (data->data, p, len);
     361     1535371 :     if (size)
     362     1535371 :         *size = len;
     363     1535371 :     return 0;
     364             : }
     365             : 
     366             : int ASN1CALL
     367           0 : der_get_octet_string_ber (const unsigned char *p, size_t len,
     368             :                           heim_octet_string *data, size_t *size)
     369             : {
     370             :     int e;
     371             :     Der_type type;
     372             :     Der_class cls;
     373           0 :     unsigned int tag, depth = 0;
     374           0 :     size_t l, datalen, oldlen = len;
     375             : 
     376           0 :     assert(p != NULL);
     377             : 
     378           0 :     if (size)
     379           0 :         *size = 0;
     380             : 
     381           0 :     data->length = 0;
     382           0 :     data->data = NULL;
     383             : 
     384           0 :     while (len) {
     385           0 :         e = der_get_tag (p, len, &cls, &type, &tag, &l);
     386           0 :         if (e) goto out;
     387           0 :         if (cls != ASN1_C_UNIV) {
     388           0 :             e = ASN1_BAD_ID;
     389           0 :             goto out;
     390             :         }
     391           0 :         if (type == PRIM && tag == UT_EndOfContent) {
     392           0 :             if (depth == 0)
     393           0 :                 break;
     394           0 :             depth--;
     395             :         }
     396           0 :         if (tag != UT_OctetString) {
     397           0 :             e = ASN1_BAD_ID;
     398           0 :             goto out;
     399             :         }
     400             : 
     401           0 :         p += l;
     402           0 :         len -= l;
     403           0 :         e = der_get_length (p, len, &datalen, &l);
     404           0 :         if (e) goto out;
     405           0 :         p += l;
     406           0 :         len -= l;
     407             : 
     408           0 :         if (datalen > len)
     409           0 :             return ASN1_OVERRUN;
     410             : 
     411           0 :         if (type == PRIM && datalen) {
     412             :             void *ptr;
     413             : 
     414           0 :             ptr = realloc(data->data, data->length + datalen);
     415           0 :             if (ptr == NULL) {
     416           0 :                 e = ENOMEM;
     417           0 :                 goto out;
     418             :             }
     419           0 :             data->data = ptr;
     420           0 :             memcpy(((unsigned char *)data->data) + data->length, p, datalen);
     421           0 :             data->length += datalen;
     422           0 :         } else if (type != PRIM)
     423           0 :             depth++;
     424             : 
     425           0 :         p += datalen;
     426           0 :         len -= datalen;
     427             :     }
     428           0 :     if (depth != 0)
     429           0 :         return ASN1_INDEF_OVERRUN;
     430           0 :     if(size) *size = oldlen - len;
     431           0 :     return 0;
     432           0 :  out:
     433           0 :     free(data->data);
     434           0 :     data->data = NULL;
     435           0 :     data->length = 0;
     436           0 :     return e;
     437             : }
     438             : 
     439             : 
     440             : int ASN1CALL
     441         531 : der_get_heim_integer (const unsigned char *p, size_t len,
     442             :                       heim_integer *data, size_t *size)
     443             : {
     444         531 :     data->length = 0;
     445         531 :     data->negative = 0;
     446         531 :     data->data = NULL;
     447             : 
     448         531 :     if (size)
     449         531 :         *size = 0;
     450             : 
     451         531 :     if (len == 0)
     452           0 :         return 0;
     453             : 
     454         531 :     assert(p != NULL);
     455             : 
     456         531 :     if (p[0] & 0x80) {
     457             :         unsigned char *q;
     458          49 :         int carry = 1;
     459          49 :         data->negative = 1;
     460             : 
     461          49 :         data->length = len;
     462             : 
     463          49 :         if (p[0] == 0xff) {
     464           0 :             p++;
     465           0 :             data->length--;
     466             :         }
     467          49 :         data->data = malloc(data->length);
     468          49 :         if (data->data == NULL) {
     469           0 :             data->length = 0;
     470           0 :             if (size)
     471           0 :                 *size = 0;
     472           0 :             return ENOMEM;
     473             :         }
     474          49 :         q = &((unsigned char*)data->data)[data->length - 1];
     475          49 :         p += data->length - 1;
     476         294 :         while (q >= (unsigned char*)data->data) {
     477         196 :             *q = *p ^ 0xff;
     478         196 :             if (carry)
     479          49 :                 carry = !++*q;
     480         196 :             p--;
     481         196 :             q--;
     482             :         }
     483             :     } else {
     484         482 :         data->negative = 0;
     485         482 :         data->length = len;
     486             : 
     487         482 :         if (p[0] == 0) {
     488         220 :             p++;
     489         220 :             data->length--;
     490             :         }
     491         482 :         data->data = malloc(data->length);
     492         482 :         if (data->data == NULL && data->length != 0) {
     493           0 :             data->length = 0;
     494           0 :             if (size)
     495           0 :                 *size = 0;
     496           0 :             return ENOMEM;
     497             :         }
     498         482 :         memcpy(data->data, p, data->length);
     499             :     }
     500         531 :     if (size)
     501         531 :         *size = len;
     502         531 :     return 0;
     503             : }
     504             : 
     505             : static int
     506      734618 : generalizedtime2time (const char *s, time_t *t)
     507             : {
     508             :     struct tm tm;
     509             : 
     510      734618 :     memset(&tm, 0, sizeof(tm));
     511      734618 :     if (sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
     512             :                 &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
     513             :                 &tm.tm_min, &tm.tm_sec) != 6) {
     514         302 :         if (sscanf (s, "%02d%02d%02d%02d%02d%02dZ",
     515             :                     &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
     516             :                     &tm.tm_min, &tm.tm_sec) != 6)
     517           0 :             return ASN1_BAD_TIMEFORMAT;
     518         302 :         if (tm.tm_year < 50)
     519         302 :             tm.tm_year += 2000;
     520             :         else
     521           0 :             tm.tm_year += 1900;
     522             :     }
     523      734618 :     tm.tm_year -= 1900;
     524      734618 :     tm.tm_mon -= 1;
     525      734618 :     *t = _der_timegm (&tm);
     526      734618 :     return 0;
     527             : }
     528             : 
     529             : static int ASN1CALL
     530      734618 : der_get_time (const unsigned char *p, size_t len,
     531             :               time_t *data, size_t *size)
     532             : {
     533             :     char *times;
     534             :     int e;
     535             : 
     536      734618 :     assert(p != NULL);
     537             : 
     538      734618 :     if (size)
     539      734618 :         *size = 0;
     540             : 
     541      734618 :     if (len == SIZE_MAX || len == 0)
     542           0 :         return ASN1_BAD_LENGTH;
     543             : 
     544      734618 :     times = malloc(len + 1);
     545      734618 :     if (times == NULL)
     546           0 :         return ENOMEM;
     547      734618 :     memcpy(times, p, len);
     548      734618 :     times[len] = '\0';
     549      734618 :     e = generalizedtime2time(times, data);
     550      734618 :     free (times);
     551      734618 :     if(size) *size = len;
     552      734618 :     return e;
     553             : }
     554             : 
     555             : int ASN1CALL
     556      734316 : der_get_generalized_time (const unsigned char *p, size_t len,
     557             :                           time_t *data, size_t *size)
     558             : {
     559      734316 :     return der_get_time(p, len, data, size);
     560             : }
     561             : 
     562             : int ASN1CALL
     563         302 : der_get_utctime (const unsigned char *p, size_t len,
     564             :                           time_t *data, size_t *size)
     565             : {
     566         302 :     return der_get_time(p, len, data, size);
     567             : }
     568             : 
     569             : int ASN1CALL
     570       54478 : der_get_oid (const unsigned char *p, size_t len,
     571             :              heim_oid *data, size_t *size)
     572             : {
     573             :     size_t n;
     574       54478 :     size_t oldlen = len;
     575             : 
     576       54478 :     assert(p != NULL);
     577             : 
     578       54478 :     if (size)
     579       18180 :         *size = 0;
     580             : 
     581       54478 :     if (len < 1)
     582           0 :         return ASN1_OVERRUN;
     583             : 
     584       54478 :     if (len == SIZE_MAX)
     585           0 :         return ASN1_BAD_LENGTH;
     586             : 
     587       54478 :     if (len + 1 > UINT_MAX/sizeof(data->components[0]))
     588           0 :         return ERANGE;
     589             : 
     590       54478 :     data->components = malloc((len + 1) * sizeof(data->components[0]));
     591       54478 :     if (data->components == NULL) {
     592           0 :         data->length = 0;
     593           0 :         return ENOMEM;
     594             :     }
     595       54478 :     data->components[0] = (*p) / 40;
     596       54478 :     data->components[1] = (*p) % 40;
     597       54478 :     --len;
     598       54478 :     ++p;
     599      302098 :     for (n = 2; len > 0; ++n) {
     600      247620 :         unsigned u = 0, u1;
     601             : 
     602             :         do {
     603      348770 :             --len;
     604      348770 :             u1 = u * 128 + (*p++ % 128);
     605             :             /* check that we don't overflow the element */
     606      348770 :             if (u1 < u) {
     607           0 :                 der_free_oid(data);
     608           0 :                 return ASN1_OVERRUN;
     609             :             }
     610      348770 :             u = u1;
     611      348770 :         } while (len > 0 && p[-1] & 0x80);
     612      247620 :         data->components[n] = u;
     613             :     }
     614       54478 :     if (n > 2 && p[-1] & 0x80) {
     615           0 :         der_free_oid (data);
     616           0 :         return ASN1_OVERRUN;
     617             :     }
     618       54478 :     data->length = n;
     619       54478 :     if (size)
     620       18180 :         *size = oldlen;
     621       54478 :     return 0;
     622             : }
     623             : 
     624             : int ASN1CALL
     625    25010792 : der_get_tag (const unsigned char *p, size_t len,
     626             :              Der_class *cls, Der_type *type,
     627             :              unsigned int *tag, size_t *size)
     628             : {
     629    25010792 :     size_t ret = 0;
     630             : 
     631    25010792 :     if (size)
     632    25010792 :         *size = 0;
     633             : 
     634    25010792 :     if (len < 1)
     635      364238 :         return ASN1_MISSING_FIELD;
     636             : 
     637    24646554 :     assert(p != NULL);
     638             : 
     639    24646554 :     *cls = (Der_class)(((*p) >> 6) & 0x03);
     640    24646554 :     *type = (Der_type)(((*p) >> 5) & 0x01);
     641    24646554 :     *tag = (*p) & 0x1f;
     642    24646554 :     p++; len--; ret++;
     643    24646554 :     if(*tag == 0x1f) {
     644             :         unsigned int continuation;
     645             :         unsigned int tag1;
     646           0 :         *tag = 0;
     647             :         do {
     648           0 :             if(len < 1)
     649           0 :                 return ASN1_OVERRUN;
     650           0 :             continuation = *p & 128;
     651           0 :             tag1 = *tag * 128 + (*p % 128);
     652             :             /* check that we don't overflow the tag */
     653           0 :             if (tag1 < *tag)
     654           0 :                 return ASN1_OVERFLOW;
     655           0 :             *tag = tag1;
     656           0 :             p++; len--; ret++;
     657           0 :         } while(continuation);
     658             :     }
     659    24646554 :     if(size) *size = ret;
     660    24646554 :     return 0;
     661             : }
     662             : 
     663             : int ASN1CALL
     664           0 : der_match_tag (const unsigned char *p, size_t len,
     665             :                Der_class cls, Der_type type,
     666             :                unsigned int tag, size_t *size)
     667             : {
     668             :     Der_type thistype;
     669             :     int e;
     670             : 
     671           0 :     e = der_match_tag2(p, len, cls, &thistype, tag, size);
     672           0 :     if (e) return e;
     673           0 :     if (thistype != type) return ASN1_BAD_ID;
     674           0 :     return 0;
     675             : }
     676             : 
     677             : int ASN1CALL
     678    25010072 : der_match_tag2 (const unsigned char *p, size_t len,
     679             :                 Der_class cls, Der_type *type,
     680             :                 unsigned int tag, size_t *size)
     681             : {
     682             :     size_t l;
     683             :     Der_class thisclass;
     684             :     unsigned int thistag;
     685             :     int e;
     686             : 
     687    25010072 :     if (size)
     688    25010072 :         *size = 0;
     689             : 
     690    25010072 :     e = der_get_tag(p, len, &thisclass, type, &thistag, &l);
     691    25010072 :     if (e) return e;
     692             :     /*
     693             :      * We do depend on ASN1_BAD_ID being returned in places where we're
     694             :      * essentially implementing an application-level CHOICE where we try to
     695             :      * decode one way then the other.  In Heimdal this happens only in lib/hdb/
     696             :      * where we try to decode a blob as an hdb_entry, then as an
     697             :      * hdb_entry_alias.  Applications should really not depend on this.
     698             :      */
     699    24645834 :     if (cls != thisclass && (cls == ASN1_C_APPL || thisclass == ASN1_C_APPL))
     700           0 :         return ASN1_BAD_ID;
     701    24645834 :     if (cls != thisclass || tag != thistag)
     702      949347 :         return ASN1_MISSING_FIELD;
     703    23696487 :     if (size) *size = l;
     704    23696487 :     return 0;
     705             : }
     706             : 
     707             : /*
     708             :  * Returns 0 if the encoded data at `p' of length `len' starts with the tag of
     709             :  * class `cls`, type `type', and tag value `tag', and puts the length of the
     710             :  * payload (i.e., the length of V in TLV, not the length of TLV) in
     711             :  * `*length_ret', and the size of the whole thing (the TLV) in `*size' if
     712             :  * `size' is not NULL.
     713             :  *
     714             :  * Else returns an error.
     715             :  */
     716             : int ASN1CALL
     717    25010072 : der_match_tag_and_length (const unsigned char *p, size_t len,
     718             :                           Der_class cls, Der_type *type, unsigned int tag,
     719             :                           size_t *length_ret, size_t *size)
     720             : {
     721    25010072 :     size_t l, ret = 0;
     722             :     int e;
     723             : 
     724    25010072 :     e = der_match_tag2 (p, len, cls, type, tag, &l);
     725    25010072 :     if (e) return e;
     726    23696487 :     p += l;
     727    23696487 :     len -= l;
     728    23696487 :     ret += l;
     729    23696487 :     e = der_get_length (p, len, length_ret, &l);
     730    23696487 :     if (e) return e;
     731    23696487 :     if(size) *size = ret + l;
     732    23696487 :     return 0;
     733             : }
     734             : 
     735             : 
     736             : 
     737             : /*
     738             :  * Old versions of DCE was based on a very early beta of the MIT code,
     739             :  * which used MAVROS for ASN.1 encoding. MAVROS had the interesting
     740             :  * feature that it encoded data in the forward direction, which has
     741             :  * it's problems, since you have no idea how long the data will be
     742             :  * until after you're done. MAVROS solved this by reserving one byte
     743             :  * for length, and later, if the actual length was longer, it reverted
     744             :  * to indefinite, BER style, lengths. The version of MAVROS used by
     745             :  * the DCE people could apparently generate correct X.509 DER encodings, and
     746             :  * did this by making space for the length after encoding, but
     747             :  * unfortunately this feature wasn't used with Kerberos.
     748             :  */
     749             : 
     750             : int
     751           0 : _heim_fix_dce(size_t reallen, size_t *len)
     752             : {
     753           0 :     if(reallen == ASN1_INDEFINITE)
     754           0 :         return 1;
     755           0 :     if(*len < reallen)
     756           0 :         return -1;
     757           0 :     *len = reallen;
     758           0 :     return 0;
     759             : }
     760             : 
     761             : int ASN1CALL
     762         302 : der_get_bit_string (const unsigned char *p, size_t len,
     763             :                     heim_bit_string *data, size_t *size)
     764             : {
     765         302 :     assert(p != NULL);
     766             : 
     767         302 :     if (size)
     768         302 :         *size = 0;
     769             : 
     770         302 :     if (len < 1)
     771           0 :         return ASN1_OVERRUN;
     772         302 :     if (p[0] > 7)
     773           0 :         return ASN1_BAD_FORMAT;
     774         302 :     if (len - 1 == 0 && p[0] != 0)
     775           0 :         return ASN1_BAD_FORMAT;
     776             :     /* check if any of the three upper bits are set
     777             :      * any of them will cause a interger overrun */
     778         302 :     if ((len - 1) >> (sizeof(len) * 8 - 3))
     779           0 :         return ASN1_OVERRUN;
     780             :     /*
     781             :      * If there is data to copy, do that now.
     782             :      */
     783         302 :     if (len - 1 > 0) {
     784         302 :         data->length = (len - 1) * 8;
     785         302 :         data->data = malloc(len - 1);
     786         302 :         if (data->data == NULL) {
     787           0 :             data->length = 0;
     788           0 :             return ENOMEM;
     789             :         }
     790         302 :         memcpy (data->data, p + 1, len - 1);
     791         302 :         data->length -= p[0];
     792             :     } else {
     793           0 :         data->data = NULL;
     794           0 :         data->length = 0;
     795             :     }
     796         302 :     if(size) *size = len;
     797         302 :     return 0;
     798             : }

Generated by: LCOV version 1.13