Blame src/parsetlv.c

Packit Service 672cf4
/* parsetlv.c -  ASN.1 TLV functions
Packit Service 672cf4
 * Copyright (C) 2005, 2007, 2008, 2012 g10 Code GmbH
Packit Service 672cf4
 *
Packit Service 672cf4
 * This file is free software; you can redistribute it and/or modify
Packit Service 672cf4
 * it under the terms of the GNU Lesser General Public License as
Packit Service 672cf4
 * published by the Free Software Foundation; either version 2.1 of
Packit Service 672cf4
 * the License, or (at your option) any later version.
Packit Service 672cf4
 *
Packit Service 672cf4
 * This file is distributed in the hope that it will be useful,
Packit Service 672cf4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 672cf4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 672cf4
 * GNU Lesser General Public License for more details.
Packit Service 672cf4
 *
Packit Service 6c01f9
 * You should have received a copy of the GNU Lesser General Public License
Packit Service 6c01f9
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
Packit Service 672cf4
 */
Packit Service 672cf4
Packit Service 672cf4
#ifdef HAVE_CONFIG_H
Packit Service 672cf4
# include <config.h>
Packit Service 672cf4
#endif
Packit Service 672cf4
#include <stdio.h>
Packit Service 672cf4
#include <stdlib.h>
Packit Service 672cf4
#include <string.h>
Packit Service 672cf4
Packit Service 672cf4
#include "parsetlv.h"
Packit Service 672cf4
Packit Service 672cf4
Packit Service 672cf4
/* Simple but pretty complete ASN.1 BER parser.  Parse the data at the
Packit Service 672cf4
   address of BUFFER with a length given at the address of SIZE.  On
Packit Service 672cf4
   success return 0 and update BUFFER and SIZE to point to the value.
Packit Service 672cf4
   Do not update them on error.  The information about the object are
Packit Service 672cf4
   stored in the caller allocated TI structure.  */
Packit Service 672cf4
int
Packit Service 672cf4
_gpgme_parse_tlv (char const **buffer, size_t *size, tlvinfo_t *ti)
Packit Service 672cf4
{
Packit Service 672cf4
  int c;
Packit Service 672cf4
  unsigned long tag;
Packit Service 672cf4
  const unsigned char *buf = (const unsigned char *)(*buffer);
Packit Service 672cf4
  size_t length = *size;
Packit Service 672cf4
Packit Service 672cf4
  ti->cls = 0;
Packit Service 672cf4
  ti->tag = 0;
Packit Service 672cf4
  ti->is_cons = 0;
Packit Service 672cf4
  ti->is_ndef = 0;
Packit Service 672cf4
  ti->length = 0;
Packit Service 672cf4
  ti->nhdr = 0;
Packit Service 672cf4
Packit Service 672cf4
  if (!length)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
  c = *buf++; length--; ++ti->nhdr;
Packit Service 672cf4
Packit Service 672cf4
  ti->cls = (c & 0xc0) >> 6;
Packit Service 672cf4
  ti->is_cons = !!(c & 0x20);
Packit Service 672cf4
  tag = c & 0x1f;
Packit Service 672cf4
Packit Service 672cf4
  if (tag == 0x1f)
Packit Service 672cf4
    {
Packit Service 672cf4
      tag = 0;
Packit Service 672cf4
      do
Packit Service 672cf4
        {
Packit Service 672cf4
          tag <<= 7;
Packit Service 672cf4
          if (!length)
Packit Service 672cf4
            return -1;
Packit Service 672cf4
          c = *buf++; length--; ++ti->nhdr;
Packit Service 672cf4
          tag |= c & 0x7f;
Packit Service 672cf4
        }
Packit Service 672cf4
      while (c & 0x80);
Packit Service 672cf4
    }
Packit Service 672cf4
  ti->tag = tag;
Packit Service 672cf4
Packit Service 672cf4
  if (!length)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
  c = *buf++; length--; ++ti->nhdr;
Packit Service 672cf4
Packit Service 672cf4
  if ( !(c & 0x80) )
Packit Service 672cf4
    ti->length = c;
Packit Service 672cf4
  else if (c == 0x80)
Packit Service 672cf4
    ti->is_ndef = 1;
Packit Service 672cf4
  else if (c == 0xff)
Packit Service 672cf4
    return -1;
Packit Service 672cf4
  else
Packit Service 672cf4
    {
Packit Service 672cf4
      unsigned long len = 0;
Packit Service 672cf4
      int count = (c & 0x7f);
Packit Service 672cf4
Packit Service 672cf4
      if (count > sizeof (len) || count > sizeof (size_t))
Packit Service 672cf4
        return -1;
Packit Service 672cf4
Packit Service 672cf4
      for (; count; count--)
Packit Service 672cf4
        {
Packit Service 672cf4
          len <<= 8;
Packit Service 672cf4
          if (!length)
Packit Service 672cf4
            return -1;
Packit Service 672cf4
          c = *buf++; length--; ++ti->nhdr;
Packit Service 672cf4
          len |= c & 0xff;
Packit Service 672cf4
        }
Packit Service 672cf4
      ti->length = len;
Packit Service 672cf4
    }
Packit Service 672cf4
Packit Service 672cf4
  *buffer = (void*)buf;
Packit Service 672cf4
  *size = length;
Packit Service 672cf4
  return 0;
Packit Service 672cf4
}