diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-06-30 16:40:38 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-06-30 16:40:38 +0000 |
commit | e9d15cbea7a98184521c851500176da7aa424012 (patch) | |
tree | d3d6aa7ea86d11ecaa6e88efbc46a5dde1c63ea5 /addons/ooh323c/src/decode.c | |
parent | b85bdd32a783a8f07004d41db8a696645685a331 (diff) |
Move Asterisk-addons modules into the main Asterisk source tree.
Someone asked yesterday, "is there a good reason why we can't just put these
modules in Asterisk?". After a brief discussion, as long as the modules are
clearly set aside in their own directory and not enabled by default, it is
perfectly fine.
For more information about why a module goes in addons, see README-addons.txt.
chan_ooh323 does not currently compile as it is behind some trunk API updates.
However, it will not build by default, so it should be okay for now.
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@204413 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'addons/ooh323c/src/decode.c')
-rw-r--r-- | addons/ooh323c/src/decode.c | 1050 |
1 files changed, 1050 insertions, 0 deletions
diff --git a/addons/ooh323c/src/decode.c b/addons/ooh323c/src/decode.c new file mode 100644 index 000000000..d09247c94 --- /dev/null +++ b/addons/ooh323c/src/decode.c @@ -0,0 +1,1050 @@ +/* + * 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); + } + else + pOctStr->data = 0; + + return stat; + } + } + + nocts = getComponentLength (pctxt, 8); + + if (nocts < 0) return LOG_ASN1ERR (pctxt, nocts); + else if (nocts == 0) { + pOctStr->numocts = 0; + ptmp = 0; + } + + /* Allocate memory for the target string */ + + else { + ptmp = (ASN1OCTET*) ASN1MALLOC (pctxt, nocts); + if (0 == ptmp) return LOG_ASN1ERR (pctxt, ASN_E_NOMEM); + } + + /* Call static octet string decode function */ + + stat = decodeOctetString (pctxt, &pOctStr->numocts, ptmp, nocts); + + pOctStr->data = ptmp; + + return stat; +} + +int decodeLength (OOCTXT* pctxt, ASN1UINT* pvalue) +{ + Asn1SizeCnst* pSize; + ASN1UINT lower, upper; + ASN1BOOL bitValue, extbit; + int stat; + + /* If size constraint is present and extendable, decode extension */ + /* bit.. */ + + if (isExtendableSize(pctxt->pSizeConstraint)) { + stat = DECODEBIT (pctxt, &extbit); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + } + else extbit = 0; + + /* Now use the value of the extension bit to select the proper */ + /* size constraint range specification.. */ + + pSize = getSizeConstraint (pctxt, extbit); + + lower = (pSize) ? pSize->lower : 0; + upper = (pSize) ? pSize->upper : ASN1UINT_MAX; + + /* Reset the size constraint in the context block structure */ + + pctxt->pSizeConstraint = 0; + + /* If upper limit is less than 64k, constrained case */ + + if (upper < 65536) { + if (lower == upper) { + *pvalue = 0; + stat = ASN_OK; + } + else + stat = decodeConsWholeNumber (pctxt, pvalue, (upper - lower + 1)); + + if (stat == ASN_OK) *pvalue += lower; + } + else { + /* unconstrained case OR constrained with upper bound >= 64K*/ + + stat = decodeByteAlign (pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + stat = DECODEBIT (pctxt, &bitValue); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + if (bitValue == 0) { + stat = decodeBits (pctxt, pvalue, 7); /* 10.9.3.6 */ + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + } + else { + stat = DECODEBIT (pctxt, &bitValue); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + if (bitValue == 0) { + stat = decodeBits (pctxt, pvalue, 14); /* 10.9.3.7 */ + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + } + else { + ASN1UINT multiplier; + + stat = decodeBits (pctxt, &multiplier, 6); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + *pvalue = 16384 * multiplier; + + stat = ASN_OK_FRAG; + } + } + } + + return stat; +} + +int decodeObjectIdentifier (OOCTXT* pctxt, ASN1OBJID* pvalue) +{ + ASN1UINT len; + int stat, j; + unsigned subid; + ASN1UINT b; + + /* Decode unconstrained length */ + + if ((stat = decodeLength (pctxt, &len)) < 0) { + return LOG_ASN1ERR (pctxt, stat); + } + + /* Copy contents to a byte-aligned local buffer */ + + j = 0; + while (len > 0 && stat == ASN_OK) { + if (j < ASN_K_MAXSUBIDS) { + + /* Parse a subidentifier out of the contents field */ + + pvalue->subid[j] = 0; + do { + if ((stat = decodeBits (pctxt, &b, 8)) == ASN_OK) { + pvalue->subid[j] = (pvalue->subid[j] * 128) + (b & 0x7F); + len--; + } + } while (b & 0x80 && stat == ASN_OK); + + /* Handle the first subidentifier special case: the first two */ + /* sub-id's are encoded into one using the formula (x * 40) + y */ + + if (j == 0) { + subid = pvalue->subid[0]; + pvalue->subid[0] = ((subid / 40) >= 2) ? 2 : subid / 40; + pvalue->subid[1] = (pvalue->subid[0] == 2) ? + subid - 80 : subid % 40; + j = 2; + } + else j++; + } + else + stat = ASN_E_INVOBJID; + } + + pvalue->numids = j; + if (stat == ASN_OK && len != 0) stat = ASN_E_INVLEN; + + return (stat); +} + +static int decodeOctets +(OOCTXT* pctxt, ASN1OCTET* pbuffer, ASN1UINT bufsiz, ASN1UINT nbits) +{ + ASN1UINT nbytes = (nbits + 7) / 8 ; + ASN1UINT i = 0, j; + ASN1UINT rshift = pctxt->buffer.bitOffset; + ASN1UINT lshift = 8 - rshift; + ASN1UINT nbitsInLastOctet; + ASN1OCTET mask; + int stat; + + /* Check to make sure buffer contains number of bits requested */ + + if ((pctxt->buffer.byteIndex + nbytes) > pctxt->buffer.size) { + return LOG_ASN1ERR (pctxt, ASN_E_ENDOFBUF); + } + + /* Check to make sure buffer is big enough to hold requested */ + /* number of bits.. */ + + if (nbytes > bufsiz) { + return LOG_ASN1ERR (pctxt, ASN_E_STROVFLW); + } + + /* If on a byte boundary, can do a direct memcpy to target buffer */ + + if (pctxt->buffer.bitOffset == 8) { + memcpy (pbuffer, &pctxt->buffer.data[pctxt->buffer.byteIndex], nbytes); + stat = moveBitCursor (pctxt, nbits); + if (stat != ASN_OK) return stat; + i = nbytes - 1; nbits %= 8; + } + else { + while (nbits >= 8) { + + /* Transfer lower bits from stream octet to upper bits of */ + /* target octet.. */ + + pbuffer[i] = pctxt->buffer.data[pctxt->buffer.byteIndex++] + << lshift; + + /* Transfer upper bits from next stream octet to lower bits */ + /* target octet.. */ + + pbuffer[i++] |= pctxt->buffer.data[pctxt->buffer.byteIndex] + >> rshift; + + nbits -= 8; + } + + /* Copy last partial byte */ + + if (nbits >= rshift) { + pbuffer[i] = + pctxt->buffer.data[pctxt->buffer.byteIndex++] << lshift; + + nbitsInLastOctet = nbits - rshift; + + if (nbitsInLastOctet > 0) { + pbuffer[i] |= + pctxt->buffer.data[pctxt->buffer.byteIndex] >> rshift; + } + + pctxt->buffer.bitOffset = 8 - nbitsInLastOctet; + } + else if (nbits > 0) { /* nbits < rshift */ + pbuffer[i] = + pctxt->buffer.data[pctxt->buffer.byteIndex] << lshift; + pctxt->buffer.bitOffset = rshift - nbits; + } + } + + /* Mask unused bits off of last byte */ + + if (nbits > 0) { + mask = 0; + for (j = 0; j < nbits; j++) { + mask >>= 1; + mask |= 0x80; + } + pbuffer[i] &= mask; + } + + return ASN_OK; +} + +int decodeOctetString +(OOCTXT* pctxt, ASN1UINT* numocts_p, ASN1OCTET* buffer, ASN1UINT bufsiz) +{ + ASN1UINT octcnt; + int lstat, octidx = 0, stat; + Asn1SizeCnst* pSizeList = pctxt->pSizeConstraint; + + for (*numocts_p = 0;;) { + lstat = decodeLength (pctxt, &octcnt); + if (lstat < 0) return LOG_ASN1ERR (pctxt, lstat); + + if (octcnt > 0) { + *numocts_p += octcnt; + + if (TRUE) { + ASN1BOOL doAlign; + + stat = bitAndOctetStringAlignmentTest + (pSizeList, octcnt, FALSE, &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, (octcnt * 8)); + + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + } + + if (lstat == ASN_OK_FRAG) { + octidx += octcnt; + } + else break; + } + + return ASN_OK; +} + +int decodeOpenType +(OOCTXT* pctxt, const ASN1OCTET** object_p2, ASN1UINT* numocts_p) +{ + ASN1DynOctStr octStr; + int stat; + + stat = decodeDynOctetString (pctxt, &octStr); + if (stat == ASN_OK) { + *numocts_p = octStr.numocts; + *object_p2 = octStr.data; + } + + return stat; +} + +int decodeSemiConsInteger (OOCTXT* pctxt, ASN1INT* pvalue, ASN1INT lower) +{ + signed char b; + unsigned char ub; + ASN1UINT nbytes; + int stat; + + stat = decodeLength (pctxt, &nbytes); + if (stat < 0) return LOG_ASN1ERR (pctxt, stat); + + if (nbytes > 0) { + + /* Align buffer */ + + stat = decodeByteAlign (pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + /* Decode first byte into a signed byte value and assign to integer. */ + /* This should handle sign extension.. */ + + stat = decodeOctets (pctxt, (ASN1OCTET*)&b, 1, 8); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + *pvalue = b; + nbytes--; + + /* Decode remaining bytes and add to result */ + + while (nbytes > 0) { + stat = decodeOctets (pctxt, (ASN1OCTET*)&ub, 1, 8); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + *pvalue = (*pvalue * 256) + ub; + nbytes--; + } + } + else { /* nbytes == 0 */ + *pvalue = 0; + } + if (lower > ASN1INT_MIN) + *pvalue += lower; + + return ASN_OK; +} + +int decodeSemiConsUnsigned (OOCTXT* pctxt, ASN1UINT* pvalue, ASN1UINT lower) +{ + ASN1UINT nbytes; + int stat; + + stat = decodeLength (pctxt, &nbytes); + if (stat < 0) return LOG_ASN1ERR (pctxt, stat); + + + if (nbytes > 0) { + stat = decodeByteAlign (pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + stat = decodeBits (pctxt, pvalue, nbytes * 8); + } + else + *pvalue = 0; + *pvalue += lower; + + return stat; +} + +int decodeSmallNonNegWholeNumber (OOCTXT* pctxt, ASN1UINT* pvalue) +{ + ASN1BOOL bitValue; + ASN1UINT len; + int ret; + + if ((ret = DECODEBIT (pctxt, &bitValue)) != ASN_OK) + return ret; + + if (bitValue == 0) { + return decodeBits (pctxt, pvalue, 6); /* 10.6.1 */ + } + else { + if ((ret = decodeLength (pctxt, &len)) < 0) + return ret; + + if ((ret = decodeByteAlign (pctxt)) != ASN_OK) + return ret; + + return decodeBits (pctxt, pvalue, len*8); + } +} + +int decodeVarWidthCharString (OOCTXT* pctxt, const char** pvalue) +{ + int stat; + ASN1OCTET* tmpstr; + ASN1UINT len; + + /* 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, 8, psize)) { + stat = decodeByteAlign (pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + } + + /* Decode data */ + + tmpstr = (ASN1OCTET*) ASN1MALLOC (pctxt, len + 1); + if (0 != tmpstr) { + if ((stat = decodeOctets (pctxt, tmpstr, len, len * 8)) != ASN_OK) + return LOG_ASN1ERR (pctxt, stat); + + tmpstr[len] = '\0'; /* add null-terminator */ + } + else + return LOG_ASN1ERR (pctxt, ASN_E_NOMEM); + + *pvalue = (char*)tmpstr; + + return ASN_OK; +} + +static int decode16BitConstrainedString +(OOCTXT* pctxt, Asn116BitCharString* pString, Asn116BitCharSet* pCharSet) +{ + ASN1UINT i, idx, nbits = pCharSet->alignedBits; + int stat; + + /* Decode length */ + + stat = decodeLength (pctxt, &pString->nchars); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + /* Byte-align */ + + stat = decodeByteAlign (pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + /* Decode data */ + + pString->data = (ASN116BITCHAR*) + ASN1MALLOC (pctxt, pString->nchars*sizeof(ASN116BITCHAR)); + + if (pString->data) { + for (i = 0; i < pString->nchars; i++) { + stat = decodeBits (pctxt, &idx, nbits); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + pString->data[i] = (pCharSet->charSet.data == 0) ? + idx + pCharSet->firstChar : pCharSet->charSet.data[idx]; + } + } + else + return LOG_ASN1ERR (pctxt, ASN_E_NOMEM); + + return ASN_OK; +} + +static int getComponentLength (OOCTXT* pctxt, ASN1UINT itemBits) +{ + OOCTXT lctxt; + ASN1UINT len, totalLen = 0; + int stat; + + stat = initSubContext (&lctxt, pctxt); + if (stat != ASN_OK) return LOG_ASN1ERR (pctxt, stat); + + stat = setPERBufferUsingCtxt (&lctxt, pctxt); + if (stat != ASN_OK) { + freeContext (&lctxt); + return LOG_ASN1ERR (pctxt, stat); + } + lctxt.pSizeConstraint = pctxt->pSizeConstraint; + + for (;;) { + stat = decodeLength (&lctxt, &len); + if (stat < 0) { + freeContext (&lctxt); + return LOG_ASN1ERR (pctxt, stat); + } + + totalLen += len; + + if (stat == ASN_OK_FRAG) { + stat = moveBitCursor (&lctxt, len * itemBits); + if (stat != ASN_OK) { + freeContext (&lctxt); + return LOG_ASN1ERR (pctxt, stat); + } + } + else break; + } + + freeContext (&lctxt); + + return totalLen; +} + +int moveBitCursor (OOCTXT* pctxt, int bitOffset) +{ + int currBitOffset = + (pctxt->buffer.byteIndex * 8) + (8 - pctxt->buffer.bitOffset); + + currBitOffset += bitOffset; + + pctxt->buffer.byteIndex = (currBitOffset / 8); + pctxt->buffer.bitOffset = 8 - (currBitOffset % 8); + + if (pctxt->buffer.byteIndex > pctxt->buffer.size) { + return (ASN_E_ENDOFBUF); + } + + return ASN_OK; +} |