decode.c

来自「一个非常美妙的proxy。功能强大。基于sip的协议。如果还要的话」· C语言 代码 · 共 1,051 行 · 第 1/2 页

C
1,051
字号
/* * Copyright (C) 1997-2005 by Objective Systems, Inc. * * This software is furnished under an open source license and may be  * used and copied only in accordance with the terms of this license.  * The text of the license may generally be found in the root  * directory of this installation in the COPYING file.  It  * can also be viewed online at the following URL: * *   http://www.obj-sys.com/open/license.html * * Any redistributions of this file including modified versions must  * maintain this copyright notice. * *****************************************************************************/#include "ooasn1.h"static int decode16BitConstrainedString (OOCTXT* pctxt, Asn116BitCharString* pString, Asn116BitCharSet* pCharSet);static int decodeOctets (OOCTXT* pctxt, ASN1OCTET* pbuffer, ASN1UINT bufsiz, ASN1UINT nbits);static int getComponentLength (OOCTXT* pctxt, ASN1UINT itemBits);int decodeBits (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT nbits){    unsigned char mask;   if (nbits == 0) {      *pvalue = 0;      return ASN_OK;   }   /* If the number of bits is less than the current bit offset, mask   */   /* off the required number of bits and return..                      */   if (nbits < (unsigned)pctxt->buffer.bitOffset) {      /* Check if buffer contains number of bits requested */      if (pctxt->buffer.byteIndex >= pctxt->buffer.size)         return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF);      pctxt->buffer.bitOffset -= nbits;      *pvalue = ((pctxt->buffer.data[pctxt->buffer.byteIndex]) >>                  pctxt->buffer.bitOffset) & ((1 << nbits) - 1);      return ASN_OK;   }   /* Otherwise, we first need to mask off the remaining bits in the    */   /* current byte, followed by a loop to extract bits from full bytes, */   /* followed by logic to mask of remaining bits from the start of     */   /* of the last byte..                                                */   else {      /* Check if buffer contains number of bits requested */      int nbytes = (((nbits - pctxt->buffer.bitOffset) + 7) / 8);            if ((pctxt->buffer.byteIndex + nbytes) >= pctxt->buffer.size) {         return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF);      }      /* first read current byte remaining bits */      mask = ((1 << pctxt->buffer.bitOffset) - 1);      *pvalue = (pctxt->buffer.data[pctxt->buffer.byteIndex]) & mask;      nbits -= pctxt->buffer.bitOffset;      pctxt->buffer.bitOffset = 8;      pctxt->buffer.byteIndex++;      /* second read bytes from next byteIndex */      while (nbits >= 8) {         *pvalue = (*pvalue << 8) |             (pctxt->buffer.data[pctxt->buffer.byteIndex]);         pctxt->buffer.byteIndex++;         nbits -= 8;      }      /* third read bits & set bitoffset of the byteIndex */      if (nbits > 0) {         pctxt->buffer.bitOffset = 8 - nbits;         *pvalue = (*pvalue << nbits) |             ((pctxt->buffer.data[pctxt->buffer.byteIndex]) >>              pctxt->buffer.bitOffset);      }      return ASN_OK;   }}int decodeBitString (OOCTXT* pctxt, ASN1UINT* numbits_p, ASN1OCTET* buffer, ASN1UINT bufsiz){   ASN1UINT bitcnt;   int lstat, octidx = 0, stat;   Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint;   ASN1BOOL doAlign;   for (*numbits_p = 0;;) {      lstat = decodeLength (pctxt, &bitcnt);      if (lstat < 0) return LOG_ASN1ERR (pctxt, lstat);      if (bitcnt > 0) {         *numbits_p += bitcnt;         stat = bitAndOctetStringAlignmentTest             (pSizeList, bitcnt, TRUE, &doAlign);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         if (doAlign) {            stat = decodeByteAlign (pctxt);            if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         }         stat = decodeOctets (pctxt, &buffer[octidx], bufsiz - octidx, bitcnt);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      }      if (lstat == ASN_OK_FRAG) {         octidx += (bitcnt / 8);      }      else break;   }   return ASN_OK;}int decodeBMPString (OOCTXT* pctxt, ASN1BMPString* pvalue, Asn116BitCharSet* permCharSet){   Asn116BitCharSet charSet;   int stat;   /* Set character set */   init16BitCharSet (&charSet, BMP_FIRST, BMP_LAST, BMP_ABITS, BMP_UBITS);   if (permCharSet) {      set16BitCharSet (pctxt, &charSet, permCharSet);   }   /* Decode constrained string */   stat = decode16BitConstrainedString (pctxt, pvalue, &charSet);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   return (stat);}int decodeByteAlign (OOCTXT* pctxt){   if (pctxt->buffer.bitOffset != 8) {      pctxt->buffer.byteIndex++;      pctxt->buffer.bitOffset = 8;   }   return ASN_OK;}int decodeConstrainedStringEx (OOCTXT* pctxt, const char** string, const char* charSet, ASN1UINT abits, ASN1UINT ubits, ASN1UINT canSetBits){   int   stat;   char* tmpstr;   ASN1UINT i, idx, len, nbits = abits;   /* note: need to save size constraint for use in alignCharStr     */   /* because it will be cleared in decodeLength from the context..        */   Asn1SizeCnst* psize = pctxt->pSizeConstraint;   /* Decode length */   stat = decodeLength (pctxt, &len);   if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   /* Byte-align */   if (alignCharStr (pctxt, len, nbits, psize)) {      stat = decodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);   }   /* Decode data */   tmpstr = (char*) ASN1MALLOC (pctxt, len+1);   if (0 != tmpstr) {      if (nbits >= canSetBits && canSetBits > 4) {         for (i = 0; i < len; i++) {            if ((stat = decodeBits (pctxt, &idx, nbits)) == ASN_OK) {               tmpstr[i] = (char) idx;            }            else break;         }      }      else if (0 != charSet) {         ASN1UINT nchars = strlen (charSet);         for (i = 0; i < len; i++) {            if ((stat = decodeBits (pctxt, &idx, nbits)) == ASN_OK) {               if (idx < nchars) {                  tmpstr[i] = charSet[idx];               }               else return LOG_ASN1ERR (pctxt, ASN_E_CONSVIO);            }            else break;         }      }      else stat = ASN_E_INVPARAM;      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      tmpstr[i] = '\0';  /* add null-terminator */   }   else      return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);   *string = tmpstr;   return ASN_OK;}int decodeConsInteger (OOCTXT* pctxt, ASN1INT* pvalue, ASN1INT lower, ASN1INT upper){    ASN1UINT range_value = upper - lower;   ASN1UINT adjusted_value;   int stat = ASN_OK;   if (range_value != ASN1UINT_MAX) { range_value += 1; }   if (lower > upper)      return ASN_E_RANGERR;   else if (lower != upper) {      stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);      if (stat == ASN_OK) {         *pvalue = adjusted_value + lower;         if (*pvalue < lower || *pvalue > upper)            stat = ASN_E_CONSVIO;      }   }   else {      *pvalue = lower;   }   return stat;}int decodeConsUInt8 (OOCTXT* pctxt, ASN1UINT8* pvalue, ASN1UINT lower, ASN1UINT upper){    ASN1UINT range_value, value;   ASN1UINT adjusted_value;   int stat = ASN_OK;   /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */   /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */   range_value = (lower == 0 && upper == ASN1UINT_MAX) ?      ASN1UINT_MAX : upper - lower + 1;   if (lower != upper) {      ASN1UINT range_bitcnt;      /* If range is <= 255, bit-field case (10.5.7a) */      if (range_value <= 255) {         range_bitcnt = getUIntBitCount (range_value - 1);      }      /* If range is exactly 256, one-octet case (10.5.7b) */      else if (range_value == 256) {         stat = decodeByteAlign (pctxt);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         range_bitcnt = 8;      }      stat = decodeBits (pctxt, &adjusted_value, range_bitcnt);      if (stat == ASN_OK) {         value = adjusted_value + lower;         if (value < lower || value > upper)            stat = ASN_E_CONSVIO;         *pvalue = (ASN1OCTET)value;      }   }   else *pvalue = (ASN1OCTET)lower;   return stat;}int decodeConsUInt16 (OOCTXT* pctxt, ASN1USINT* pvalue, ASN1UINT lower, ASN1UINT upper){    ASN1UINT range_value, value;   ASN1UINT adjusted_value;   int stat = ASN_OK;   /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */   /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */   range_value = (lower == 0 && upper == ASN1UINT_MAX) ?      ASN1UINT_MAX : upper - lower + 1;   if (lower != upper) {      stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);      if (stat == ASN_OK) {         value = adjusted_value + lower;         /* Verify value is within given range (ED, 1/15/2002) */         if (value < lower || value > upper)            stat = ASN_E_CONSVIO;         *pvalue = (ASN1USINT) value;      }   }   else *pvalue = (ASN1USINT) lower;   return stat;}int decodeConsUnsigned (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT lower, ASN1UINT upper){    ASN1UINT range_value;   ASN1UINT adjusted_value;   int stat = ASN_OK;   /* Check for special case: if lower is 0 and upper is ASN1UINT_MAX,  */   /* set range to ASN1UINT_MAX; otherwise to upper - lower + 1         */   range_value = (lower == 0 && upper == ASN1UINT_MAX) ?      ASN1UINT_MAX : upper - lower + 1;   if (lower != upper) {      stat = decodeConsWholeNumber (pctxt, &adjusted_value, range_value);      if (stat == ASN_OK) {         *pvalue = adjusted_value + lower;         if (*pvalue < lower || *pvalue > upper)            stat = ASN_E_CONSVIO;      }   }   else *pvalue = lower;   return stat;}int decodeConsWholeNumber (OOCTXT* pctxt, ASN1UINT* padjusted_value, ASN1UINT range_value){    ASN1UINT nocts, range_bitcnt;   int stat;   /* If unaligned, decode non-negative binary integer in the minimum   */   /* number of bits necessary to represent the range (10.5.6)          */   if (!TRUE) {      range_bitcnt = getUIntBitCount (range_value - 1);   }   /* If aligned, encoding depended on range value (10.5.7) */   else {  /* aligned */      /* If range is <= 255, bit-field case (10.5.7a) */      if (range_value <= 255) {         range_bitcnt = getUIntBitCount (range_value - 1);      }      /* If range is exactly 256, one-octet case (10.5.7b) */      else if (range_value == 256) {         stat = decodeByteAlign (pctxt);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         range_bitcnt = 8;      }      /* If range > 256 and <= 64k (65535), two-octet case (10.5.7c) */      else if (range_value <= 65536) {         stat = decodeByteAlign (pctxt);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         range_bitcnt = 16;      }      /* If range > 64k, indefinite-length case (10.5.7d) */      else {         stat = decodeBits (pctxt, &nocts, 2);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         stat = decodeByteAlign (pctxt);         if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         range_bitcnt = (nocts + 1) * 8;      }   }   return decodeBits (pctxt, padjusted_value, range_bitcnt);}int decodeDynBitString (OOCTXT* pctxt, ASN1DynBitStr* pBitStr){   ASN1UINT nocts;   ASN1OCTET* ptmp;   int nbits, stat = ASN_OK;   /* If "fast copy" option is not set (ASN1FATSCOPY) or if constructed,    * copy the bit string value into a dynamic memory buffer;    * otherwise, store the pointer to the value in the decode     * buffer in the data pointer argument. */      if (pctxt->flags & ASN1FASTCOPY) {      /* check is it possible to do optimized decoding */      ASN1OCTET bit;      ASN1UINT byteIndex = pctxt->buffer.byteIndex;  /* save byte index */      ASN1USINT bitOffset = pctxt->buffer.bitOffset; /* save bit offset */      stat = decodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      stat = DECODEBIT (pctxt, &bit); /* read first bit of length determinant */      if (bit == 1 && stat == ASN_OK)          stat = DECODEBIT (pctxt, &bit); /* read second bit */      pctxt->buffer.byteIndex = byteIndex;  /* restore byte index */      pctxt->buffer.bitOffset = bitOffset;  /* restore bit offset */      /* if either first or second bit != 0 - not fragmented */      if (bit == 0 && stat == ASN_OK) {          ASN1UINT bitcnt;                  stat = decodeLength (pctxt, &bitcnt);         if (stat != 0) return LOG_ASN1ERR (pctxt, stat);         pBitStr->numbits = bitcnt;         if (bitcnt > 0) {            pBitStr->data = ASN1BUFPTR (pctxt);            stat = moveBitCursor (pctxt, bitcnt);            if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);         }         else             pBitStr->data = 0;            return stat;      }   }   nbits = getComponentLength (pctxt, 1);   if (nbits < 0) return LOG_ASN1ERR (pctxt, nbits);   else if (nbits == 0) {      pBitStr->numbits = 0;      ptmp = 0;   }   nocts = (nbits + 7) / 8;         /* Allocate memory for the target string */   if (nocts > 0) {      ptmp = (ASN1OCTET*) ASN1MALLOC (pctxt, nocts);      if (0 == ptmp) return LOG_ASN1ERR (pctxt, ASN_E_NOMEM);            /* Call static bit string decode function */      stat = decodeBitString (pctxt, &pBitStr->numbits, ptmp, nocts);   }   pBitStr->data = ptmp;   return stat;}int decodeDynOctetString (OOCTXT* pctxt, ASN1DynOctStr* pOctStr){   ASN1OCTET* ptmp;   int nocts, stat;   /* If "fast copy" option is not set (ASN1FASTCOPY) or if constructed,    * copy the octet string value into a dynamic memory buffer;    * otherwise, store the pointer to the value in the decode     * buffer in the data pointer argument. */   if (pctxt->flags & ASN1FASTCOPY) {      /* check if it is possible to do optimized decoding */      ASN1OCTET bit;      ASN1UINT byteIndex = pctxt->buffer.byteIndex;  /* save byte index */      ASN1USINT bitOffset = pctxt->buffer.bitOffset; /* save bit offset */      stat = decodeByteAlign (pctxt);      if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);      stat = DECODEBIT (pctxt, &bit); /* read first bit of length determinant */      if (bit == 1 && stat == ASN_OK)          stat = DECODEBIT (pctxt, &bit); /* read second bit */      pctxt->buffer.byteIndex = byteIndex;  /* restore byte index */      pctxt->buffer.bitOffset = bitOffset;  /* restore bit offset */      /* if either first or second bit != 0 - not fragmented */      if (bit == 0 && stat == ASN_OK) {          ASN1UINT octcnt;                  stat = decodeLength (pctxt, &octcnt);         if (stat != 0) return LOG_ASN1ERR (pctxt, stat);         pOctStr->numocts = octcnt;         if (octcnt > 0) {            pOctStr->data = ASN1BUFPTR (pctxt);            stat = moveBitCursor (pctxt, octcnt * 8);            if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?