#include "asn-config.h"
#if STDC_HEADERS || HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include "asn-len.h"
#include "asn-tag.h"
#include "str-stk.h"
#include "asn-bits.h"
static unsigned short int unusedBitsG;
char numToHexCharTblG[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
AsnLen
BEncAsnBits PARAMS ((b, data),
BUF_TYPE b _AND_
AsnBits *data)
{
AsnLen len;
len = BEncAsnBitsContent (b, data);
len += BEncDefLen (b, len);
len += BEncTag1 (b, UNIV, PRIM, BITSTRING_TAG_CODE);
return len;
}
void
BDecAsnBits PARAMS ((b, result, bytesDecoded, env),
BUF_TYPE b _AND_
AsnBits *result _AND_
AsnLen *bytesDecoded _AND_
jmp_buf env)
{
AsnTag tag;
AsnLen elmtLen;
if (((tag =BDecTag (b, bytesDecoded, env)) !=
MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE)) &&
(tag != MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE)))
{
Asn1Error ("BDecAsnBits: ERROR - wrong tag on BIT STRING.\n");
longjmp (env, -40);
}
elmtLen = BDecLen (b, bytesDecoded, env);
BDecAsnBitsContent (b, tag, elmtLen, result, bytesDecoded, env);
}
AsnLen
BEncAsnBitsContent PARAMS ((b, bits),
BUF_TYPE b _AND_
AsnBits *bits)
{
unsigned long int unusedBits;
unsigned long int byteLen;
if (bits->bitLen == 0)
byteLen = 0;
else
byteLen = ((bits->bitLen-1) / 8) + 1;
BufPutSegRvs (b, bits->bits, byteLen);
unusedBits = (bits->bitLen % 8);
if (unusedBits != 0)
unusedBits = 8 - unusedBits;
BufPutByteRvs (b, unusedBits);
return byteLen + 1;
}
static void
FillBitStringStk PARAMS ((b, elmtLen0, bytesDecoded, env),
BUF_TYPE b _AND_
AsnLen elmtLen0 _AND_
AsnLen *bytesDecoded _AND_
jmp_buf env)
{
unsigned long int refdLen;
unsigned long int totalRefdLen;
char *strPtr;
unsigned long int totalElmtsLen1 = 0;
unsigned long int tagId1;
unsigned long int elmtLen1;
unsigned long int lenToRef;
for (; (totalElmtsLen1 < elmtLen0) || (elmtLen0 == INDEFINITE_LEN); )
{
tagId1 = BDecTag (b, &totalElmtsLen1, env);
if ((tagId1 == EOC_TAG_ID) && (elmtLen0 == INDEFINITE_LEN))
{
BDEC_2ND_EOC_OCTET (b, &totalElmtsLen1, env);
break;
}
elmtLen1 = BDecLen (b, &totalElmtsLen1, env);
if (tagId1 == MAKE_TAG_ID (UNIV, PRIM, BITSTRING_TAG_CODE))
{
if (unusedBitsG != 0)
{
Asn1Error ("FillBitStringStk: ERROR - a component of a constructed BIT STRING that is not the last has non-zero unused bits\n");
longjmp (env, -1);
}
if (elmtLen1 != 0)
unusedBitsG = BufGetByte (b);
totalRefdLen = 0;
lenToRef =elmtLen1-1;
refdLen = lenToRef;
while (1)
{
strPtr = BufGetSeg (b, &refdLen);
PUSH_STR (strPtr, refdLen, env);
totalRefdLen += refdLen;
if (totalRefdLen == lenToRef)
break;
if (refdLen == 0)
{
Asn1Error ("FillBitStringStk: ERROR - expecting more data\n");
longjmp (env, -2);
}
refdLen = lenToRef - totalRefdLen;
}
totalElmtsLen1 += elmtLen1;
}
else if (tagId1 == MAKE_TAG_ID (UNIV, CONS, BITSTRING_TAG_CODE))
{
FillBitStringStk (b, elmtLen1, &totalElmtsLen1, env);
}
else
{
Asn1Error ("FillBitStringStk: ERROR - decoded non-BIT STRING tag inside a constructed BIT STRING\n");
longjmp (env, -3);
}
}
(*bytesDecoded) += totalElmtsLen1;
}
static void
BDecConsAsnBits PARAMS ((b, len, result, bytesDecoded, env),
BUF_TYPE b _AND_
AsnLen len _AND_
AsnBits *result _AND_
AsnLen *bytesDecoded _AND_
jmp_buf env)
{
char *bufCurr;
unsigned long int curr;
RESET_STR_STK();
FillBitStringStk (b, len, bytesDecoded, env);
result->bitLen = strStkG.totalByteLen*8 - unusedBitsG;
bufCurr = result->bits = Asn1Alloc (strStkG.totalByteLen);
for (curr = 0; curr < strStkG.nextFreeElmt; curr++)
{
memcpy (bufCurr, strStkG.stk[curr].str, strStkG.stk[curr].len);
bufCurr += strStkG.stk[curr].len;
}
}
void
BDecAsnBitsContent PARAMS ((b, tagId, len, result, bytesDecoded, env),
BUF_TYPE b _AND_
AsnTag tagId _AND_
AsnLen len _AND_
AsnBits *result _AND_
AsnLen *bytesDecoded _AND_
jmp_buf env)
{
if (TAG_IS_CONS (tagId))
BDecConsAsnBits (b, len, result, bytesDecoded, env);
else
{
(*bytesDecoded) += len;
len--;
result->bitLen = (len * 8) - (unsigned int)BufGetByte (b);
result->bits = Asn1Alloc (len);
BufCopy (result->bits, b, len);
if (BufReadError (b))
{
Asn1Error ("BDecAsnBitsContent: ERROR - decoded past end of data\n");
longjmp (env, -4);
}
}
}
void
FreeAsnBits PARAMS ((v),
AsnBits *v)
{
Asn1Free (v->bits);
}
void
PrintAsnBits PARAMS ((f,v, indent),
FILE *f _AND_
AsnBits *v _AND_
unsigned short indent)
{
int i;
unsigned long int octetLen;
if (v->bitLen == 0)
octetLen = 0;
else
octetLen = (v->bitLen-1)/8 +1;
fprintf (f,"'");
for (i = 0; i < octetLen; i++)
fprintf (f,"%c%c", TO_HEX (v->bits[i] >> 4), TO_HEX (v->bits[i]));
fprintf (f,"'H");
}
int
AsnBitsEquiv PARAMS ((b1, b2),
AsnBits *b1 _AND_
AsnBits *b2)
{
int octetsLessOne;
int octetBits;
if ((b1->bitLen == 0) && (b2->bitLen == 0))
return TRUE;
octetsLessOne = (b1->bitLen-1)/8;
octetBits = 7 - (b1->bitLen % 8);
return b1->bitLen == b2->bitLen && !memcmpeq (b1->bits, b2->bits, octetsLessOne) && ((b1->bits[octetsLessOne] & (0xFF << octetBits)) == (b1->bits[octetsLessOne] & (0xFF << octetBits)));
}
void
SetAsnBit PARAMS ((b1, bit),
AsnBits *b1 _AND_
unsigned long int bit)
{
unsigned long int octet;
unsigned long int octetsBit;
if (bit < b1->bitLen)
{
octet = bit/8;
octetsBit = 7 - (bit % 8);
b1->bits[octet] |= 1 << octetsBit;
}
}
void
ClrAsnBit PARAMS ((b1, bit),
AsnBits *b1 _AND_
unsigned long int bit)
{
unsigned long int octet;
unsigned long int octetsBit;
if (bit < b1->bitLen)
{
octet = bit/8;
octetsBit = 7 - (bit % 8);
b1->bits[octet] &= ~(1 << octetsBit);
}
}
int
GetAsnBit PARAMS ((b1, bit),
AsnBits *b1 _AND_
unsigned long int bit)
{
unsigned long int octet;
unsigned long int octetsBit;
if (bit < b1->bitLen)
{
octet = bit/8;
octetsBit = 7 - (bit % 8);
return b1->bits[octet] & (1 << octetsBit);
}
return 0;
}