Files
asterisk/addons/ooh323c/src/decode.c
Josh Soref 01697d4836 addons: Spelling fixes
Correct typos of the following word families:

definition
listener
fastcopy
logical
registration
classify
documentation
explicitly
dialed
endpoint
elements
arithmetic
might
prepend
byte
terminal
inquiry
skipping
aliases
calling
absent
authentication
transmit
their
ericsson
disconnecting
redir
items
client
adapter
transmitter
existing
satisfies
pointer
interval
supplied

ASTERISK-29714

Change-Id: I8548438246f7b718d88e0b9e0a1eb384bbec88e4
2021-11-16 06:00:43 -06:00

1058 lines
28 KiB
C

/*
* 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 "asterisk.h"
#include "asterisk/lock.h"
#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 = 0;
/* 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 (ASN1FASTCOPY) 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 = 0;
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 = 0;
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;
}
if (nbits <= 0) {
return ASN_OK;
}
/* 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 { /* 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 = 0;
unsigned char ub = 0;
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;
}