Windows-Server-2003/enduser/msasn1/ms_per.c

606 lines
16 KiB
C

/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
//--------------------------------------------------------------------------
//
// Module Name: ms_per.c
//
// Brief Description:
// This module contains the routines for the Microsoft
// ASN.1 encoder and decoder.
//
// History:
// 10/15/97 Lon-Chan Chu (lonchanc)
// Created.
//
// Copyright (c) 1997 Microsoft Corporation
//
//--------------------------------------------------------------------------
#include "precomp.h"
#define MLZ_FILE_ZONE ZONE_MSPER
int ASN1PEREncInteger(ASN1encoding_t enc, ASN1int32_t val)
{
ASN1uint32_t l = ASN1int32_octets(val);
ASN1PEREncAlignment(enc);
if (ASN1PEREncBitVal(enc, 8, l))
{
return ASN1PEREncBitVal(enc, l * 8, val);
}
return 0;
}
int ASN1PERDecInteger(ASN1decoding_t dec, ASN1int32_t *val)
{
ASN1uint32_t l;
ASN1PERDecAlignment(dec);
if (ASN1PERDecFragmentedLength(dec, &l))
{
return ASN1PERDecS32Val(dec, l * 8, val);
}
return 0;
}
int ASN1PEREncUnsignedInteger(ASN1encoding_t enc, ASN1uint32_t val)
{
ASN1uint32_t l = ASN1uint32_uoctets(val);
ASN1PEREncAlignment(enc);
if (ASN1PEREncBitVal(enc, 8, l))
{
return ASN1PEREncBitVal(enc, l * 8, val);
}
return 0;
}
int ASN1PERDecUnsignedInteger(ASN1decoding_t dec, ASN1uint32_t *val)
{
ASN1uint32_t l;
ASN1PERDecAlignment(dec);
if (ASN1PERDecFragmentedLength(dec, &l))
{
return ASN1PERDecU32Val(dec, l * 8, val);
}
return 0;
}
int ASN1PEREncUnsignedShort(ASN1encoding_t enc, ASN1uint32_t val)
{
ASN1PEREncAlignment(enc);
return ASN1PEREncBitVal(enc, 16, val);
}
int ASN1PERDecUnsignedShort(ASN1decoding_t dec, ASN1uint16_t *val)
{
ASN1PERDecAlignment(dec);
return ASN1PERDecU16Val(dec, 16, val);
}
int ASN1PEREncBoolean(ASN1encoding_t enc, ASN1bool_t val)
{
return ASN1PEREncBitVal(enc, 1, val ? 1 : 0);
}
int ASN1PERDecBoolean(ASN1decoding_t dec, ASN1bool_t *val)
{
DecAssert(dec, sizeof(ASN1bool_t) == sizeof(ASN1uint8_t));
*val = 0; // in case we change the boolean type
return ASN1PERDecU8Val(dec, 1, val);
}
__inline int _EncExtensionBitClear(ASN1encoding_t enc)
{
return ASN1PEREncBitVal(enc, 1, 0);
}
int ASN1PEREncExtensionBitClear(ASN1encoding_t enc)
{
return _EncExtensionBitClear(enc);
}
__inline int _EncExtensionBitSet(ASN1encoding_t enc)
{
return ASN1PEREncBitVal(enc, 1, 1);
}
int ASN1PEREncExtensionBitSet(ASN1encoding_t enc)
{
return _EncExtensionBitSet(enc);
}
int ASN1PERDecSkipNormallySmallExtensionFragmented(ASN1decoding_t dec)
{
ASN1uint32_t e, i;
if (ASN1PERDecSkipNormallySmallExtension(dec, &e))
{
for (i = 0; i < e; i++)
{
if (ASN1PERDecSkipFragmented(dec, 8))
{
continue;
}
return 0;
}
return 1;
}
return 0;
}
int ASN1PEREncSimpleChoice(ASN1encoding_t enc, ASN1choice_t ChoiceVal, ASN1int32_t cChoiceBits)
{
if (ChoiceVal >= ASN1_CHOICE_BASE)
{
ChoiceVal -= ASN1_CHOICE_BASE;
return (cChoiceBits ? ASN1PEREncBitVal(enc, cChoiceBits, ChoiceVal) : 1);
}
EncAssert(enc, FALSE);
return 0;
}
int ASN1PERDecSimpleChoice(ASN1decoding_t dec, ASN1choice_t *pChoiceVal, ASN1int32_t cChoiceBits)
{
DecAssert(dec, cChoiceBits <= sizeof(ASN1choice_t) * 8);
*pChoiceVal = ASN1_CHOICE_BASE; // default choice
if (cChoiceBits)
{
if (ASN1PERDecU16Val(dec, cChoiceBits, pChoiceVal))
{
*pChoiceVal += ASN1_CHOICE_BASE;
}
else
{
return 0;
}
}
return 1;
}
int ASN1PEREncSimpleChoiceEx(ASN1encoding_t enc, ASN1choice_t ChoiceVal, ASN1int32_t cChoiceBits)
{
if (ChoiceVal >= ASN1_CHOICE_BASE)
{
ChoiceVal -= ASN1_CHOICE_BASE;
if (_EncExtensionBitClear(enc))
{
return (cChoiceBits ? ASN1PEREncBitVal(enc, cChoiceBits, ChoiceVal) : 1);
}
}
else
{
EncAssert(enc, 0);
}
return 0;
}
int ASN1PERDecSimpleChoiceEx(ASN1decoding_t dec, ASN1choice_t *pChoiceVal, ASN1int32_t cChoiceBits)
{
ASN1uint32_t x;
DecAssert(dec, cChoiceBits <= sizeof(ASN1choice_t) * 8);
if (ASN1PERDecExtensionBit(dec, &x))
{
if (!x)
{
*pChoiceVal = ASN1_CHOICE_BASE; // default choice
if (cChoiceBits)
{
if (ASN1PERDecU16Val(dec, cChoiceBits, pChoiceVal))
{
*pChoiceVal += ASN1_CHOICE_BASE;
return 1;
}
return 0;
}
return 1;
}
*pChoiceVal = ASN1_CHOICE_EXTENSION; // extension choice
return ASN1PERDecSkipNormallySmall(dec);
}
return 0;
}
int ASN1PEREncComplexChoice(ASN1encoding_t enc, ASN1choice_t ChoiceVal, ASN1int32_t cChoiceBits, ASN1choice_t ExtensionChoice)
{
if (ChoiceVal >= ASN1_CHOICE_BASE)
{
ChoiceVal -= ASN1_CHOICE_BASE;
if (ChoiceVal < ExtensionChoice) // lonchanc: no equal sign
{
if (_EncExtensionBitClear(enc))
{
if (cChoiceBits)
{
return ASN1PEREncBitVal(enc, cChoiceBits, ChoiceVal);
}
return 1;
}
}
else
{
if (_EncExtensionBitSet(enc))
{
return ASN1PEREncNormallySmall(enc, ChoiceVal - ExtensionChoice);
}
}
}
else
{
EncAssert(enc, 0);
}
return 0;
}
int ASN1PERDecComplexChoice(ASN1decoding_t dec, ASN1choice_t *pChoiceVal, ASN1int32_t cChoiceBits, ASN1choice_t ExtensionChoice)
{
ASN1uint32_t x;
DecAssert(dec, cChoiceBits <= sizeof(ASN1choice_t) * 8);
if (ASN1PERDecExtensionBit(dec, &x))
{
if (!x)
{
*pChoiceVal = ASN1_CHOICE_BASE; // default choice
if (cChoiceBits)
{
if (ASN1PERDecU16Val(dec, cChoiceBits, pChoiceVal))
{
*pChoiceVal += ASN1_CHOICE_BASE;
return 1;
}
return 0;
}
return 1;
}
if (ASN1PERDecN16Val(dec, pChoiceVal))
{
*pChoiceVal += ExtensionChoice + ASN1_CHOICE_BASE;
return 1;
}
}
return 0;
}
int ASN1PEREncOctetString_NoSize(ASN1encoding_t enc, ASN1octetstring_t *pOctetStr)
{
return ASN1PEREncFragmented(enc, pOctetStr->length, pOctetStr->value, 8);
}
int ASN1PERDecOctetString_NoSize(ASN1decoding_t dec, ASN1octetstring_t *pOctetStr)
{
return ASN1PERDecFragmented(dec, &(pOctetStr->length), &(pOctetStr->value), 8);
}
int _PEREncOctetString2
(
ASN1encoding_t enc,
ASN1uint32_t length,
ASN1octet_t *value,
ASN1uint32_t nSizeLowerBound,
ASN1uint32_t nSizeUpperBound,
ASN1uint32_t cSizeBits
)
{
// fixed size array?
if (nSizeLowerBound == nSizeUpperBound)
{
ASN1uint32_t nSizeLimit = nSizeLowerBound;
EncAssert(enc, cSizeBits == 0);
EncAssert(enc, nSizeLimit < 64 * 1024);
if (length == nSizeLimit)
{
if (nSizeLimit > 2)
{
ASN1PEREncAlignment(enc);
}
return ASN1PEREncBits(enc, nSizeLimit * 8, value);
}
EncAssert(enc, 0);
return 0;
}
// ranged size array
EncAssert(enc, cSizeBits);
EncAssert(enc, nSizeLowerBound < nSizeUpperBound);
if (nSizeLowerBound <= length && length <= nSizeUpperBound)
{
if (nSizeUpperBound - nSizeLowerBound < 255) // lonchanc: inherited from TELES
{
if (ASN1PEREncBitVal(enc, cSizeBits, length - nSizeLowerBound))
{
ASN1PEREncAlignment(enc);
}
else
{
return 0;
}
}
else
{
EncAssert(enc, cSizeBits % 8 == 0);
ASN1PEREncAlignment(enc);
if (!ASN1PEREncBitVal(enc, cSizeBits, length - nSizeLowerBound))
return 0;
}
return ASN1PEREncBits(enc, length * 8, value);
}
EncAssert(enc, 0);
return 0;
}
int ASN1PEREncOctetString_FixedSize(ASN1encoding_t enc, ASN1octetstring2_t *pOctetStr, ASN1uint32_t nSizeLimit)
{
return _PEREncOctetString2(enc, pOctetStr->length, &(pOctetStr->value[0]), nSizeLimit, nSizeLimit, 0);
}
int ASN1PEREncOctetString_FixedSizeEx(ASN1encoding_t enc, ASN1octetstring_t *pOctetStr, ASN1uint32_t nSizeLimit)
{
return _PEREncOctetString2(enc, pOctetStr->length, pOctetStr->value, nSizeLimit, nSizeLimit, 0);
}
int ASN1PEREncOctetString_VarSize(ASN1encoding_t enc, ASN1octetstring2_t *pOctetStr, ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
return _PEREncOctetString2(enc, pOctetStr->length, &(pOctetStr->value[0]), nSizeLowerBound, nSizeUpperBound, cSizeBits);
}
int ASN1PEREncOctetString_VarSizeEx(ASN1encoding_t enc, ASN1octetstring_t *pOctetStr, ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
return _PEREncOctetString2(enc, pOctetStr->length, pOctetStr->value, nSizeLowerBound, nSizeUpperBound, cSizeBits);
}
int _PERDecOctetString2
(
ASN1decoding_t dec,
ASN1uint32_t *length,
ASN1octet_t **value,
ASN1uint32_t nSizeLowerBound,
ASN1uint32_t nSizeUpperBound,
ASN1uint32_t cSizeBits
)
{
// fixed size array?
if (nSizeLowerBound == nSizeUpperBound)
{
ASN1uint32_t nSizeLimit = nSizeLowerBound;
DecAssert(dec, cSizeBits == 0);
DecAssert(dec, nSizeLimit < 64 * 1024);
*length = nSizeLimit;
if (nSizeLimit > 2)
{
ASN1PERDecAlignment(dec);
}
if (NULL == *value)
{
// must be unbounded
*value = (ASN1octet_t *) DecMemAlloc(dec, nSizeLimit + 1);
if (NULL == *value)
{
return 0;
}
}
return ASN1PERDecExtension(dec, nSizeLimit * 8, *value);
}
// ranged size array
DecAssert(dec, cSizeBits);
DecAssert(dec, nSizeLowerBound < nSizeUpperBound);
if (nSizeUpperBound - nSizeLowerBound < 255) // lonchanc: inherited from TELES
{
if (ASN1PERDecU32Val(dec, cSizeBits, length))
{
*length += nSizeLowerBound;
ASN1PERDecAlignment(dec);
}
else
{
return 0;
}
}
else
{
DecAssert(dec, cSizeBits % 8 == 0);
ASN1PERDecAlignment(dec);
if (ASN1PERDecU32Val(dec, cSizeBits, length))
{
*length += nSizeLowerBound;
}
else
{
return 0;
}
}
if (*length <= nSizeUpperBound)
{
if (NULL == *value)
{
*value = (ASN1octet_t *) DecMemAlloc(dec, *length + 1);
if (NULL == *value)
{
return 0;
}
}
return ASN1PERDecExtension(dec, *length * 8, *value);
}
DecAssert(dec, 0);
return 0;
}
int ASN1PERDecOctetString_FixedSize(ASN1decoding_t dec, ASN1octetstring2_t *pOctetStr, ASN1uint32_t nSizeLimit)
{
ASN1octet_t *pData = &(pOctetStr->value[0]);
return _PERDecOctetString2(dec, &(pOctetStr->length), &pData, nSizeLimit, nSizeLimit, 0);
}
int ASN1PERDecOctetString_FixedSizeEx(ASN1decoding_t dec, ASN1octetstring_t *pOctetStr, ASN1uint32_t nSizeLimit)
{
pOctetStr->value = NULL;
return _PERDecOctetString2(dec, &(pOctetStr->length), &(pOctetStr->value), nSizeLimit, nSizeLimit, 0);
}
int ASN1PERDecOctetString_VarSize(ASN1decoding_t dec, ASN1octetstring2_t *pOctetStr, ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
ASN1octet_t *pData = &(pOctetStr->value[0]);
return _PERDecOctetString2(dec, &(pOctetStr->length), &pData, nSizeLowerBound, nSizeUpperBound, cSizeBits);
}
int ASN1PERDecOctetString_VarSizeEx(ASN1decoding_t dec, ASN1octetstring_t *pOctetStr, ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
pOctetStr->value = NULL;
return _PERDecOctetString2(dec, &(pOctetStr->length), &(pOctetStr->value), nSizeLowerBound, nSizeUpperBound, cSizeBits);
}
int ASN1PEREncSeqOf_NoSize(ASN1encoding_t enc, ASN1iterator_t **val, ASN1iterator_encfn pfnIterator)
{
ASN1uint32_t t;
ASN1iterator_t *f;
ASN1uint32_t i;
ASN1uint32_t j, n = 0x4000;
EncAssert(enc, NULL != pfnIterator);
for (t = 0, f = *val; f; f = f->next)
t++;
f = *val;
for (i = 0; i < t;)
{
if (ASN1PEREncFragmentedLength(&n, enc, t - i))
{
for (j = 0; j < n; i++, j++)
{
if (((*pfnIterator)(enc, f)))
{
f = f->next;
continue;
}
return 0;
}
}
else
{
return 0;
}
}
return ((n < 0x4000) ? 1 : ASN1PEREncFragmentedLength(&n, enc, 0));
}
int ASN1PERDecSeqOf_NoSize(ASN1decoding_t dec, ASN1iterator_t **val, ASN1iterator_decfn pfnIterator, ASN1uint32_t cbElementSize)
{
ASN1iterator_t **f;
ASN1uint32_t l;
ASN1uint32_t i;
ASN1uint32_t n;
DecAssert(dec, NULL != pfnIterator);
f = val;
do {
if (ASN1PERDecFragmentedLength(dec, &n))
{
for (i = 0; i < n; i++)
{
if (NULL != (*f = (ASN1iterator_t *)DecMemAlloc(dec, cbElementSize)))
{
if ((*pfnIterator)(dec, *f))
{
f = &(*f)->next;
continue;
}
}
return 0;
}
}
else
{
return 0;
}
} while (n >= 0x4000);
*f = NULL;
return 1;
}
int ASN1PEREncSeqOf_VarSize(ASN1encoding_t enc, ASN1iterator_t **val, ASN1iterator_encfn pfnIterator,
ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
ASN1uint32_t t;
ASN1iterator_t *f;
for (t = 0, f = *val; f; f = f->next)
t++;
if (nSizeLowerBound <= t && t <= nSizeUpperBound)
{
if (nSizeUpperBound - nSizeLowerBound + 1 >= 256)
{
ASN1PEREncAlignment(enc);
}
if (ASN1PEREncBitVal(enc, cSizeBits, t - nSizeLowerBound))
{
for (f = *val; f; f = f->next)
{
if (((*pfnIterator)(enc, f)))
{
continue;
}
return 0;
}
return 1;
}
}
else
{
EncAssert(enc, 0);
}
return 0;
}
int ASN1PERDecSeqOf_VarSize(ASN1decoding_t dec, ASN1iterator_t **val, ASN1iterator_decfn pfnIterator, ASN1uint32_t cbElementSize,
ASN1uint32_t nSizeLowerBound, ASN1uint32_t nSizeUpperBound, ASN1uint32_t cSizeBits)
{
ASN1iterator_t **f;
ASN1uint32_t l, i;
if (nSizeUpperBound - nSizeLowerBound + 1 >= 256)
{
ASN1PERDecAlignment(dec);
}
if (ASN1PERDecU32Val(dec, cSizeBits, &l))
{
l += nSizeLowerBound;
DecAssert(dec, l <= nSizeUpperBound);
f = val;
for (i = 0; i < l; i++)
{
if (NULL != (*f = (ASN1iterator_t *)DecMemAlloc(dec, cbElementSize)))
{
if ((*pfnIterator)(dec, *f))
{
f = &(*f)->next;
continue;
}
}
return 0;
}
*f = NULL;
return 1;
}
return 0;
}
void ASN1PERFreeSeqOf(ASN1iterator_t **val, ASN1iterator_freefn pfnIterator)
{
if (val)
{
ASN1iterator_t *f, *ff;
for (f = *val; f; f = ff)
{
ff = f->next;
if (pfnIterator)
{
(*pfnIterator)(f);
}
MemFree(f);
}
}
}