"Fossies" - the Fresh Open Source Software Archive

Member "libksba-1.6.0/src/ber-help.c" (18 May 2021, 17838 Bytes) of package /linux/privat/libksba-1.6.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /* ber-help.c - BER herlper functions
    2  *      Copyright (C) 2001, 2012 g10 Code GmbH
    3  *
    4  * This file is part of KSBA.
    5  *
    6  * KSBA is free software; you can redistribute it and/or modify
    7  * it under the terms of either
    8  *
    9  *   - the GNU Lesser General Public License as published by the Free
   10  *     Software Foundation; either version 3 of the License, or (at
   11  *     your option) any later version.
   12  *
   13  * or
   14  *
   15  *   - the GNU General Public License as published by the Free
   16  *     Software Foundation; either version 2 of the License, or (at
   17  *     your option) any later version.
   18  *
   19  * or both in parallel, as here.
   20  *
   21  * KSBA is distributed in the hope that it will be useful, but WITHOUT
   22  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   23  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   24  * License for more details.
   25  *
   26  * You should have received a copies of the GNU General Public License
   27  * and the GNU Lesser General Public License along with this program;
   28  * if not, see <http://www.gnu.org/licenses/>.
   29  */
   30 
   31 #include <config.h>
   32 #include <stdio.h>
   33 #include <stdlib.h>
   34 #include <string.h>
   35 #include <assert.h>
   36 #include "util.h"
   37 
   38 #include "asn1-func.h" /* need some constants */
   39 #include "convert.h"
   40 #include "ber-help.h"
   41 
   42 /* Fixme: The parser functions should check that primitive types don't
   43    have the constructed bit set (which is not allowed).  This saves us
   44    some work when using these parsers */
   45 
   46 static int
   47 read_byte (ksba_reader_t reader)
   48 {
   49   unsigned char buf;
   50   size_t nread;
   51   int rc;
   52 
   53   do
   54     rc = ksba_reader_read (reader, &buf, 1, &nread);
   55   while (!rc && !nread);
   56   return rc? -1: buf;
   57 }
   58 
   59 
   60 static int
   61 premature_eof (struct tag_info *ti)
   62 {
   63   /* Note: We do an strcmp on this string at other places. */
   64   ti->err_string = "premature EOF";
   65   return gpg_error (GPG_ERR_BAD_BER);
   66 }
   67 
   68 
   69 
   70 static gpg_error_t
   71 eof_or_error (ksba_reader_t reader, struct tag_info *ti, int premature)
   72 {
   73   gpg_error_t err;
   74 
   75   err = ksba_reader_error (reader);
   76   if (err)
   77     {
   78       ti->err_string = "read error";
   79       return err;
   80     }
   81   if (premature)
   82     return premature_eof (ti);
   83 
   84   return gpg_error (GPG_ERR_EOF);
   85 }
   86 
   87 
   88 
   89 /*
   90    Read the tag and the length part from the TLV triplet.
   91  */
   92 gpg_error_t
   93 _ksba_ber_read_tl (ksba_reader_t reader, struct tag_info *ti)
   94 {
   95   int c;
   96   unsigned long tag;
   97 
   98   ti->length = 0;
   99   ti->ndef = 0;
  100   ti->nhdr = 0;
  101   ti->err_string = NULL;
  102   ti->non_der = 0;
  103 
  104   /* Get the tag */
  105   c = read_byte (reader);
  106   if (c==-1)
  107     return eof_or_error (reader, ti, 0);
  108 
  109   ti->buf[ti->nhdr++] = c;
  110   ti->class = (c & 0xc0) >> 6;
  111   ti->is_constructed = !!(c & 0x20);
  112   tag = c & 0x1f;
  113 
  114   if (tag == 0x1f)
  115     {
  116       tag = 0;
  117       do
  118         {
  119           /* We silently ignore an overflow in the tag value.  It is
  120              not worth checking for it. */
  121           tag <<= 7;
  122           c = read_byte (reader);
  123           if (c == -1)
  124             return eof_or_error (reader, ti, 1);
  125           if (ti->nhdr >= DIM (ti->buf))
  126             {
  127               ti->err_string = "tag+length header too large";
  128               return gpg_error (GPG_ERR_BAD_BER);
  129             }
  130           ti->buf[ti->nhdr++] = c;
  131           tag |= c & 0x7f;
  132         }
  133       while (c & 0x80);
  134     }
  135   ti->tag = tag;
  136 
  137   /* Get the length */
  138   c = read_byte (reader);
  139   if (c == -1)
  140     return eof_or_error (reader, ti, 1);
  141   if (ti->nhdr >= DIM (ti->buf))
  142     {
  143       ti->err_string = "tag+length header too large";
  144       return gpg_error (GPG_ERR_BAD_BER);
  145     }
  146   ti->buf[ti->nhdr++] = c;
  147 
  148   if ( !(c & 0x80) )
  149     ti->length = c;
  150   else if (c == 0x80)
  151     {
  152       ti->ndef = 1;
  153       ti->non_der = 1;
  154     }
  155   else if (c == 0xff)
  156     {
  157       ti->err_string = "forbidden length value";
  158       return gpg_error (GPG_ERR_BAD_BER);
  159     }
  160   else
  161     {
  162       unsigned long len = 0;
  163       int count = c & 0x7f;
  164 
  165       if (count > sizeof (len) || count > sizeof (size_t))
  166         return gpg_error (GPG_ERR_BAD_BER);
  167 
  168       for (; count; count--)
  169         {
  170           len <<= 8;
  171           c = read_byte (reader);
  172           if (c == -1)
  173             return eof_or_error (reader, ti, 1);
  174           if (ti->nhdr >= DIM (ti->buf))
  175             {
  176               ti->err_string = "tag+length header too large";
  177               return gpg_error (GPG_ERR_BAD_BER);
  178             }
  179           ti->buf[ti->nhdr++] = c;
  180           len |= c & 0xff;
  181         }
  182       ti->length = len;
  183     }
  184 
  185   /* Without this kludge some example certs can't be parsed */
  186   if (ti->class == CLASS_UNIVERSAL && !ti->tag)
  187     ti->length = 0;
  188 
  189   return 0;
  190 }
  191 
  192 
  193 /* Parse the buffer at the address BUFFER which of SIZE and return the
  194  * tag and the length part from the TLV triplet.  Update BUFFER and
  195  * SIZE on success.  Note that this function will never return
  196  * GPG_ERR_INV_OBJ so that this error code can be used by the parse_foo
  197  * functions below to return an error for unexpected tags and the
  198  * caller is able to backoff in that case.  */
  199 gpg_error_t
  200 _ksba_ber_parse_tl (unsigned char const **buffer, size_t *size,
  201                     struct tag_info *ti)
  202 {
  203   int c;
  204   unsigned long tag;
  205   const unsigned char *buf = *buffer;
  206   size_t length = *size;
  207 
  208   ti->length = 0;
  209   ti->ndef = 0;
  210   ti->nhdr = 0;
  211   ti->err_string = NULL;
  212   ti->non_der = 0;
  213 
  214   /* Get the tag */
  215   if (!length)
  216     return premature_eof (ti);
  217   c = *buf++; length--;
  218 
  219   ti->buf[ti->nhdr++] = c;
  220   ti->class = (c & 0xc0) >> 6;
  221   ti->is_constructed = !!(c & 0x20);
  222   tag = c & 0x1f;
  223 
  224   if (tag == 0x1f)
  225     {
  226       tag = 0;
  227       do
  228         {
  229           /* We silently ignore an overflow in the tag value.  It is
  230              not worth checking for it. */
  231           tag <<= 7;
  232           if (!length)
  233             return premature_eof (ti);
  234           c = *buf++; length--;
  235           if (ti->nhdr >= DIM (ti->buf))
  236             {
  237               ti->err_string = "tag+length header too large";
  238               return gpg_error (GPG_ERR_BAD_BER);
  239             }
  240           ti->buf[ti->nhdr++] = c;
  241           tag |= c & 0x7f;
  242         }
  243       while (c & 0x80);
  244     }
  245   ti->tag = tag;
  246 
  247   /* Get the length */
  248   if (!length)
  249     return premature_eof (ti);
  250   c = *buf++; length--;
  251   if (ti->nhdr >= DIM (ti->buf))
  252     {
  253       ti->err_string = "tag+length header too large";
  254       return gpg_error (GPG_ERR_BAD_BER);
  255     }
  256   ti->buf[ti->nhdr++] = c;
  257 
  258   if ( !(c & 0x80) )
  259     ti->length = c;
  260   else if (c == 0x80)
  261     {
  262       ti->ndef = 1;
  263       ti->non_der = 1;
  264     }
  265   else if (c == 0xff)
  266     {
  267       ti->err_string = "forbidden length value";
  268       return gpg_error (GPG_ERR_BAD_BER);
  269     }
  270   else
  271     {
  272       unsigned long len = 0;
  273       int count = c & 0x7f;
  274 
  275       if (count > sizeof (len) || count > sizeof (size_t))
  276         return gpg_error (GPG_ERR_BAD_BER);
  277 
  278       for (; count; count--)
  279         {
  280           len <<= 8;
  281           if (!length)
  282             return premature_eof (ti);
  283           c = *buf++; length--;
  284           if (ti->nhdr >= DIM (ti->buf))
  285             {
  286               ti->err_string = "tag+length header too large";
  287               return gpg_error (GPG_ERR_BAD_BER);
  288             }
  289           ti->buf[ti->nhdr++] = c;
  290           len |= c & 0xff;
  291         }
  292       /* Sanity check for the length: This is done so that we can take
  293        * the value for malloc plus some additional bytes without
  294        * risking an overflow.  */
  295       if (len > (1 << 30))
  296         return gpg_error (GPG_ERR_BAD_BER);
  297       ti->length = len;
  298     }
  299 
  300 
  301   /* Without this kludge some example certs can't be parsed */
  302   if (ti->class == CLASS_UNIVERSAL && !ti->tag)
  303     ti->length = 0;
  304 
  305   *buffer = buf;
  306   *size = length;
  307   return 0;
  308 }
  309 
  310 
  311 /* Write TAG of CLASS to WRITER.  constructed is a flag telling
  312    whether the value is a constructed one.  length gives the length of
  313    the value, if it is 0 undefinite length is assumed.  length is
  314    ignored for the NULL tag. */
  315 gpg_error_t
  316 _ksba_ber_write_tl (ksba_writer_t writer,
  317                     unsigned long tag,
  318                     enum tag_class class,
  319                     int constructed,
  320                     unsigned long length)
  321 {
  322   unsigned char buf[50];
  323   int buflen = 0;
  324 
  325   if (tag < 0x1f)
  326     {
  327       *buf = (class << 6) | tag;
  328       if (constructed)
  329         *buf |= 0x20;
  330       buflen++;
  331     }
  332   else
  333     {
  334       return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
  335     }
  336 
  337   if (!tag && !class)
  338     buf[buflen++] = 0; /* end tag */
  339   else if (tag == TYPE_NULL && !class)
  340     buf[buflen++] = 0; /* NULL tag */
  341   else if (!length)
  342     buf[buflen++] = 0x80; /* indefinite length */
  343   else if (length < 128)
  344     buf[buflen++] = length;
  345   else
  346     {
  347       int i;
  348 
  349       /* fixme: if we know the sizeof an ulong we could support larger
  350          objects - however this is pretty ridiculous */
  351       i = (length <= 0xff ? 1:
  352            length <= 0xffff ? 2:
  353            length <= 0xffffff ? 3: 4);
  354 
  355       buf[buflen++] = (0x80 | i);
  356       if (i > 3)
  357         buf[buflen++] = length >> 24;
  358       if (i > 2)
  359         buf[buflen++] = length >> 16;
  360       if (i > 1)
  361         buf[buflen++] = length >> 8;
  362       buf[buflen++] = length;
  363     }
  364 
  365   return ksba_writer_write (writer, buf, buflen);
  366 }
  367 
  368 /* Encode TAG of CLASS in BUFFER.  CONSTRUCTED is a flag telling
  369    whether the value is a constructed one.  LENGTH gives the length of
  370    the value, if it is 0 undefinite length is assumed.  LENGTH is
  371    ignored for the NULL tag. It is assumed that the provide buffer is
  372    large enough for storing the result - this is usually achieved by
  373    using _ksba_ber_count_tl() in advance.  Returns 0 in case of an
  374    error or the length of the encoding.*/
  375 size_t
  376 _ksba_ber_encode_tl (unsigned char *buffer,
  377                      unsigned long tag,
  378                      enum tag_class class,
  379                      int constructed,
  380                      unsigned long length)
  381 {
  382   unsigned char *buf = buffer;
  383 
  384   if (tag < 0x1f)
  385     {
  386       *buf = (class << 6) | tag;
  387       if (constructed)
  388         *buf |= 0x20;
  389       buf++;
  390     }
  391   else
  392     {
  393       return 0; /*Not implemented*/
  394     }
  395 
  396   if (!tag && !class)
  397     *buf++ = 0; /* end tag */
  398   else if (tag == TYPE_NULL && !class)
  399     *buf++ = 0; /* NULL tag */
  400   else if (!length)
  401     *buf++ = 0x80; /* indefinite length */
  402   else if (length < 128)
  403     *buf++ = length;
  404   else
  405     {
  406       int i;
  407 
  408       /* fixme: if we know the sizeof an ulong we could support larger
  409          objetcs - however this is pretty ridiculous */
  410       i = (length <= 0xff ? 1:
  411            length <= 0xffff ? 2:
  412            length <= 0xffffff ? 3: 4);
  413 
  414       *buf++ = (0x80 | i);
  415       if (i > 3)
  416         *buf++ = length >> 24;
  417       if (i > 2)
  418         *buf++ = length >> 16;
  419       if (i > 1)
  420         *buf++ = length >> 8;
  421       *buf++ = length;
  422     }
  423 
  424   return buf - buffer;
  425 }
  426 
  427 
  428 /* Calculate the length of the TL needed to encode a TAG of CLASS.
  429    CONSTRUCTED is a flag telling whether the value is a constructed
  430    one.  LENGTH gives the length of the value; if it is 0 an
  431    indefinite length is assumed.  LENGTH is ignored for the NULL
  432    tag. */
  433 size_t
  434 _ksba_ber_count_tl (unsigned long tag,
  435                     enum tag_class class,
  436                     int constructed,
  437                     unsigned long length)
  438 {
  439   int buflen = 0;
  440 
  441   (void)constructed;  /* Not used, but passed for uniformity of such calls.  */
  442 
  443   /* coverity[identical_branches] */
  444   if (tag < 0x1f)
  445     {
  446       buflen++;
  447     }
  448   else
  449     {
  450       buflen++; /* assume one and let the actual write function bail out */
  451     }
  452 
  453   if (!tag && !class)
  454     buflen++; /* end tag */
  455   else if (tag == TYPE_NULL && !class)
  456     buflen++; /* NULL tag */
  457   else if (!length)
  458     buflen++; /* indefinite length */
  459   else if (length < 128)
  460     buflen++;
  461   else
  462     {
  463       int i;
  464 
  465       /* fixme: if we know the sizeof an ulong we could support larger
  466          objetcs - however this is pretty ridiculous */
  467       i = (length <= 0xff ? 1:
  468            length <= 0xffff ? 2:
  469            length <= 0xffffff ? 3: 4);
  470 
  471       buflen++;
  472       if (i > 3)
  473         buflen++;
  474       if (i > 2)
  475         buflen++;
  476       if (i > 1)
  477         buflen++;
  478       buflen++;
  479     }
  480 
  481   return buflen;
  482 }
  483 
  484 
  485 gpg_error_t
  486 _ksba_parse_sequence (unsigned char const **buf, size_t *len,
  487                       struct tag_info *ti)
  488 {
  489   gpg_error_t err;
  490 
  491   err = _ksba_ber_parse_tl (buf, len, ti);
  492   if (err)
  493     ;
  494   else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_SEQUENCE
  495              && ti->is_constructed) )
  496     err = gpg_error (GPG_ERR_INV_OBJ);
  497   else if (ti->length > *len)
  498     err = gpg_error (GPG_ERR_BAD_BER);
  499   return err;
  500 }
  501 
  502 
  503 /* Note that this function returns GPG_ERR_FALSE if the TLV is valid
  504  * but the tag does not match.  The caller may thus check for this
  505  * error code and compare against other tag values.  */
  506 gpg_error_t
  507 _ksba_parse_context_tag (unsigned char const **buf, size_t *len,
  508                          struct tag_info *ti, int tag)
  509 {
  510   gpg_error_t err;
  511 
  512   err = _ksba_ber_parse_tl (buf, len, ti);
  513   if (err)
  514     ;
  515   else if (!(ti->class == CLASS_CONTEXT && ti->is_constructed))
  516     err = gpg_error (GPG_ERR_INV_OBJ);
  517   else if (ti->length > *len)
  518     err = gpg_error (GPG_ERR_BAD_BER);
  519   else if (ti->tag != tag)
  520     err = gpg_error (GPG_ERR_FALSE);
  521 
  522   return err;
  523 }
  524 
  525 
  526 gpg_error_t
  527 _ksba_parse_enumerated (unsigned char const **buf, size_t *len,
  528                         struct tag_info *ti, size_t maxlen)
  529 {
  530   gpg_error_t err;
  531 
  532   err = _ksba_ber_parse_tl (buf, len, ti);
  533   if (err)
  534      ;
  535   else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_ENUMERATED
  536              && !ti->is_constructed) )
  537     err = gpg_error (GPG_ERR_INV_OBJ);
  538   else if (!ti->length)
  539     err = gpg_error (GPG_ERR_TOO_SHORT);
  540   else if (maxlen && ti->length > maxlen)
  541     err = gpg_error (GPG_ERR_TOO_LARGE);
  542   else if (ti->length > *len)
  543     err = gpg_error (GPG_ERR_BAD_BER);
  544 
  545   return err;
  546 }
  547 
  548 
  549 gpg_error_t
  550 _ksba_parse_integer (unsigned char const **buf, size_t *len,
  551                      struct tag_info *ti)
  552 {
  553   gpg_error_t err;
  554 
  555   err = _ksba_ber_parse_tl (buf, len, ti);
  556   if (err)
  557      ;
  558   else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_INTEGER
  559              && !ti->is_constructed) )
  560     err = gpg_error (GPG_ERR_INV_OBJ);
  561   else if (!ti->length)
  562     err = gpg_error (GPG_ERR_TOO_SHORT);
  563   else if (ti->length > *len)
  564     err = gpg_error (GPG_ERR_BAD_BER);
  565 
  566   return err;
  567 }
  568 
  569 
  570 gpg_error_t
  571 _ksba_parse_octet_string (unsigned char const **buf, size_t *len,
  572                           struct tag_info *ti)
  573 {
  574   gpg_error_t err;
  575 
  576   err= _ksba_ber_parse_tl (buf, len, ti);
  577   if (err)
  578     ;
  579   else if (!(ti->class == CLASS_UNIVERSAL && ti->tag == TYPE_OCTET_STRING
  580              && !ti->is_constructed) )
  581     err = gpg_error (GPG_ERR_INV_OBJ);
  582   else if (!ti->length)
  583     err = gpg_error (GPG_ERR_TOO_SHORT);
  584   else if (ti->length > *len)
  585     err = gpg_error (GPG_ERR_BAD_BER);
  586 
  587   return err;
  588 }
  589 
  590 
  591 /* Note that R_BOOL will only be set if a value has been given. Thus
  592    the caller should set it to the default value prior to calling this
  593    function.  Obviously no call to parse_skip is required after
  594    calling this function. */
  595 gpg_error_t
  596 _ksba_parse_optional_boolean (unsigned char const **buf, size_t *len,
  597                               int *r_bool)
  598 {
  599   gpg_error_t err;
  600   struct tag_info ti;
  601 
  602   err = _ksba_ber_parse_tl (buf, len, &ti);
  603   if (err)
  604     ;
  605   else if (!ti.length)
  606     err = gpg_error (GPG_ERR_TOO_SHORT);
  607   else if (ti.length > *len)
  608     err = gpg_error (GPG_ERR_BAD_BER);
  609   else if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_BOOLEAN
  610            && !ti.is_constructed)
  611     {
  612       if (ti.length != 1)
  613         err = gpg_error (GPG_ERR_BAD_BER);
  614       *r_bool = !!**buf;
  615       parse_skip (buf, len, &ti);
  616     }
  617   else
  618     { /* Undo the read. */
  619       *buf -= ti.nhdr;
  620       *len += ti.nhdr;
  621     }
  622 
  623   return err;
  624 }
  625 
  626 
  627 /* Parse an optional Null tag.  Ir R_SEEN is not NULL it is set to
  628  * true if a NULL tag was encountered.  */
  629 gpg_error_t
  630 _ksba_parse_optional_null (unsigned char const **buf, size_t *len,
  631                            int *r_seen)
  632 {
  633   gpg_error_t err;
  634   struct tag_info ti;
  635 
  636   if (r_seen)
  637     *r_seen = 0;
  638   err = _ksba_ber_parse_tl (buf, len, &ti);
  639   if (err)
  640     ;
  641   else if (ti.length > *len)
  642     err = gpg_error (GPG_ERR_BAD_BER);
  643   else if (ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_NULL
  644            && !ti.is_constructed)
  645     {
  646       if (ti.length)
  647         err = gpg_error (GPG_ERR_BAD_BER);
  648       if (r_seen)
  649         *r_seen = 1;
  650       parse_skip (buf, len, &ti);
  651     }
  652   else
  653     { /* Undo the read. */
  654       *buf -= ti.nhdr;
  655       *len += ti.nhdr;
  656     }
  657 
  658   return err;
  659 }
  660 
  661 
  662 
  663 gpg_error_t
  664 _ksba_parse_object_id_into_str (unsigned char const **buf, size_t *len,
  665                                 char **oid)
  666 {
  667   struct tag_info ti;
  668   gpg_error_t err;
  669 
  670   *oid = NULL;
  671   err = _ksba_ber_parse_tl (buf, len, &ti);
  672   if (err)
  673     ;
  674   else if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OBJECT_ID
  675                 && !ti.is_constructed) )
  676     err = gpg_error (GPG_ERR_INV_OBJ);
  677   else if (!ti.length)
  678     err = gpg_error (GPG_ERR_TOO_SHORT);
  679   else if (ti.length > *len)
  680     err = gpg_error (GPG_ERR_BAD_BER);
  681   else if (!(*oid = ksba_oid_to_str (*buf, ti.length)))
  682     err = gpg_error_from_syserror ();
  683   else
  684     {
  685       *buf += ti.length;
  686       *len -= ti.length;
  687     }
  688   return err;
  689 }
  690 
  691 
  692 gpg_error_t
  693 _ksba_parse_asntime_into_isotime (unsigned char const **buf, size_t *len,
  694                                   ksba_isotime_t isotime)
  695 {
  696   struct tag_info ti;
  697   gpg_error_t err;
  698 
  699   err = _ksba_ber_parse_tl (buf, len, &ti);
  700   if (err)
  701     ;
  702   else if ( !(ti.class == CLASS_UNIVERSAL
  703               && (ti.tag == TYPE_UTC_TIME || ti.tag == TYPE_GENERALIZED_TIME)
  704               && !ti.is_constructed) )
  705     err = gpg_error (GPG_ERR_INV_OBJ);
  706   else if (ti.length > *len)
  707     err = gpg_error (GPG_ERR_INV_BER);
  708   else if (!(err = _ksba_asntime_to_iso (*buf, ti.length,
  709                                          ti.tag == TYPE_UTC_TIME, isotime)))
  710     parse_skip (buf, len, &ti);
  711 
  712   return err;
  713 }