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

1311 lines
36 KiB
C

/* Copyright (C) Boris Nikolaus, Germany, 1996-1997. All rights reserved. */
/* Copyright (C) Microsoft Corporation, 1997-1998. All rights reserved. */
#include "precomp.h"
#include "cintern.h"
#ifdef TEST_CODER
typedef struct ASN1testcoder_s
{
struct ASN1INTERNencoding_s e;
struct ASN1INTERNdecoding_s d;
} *ASN1testcoder_t;
#define ASN1_TEST_CODER_SIZE (sizeof(struct ASN1testcoder_s))
int TestEnc_InitCoder(ASN1INTERNencoding_t e, ASN1module_t mod);
int TestDec_InitCoder(ASN1INTERNdecoding_t d, ASN1module_t mod);
int TestEnc_Compare(ASN1INTERNencoding_t e, ASN1uint32_t id, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
int TestDec_Compare(ASN1INTERNdecoding_t d, ASN1uint32_t id, void *valref, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize);
#else
#define ASN1_TEST_CODER_SIZE 0
#endif
/* init an ASN1encoding_t */
ASN1error_e ASN1_CreateEncoder
(
ASN1module_t mod,
ASN1encoding_t *enc,
ASN1octet_t *pbBuf,
ASN1uint32_t cbBufSize,
ASN1encoding_t pParent
)
{
if (NULL != mod && NULL != enc)
{
ASN1INTERNencoding_t e;
*enc = NULL;
/* construct ASN1encoding_t */
e = (ASN1INTERNencoding_t)MemAlloc(sizeof(*e) + ASN1_TEST_CODER_SIZE, mod->nModuleName);
if (NULL != e)
{
ZeroMemory(e, sizeof(*e) + ASN1_TEST_CODER_SIZE);
e->info.magic = MAGIC_ENCODER;
e->info.err = ASN1_SUCCESS;
// e->info.pos = e->info.buf = NULL;
// e->info.size = e->info.len = e->info.bit = 0;
e->info.dwFlags = mod->dwFlags;
e->info.module = mod;
// e->child = NULL;
/* set buffer if given */
if (NULL != pbBuf && cbBufSize)
{
e->info.dwFlags |= ASN1ENCODE_SETBUFFER;
e->info.pos = e->info.buf = pbBuf;
e->info.size = cbBufSize;
}
/* set parent if parented, otherwise, initialized to itself */
if (NULL != pParent)
{
e->parent = (ASN1INTERNencoding_t) pParent;
e->info.eRule = pParent->eRule;
}
else
{
e->parent = e;
e->info.eRule = mod->eRule;
}
// e->mem = NULL;
// e->memlength = 0;
// e->memsize = 0;
// e->epi = NULL;
// e->epilength = 0;
// e->episize = 0;
// e->csi = NULL;
// e->csilength = 0;
// e->csisize = 0;
if (! (e->info.dwFlags & ASN1ENCODE_SETBUFFER) && (NULL != pParent))
{
// lonchanc: make sure we have a minimum 256 bytes available.
BOOL fRet = FALSE;
if (ASN1_PER_RULE & e->info.eRule)
{
// this is required for h245.
fRet = ASN1PEREncCheck((ASN1encoding_t) e, 1);
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & e->info.eRule)
{
// this is required for h245.
fRet = ASN1BEREncCheck((ASN1encoding_t) e, 1);
}
#endif // ENABLE_BER
else
{
EncAssert((ASN1encoding_t) e, 0);
MemFree(e);
return ASN1_ERR_RULE;
}
if (fRet)
{
// lonchanc: make sure the first byte is zeroed out, which
// is required for h245.
e->info.buf[0] = '\0';
}
else
{
MemFree(e);
return ASN1_ERR_MEMORY;
}
}
#if defined(TEST_CODER) && defined(_DEBUG)
TestEnc_InitCoder(e, mod);
#endif // defined(TEST_CODER) && defined(_DEBUG)
if (NULL != pParent)
{
EncAssert((ASN1encoding_t) e, NULL == ((ASN1INTERNencoding_t) pParent)->child);
((ASN1INTERNencoding_t) pParent)->child = e;
}
*enc = (ASN1encoding_t) e;
return ASN1_SUCCESS;
}
else
{
return ASN1_ERR_MEMORY;
}
}
return ASN1_ERR_BADARGS;
}
/* encode a value */
ASN1error_e ASN1_Encode
(
ASN1encoding_t enc,
void *value,
ASN1uint32_t id,
ASN1uint32_t flags,
ASN1octet_t *pbBuf,
ASN1uint32_t cbBufSize
)
{
if (NULL != enc)
{
ASN1INTERNencoding_t e = (ASN1INTERNencoding_t)enc;
/* check magic numbers */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
/* clear error */
ASN1EncSetError(enc, ASN1_SUCCESS);
/* new buffer given? */
if (flags & ASN1ENCODE_SETBUFFER)
{
e->info.dwFlags |= ASN1ENCODE_SETBUFFER;
enc->pos = enc->buf = pbBuf;
enc->size = cbBufSize;
enc->len = enc->bit = 0;
}
/* use a new buffer? */
else if ((e->info.dwFlags | flags) & ASN1ENCODE_ALLOCATEBUFFER)
{
e->info.dwFlags &= ~ASN1ENCODE_SETBUFFER;
enc->pos = enc->buf = NULL;
enc->size = enc->len = enc->bit = 0;
}
/* reuse buffer? */
else if ((flags & ASN1ENCODE_REUSEBUFFER) || !((e->info.dwFlags | flags) & ASN1ENCODE_APPEND))
{
EncAssert(enc, NULL != enc->buf);
enc->pos = enc->buf;
enc->bit = enc->len = 0;
}
/* otherwise append to buffer */
/* check id number */
if (id < enc->module->cPDUs)
{
if (ASN1_PER_RULE & enc->eRule)
{
/* encode value */
ASN1PerEncFun_t pfnPER;
if (NULL != (pfnPER = enc->module->PER.apfnEncoder[id]))
{
if ((*pfnPER)(enc, value))
{
ASN1PEREncFlush(enc);
}
else
{
// the error code must be an error
if (ASN1_SUCCEEDED(e->parent->info.err))
{
// cannot return here immediately because we need to do cleanup
ASN1EncSetError(enc, ASN1_ERR_CORRUPT);
}
}
}
else
{
return ASN1EncSetError(enc, ASN1_ERR_BADPDU);
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & enc->eRule)
{
/* encode value */
ASN1BerEncFun_t pfnBER;
if (NULL != (pfnBER = enc->module->BER.apfnEncoder[id]))
{
if ((*pfnBER)(enc, 0, value)) // lonchanc: tag is 0 to make it compiled
{
ASN1BEREncFlush(enc);
}
else
{
// the error code must be an error
if (ASN1_SUCCEEDED(e->parent->info.err))
{
// cannot return here immediately because we need to do cleanup
ASN1EncSetError(enc, ASN1_ERR_CORRUPT);
}
}
}
else
{
return ASN1EncSetError(enc, ASN1_ERR_BADPDU);
}
}
#endif // ENABLE_BER
else
{
return ASN1EncSetError(enc, ASN1_ERR_RULE);
}
/* call abort/done function for non-parented encoding stream */
if (ASN1_SUCCEEDED(e->parent->info.err))
{
// not parented
if (e == e->parent)
{
#if defined(TEST_CODER) && defined(_DEBUG)
if (ASN1_PER_RULE & enc->eRule)
{
if (! TestEnc_Compare(e, id, enc->buf + enc->cbExtraHeader, enc->len - enc->cbExtraHeader))
{
MyDebugBreak();
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & enc->eRule)
{
if (! TestEnc_Compare(e, id, enc->buf + enc->cbExtraHeader, enc->len - enc->cbExtraHeader))
{
MyDebugBreak();
}
}
#endif // ENABLE_BER
#endif
ASN1EncDone(enc);
}
}
else
{
ASN1INTERNencoding_t child, child2;
// not parented
if (e == e->parent)
{
ASN1EncAbort(enc);
}
// clean up...
if ((e->info.dwFlags | flags) & ASN1ENCODE_ALLOCATEBUFFER)
{
ASN1_FreeEncoded(enc, enc->buf);
enc->pos = enc->buf = NULL;
enc->size = enc->len = enc->bit = 0;
}
for (child = e->child; child; child = child2)
{
child2 = child->child;
// make sure it does not touch its parent which may already be freed
child->parent = child;
ASN1_CloseEncoder2((ASN1encoding_t) child);
}
e->child = NULL;
}
/* return error code */
return e->parent->info.err;
}
else
{
return ASN1EncSetError(enc, ASN1_ERR_BADPDU);
}
}
return ASN1_ERR_BADARGS;
}
/* control function for encoding */
ASN1error_e ASN1_SetEncoderOption
(
ASN1encoding_t enc,
ASN1optionparam_t *pOptParam
)
{
if (NULL != enc && NULL != pOptParam)
{
ASN1INTERNencoding_t e = (ASN1INTERNencoding_t)enc;
ASN1error_e rc = ASN1_SUCCESS;
/* check magic number */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
switch (pOptParam->eOption)
{
case ASN1OPT_CHANGE_RULE:
enc->eRule = pOptParam->eRule;
break;
case ASN1OPT_NOT_REUSE_BUFFER:
e->info.dwFlags &= ~ASN1ENCODE_SETBUFFER;
enc->buf = enc->pos = NULL;
enc->size = enc->bit = enc->len = 0;
break;
case ASN1OPT_REWIND_BUFFER:
enc->pos = enc->buf;
enc->bit = enc->len = 0;
break;
default:
rc = ASN1_ERR_BADARGS;
break;
}
return ASN1EncSetError(enc, rc);
}
return ASN1_ERR_BADARGS;
}
ASN1error_e ASN1_GetEncoderOption
(
ASN1encoding_t enc,
ASN1optionparam_t *pOptParam
)
{
if (NULL != enc && NULL != pOptParam)
{
ASN1INTERNencoding_t e = (ASN1INTERNencoding_t)enc;
ASN1error_e rc = ASN1_SUCCESS;
/* check magic number */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
switch (pOptParam->eOption)
{
case ASN1OPT_GET_RULE:
pOptParam->eRule = enc->eRule;
break;
default:
rc = ASN1_ERR_BADARGS;
break;
}
return ASN1EncSetError(enc, rc);
}
return ASN1_ERR_BADARGS;
}
/* destroy encoding stream */
void ASN1_CloseEncoder
(
ASN1encoding_t enc
)
{
if (NULL != enc)
{
ASN1INTERNencoding_t e = (ASN1INTERNencoding_t)enc;
/* check magic number */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
if (e != e->parent)
{
EncAssert(enc, e == e->parent->child);
e->parent->child = NULL;
}
/* free encoding stream */
MemFree(e);
}
}
/* destroy encoding stream */
void ASN1_CloseEncoder2
(
ASN1encoding_t enc
)
{
if (NULL != enc)
{
/* check magic number */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
EncMemFree(enc, enc->buf);
ASN1_CloseEncoder(enc);
}
}
/* init an ASN1decoding_t */
ASN1error_e ASN1_CreateDecoder
(
ASN1module_t mod,
ASN1decoding_t *dec,
ASN1octet_t *pbBuf,
ASN1uint32_t cbBufSize,
ASN1decoding_t pParent
)
{
return ASN1_CreateDecoderEx(mod, dec, pbBuf, cbBufSize, pParent, ASN1FLAGS_NONE);
}
ASN1error_e ASN1_CreateDecoderEx
(
ASN1module_t mod,
ASN1decoding_t *dec,
ASN1octet_t *pbBuf,
ASN1uint32_t cbBufSize,
ASN1decoding_t pParent,
ASN1uint32_t dwFlags
)
{
if (NULL != mod && NULL != dec)
{
ASN1INTERNdecoding_t d;
*dec = NULL;
/* construct ASN1decoding_t */
d = (ASN1INTERNdecoding_t)MemAlloc(sizeof(*d) + ASN1_TEST_CODER_SIZE, mod->nModuleName);
if (NULL != d)
{
ZeroMemory(d, sizeof(*d) + ASN1_TEST_CODER_SIZE);
d->info.magic = MAGIC_DECODER;
d->info.err = ASN1_SUCCESS;
d->info.dwFlags = mod->dwFlags;
d->info.module = mod;
// d->child = NULL;
/* set parent if parented */
if (NULL != pParent)
{
DecAssert((ASN1decoding_t) d, NULL == ((ASN1INTERNdecoding_t) pParent)->child);
((ASN1INTERNdecoding_t) pParent)->child = d;
d->parent = (ASN1INTERNdecoding_t) pParent;
d->info.eRule = pParent->eRule;
}
else
/* initialize otherwise */
{
d->parent = d;
d->info.eRule = mod->eRule;
}
/* set buffer if given */
// lonchanc: it is ok to have a zero buffer size here
if (NULL != pbBuf)
{
d->info.dwFlags |= ASN1DECODE_SETBUFFER;
d->info.buf = d->info.pos = pbBuf;
d->info.size = cbBufSize;
// d->info.len = d->info.bit = 0;
if ((dwFlags & ASN1DECODE_AUTOFREEBUFFER)
&& !d->parent->fExtBuf)
{
// dbarlow: It's possible the buffer isn't really
// allocated, but instead came from the
// parent's Extension buffer.
d->info.dwFlags |= ASN1DECODE_AUTOFREEBUFFER;
}
}
// else
// {
// d->info.buf = d->info.pos = NULL;
// d->info.size = d->info.len = d->info.bit = 0;
// }
// d->mem = NULL;
// d->memlength = 0;
// d->memsize = 0;
// d->epi = NULL;
// d->epilength = 0;
// d->episize = 0;
// d->csi = NULL;
// d->csilength = 0;
// d->csisize = 0;
#if defined(TEST_CODER) && defined(_DEBUG)
TestDec_InitCoder(d, mod);
#endif // defined(TEST_CODER) && defined(_DEBUG)
*dec = (ASN1decoding_t) d;
return ASN1_SUCCESS;
}
else
{
if (dwFlags & ASN1DECODE_AUTOFREEBUFFER)
{
// dbarlow: It's possible the buffer isn't really
// allocated, but instead came from the
// parent's Extension buffer.
d = (ASN1INTERNdecoding_t)pParent;
if ((NULL == d) || !d->fExtBuf)
{
MemFree(pbBuf);
}
}
return ASN1_ERR_MEMORY;
}
}
return ASN1_ERR_BADARGS;
}
/* decode a value */
ASN1error_e ASN1_Decode
(
ASN1decoding_t dec,
void **valref,
ASN1uint32_t id,
ASN1uint32_t flags,
ASN1octet_t *pbBuf,
ASN1uint32_t cbBufSize
)
{
ASN1error_e ReturnCode = ASN1_SUCCESS;
if (NULL != dec && NULL != valref)
{
ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t)dec;
/* check magic numbers */
DecAssert(dec, MAGIC_DECODER == dec->magic);
/* clear error */
ASN1DecSetError(dec, ASN1_SUCCESS);
/* new buffer given? */
*valref = NULL;
if (flags & ASN1DECODE_SETBUFFER)
{
if (NULL != pbBuf && 0 != cbBufSize)
{
dec->pos = dec->buf = pbBuf;
dec->size = cbBufSize;
dec->bit = dec->len = 0;
}
else
{
ReturnCode = ASN1DecSetError(dec, ASN1_ERR_BADARGS);
goto ErrorExit;
}
}
/* rewind buffer? */
else if ((flags & ASN1DECODE_REWINDBUFFER) ||
!((d->info.dwFlags | flags ) & ASN1DECODE_APPENDED))
{
dec->pos = dec->buf;
dec->bit = dec->len = 0;
}
/* otherwise continue reading from last buffer */
/* check id number */
if (id < dec->module->cPDUs)
{
ASN1uint32_t cbTopLevelStruct;
/* clear length of linear buffer required */
d->cbLinearBufSize = 0;
/* double check for the availability of destination buffer */
if (d->lpOrigExtBuf == NULL || d->cbOrigExtBufSize == 0)
{
d->fExtBuf = FALSE;
}
cbTopLevelStruct = dec->module->acbStructSize[id];
if (NULL != (*valref = DecMemAlloc(dec, cbTopLevelStruct)))
{
if (ASN1_PER_RULE & dec->eRule)
{
ASN1PerDecFun_t pfnPER;
/* decode value */
if (NULL != (pfnPER = dec->module->PER.apfnDecoder[id]))
{
if ((*pfnPER)(dec, *valref))
{
ASN1PERDecFlush(dec);
}
else
{
// the error code must be an error
if (ASN1_SUCCEEDED(d->parent->info.err))
{
// cannot return here immediately because we need to do cleanup
ASN1DecSetError(dec, ASN1_ERR_CORRUPT);
}
}
}
else
{
ReturnCode = ASN1DecSetError(dec, ASN1_ERR_BADPDU);
goto ErrorExit;
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & dec->eRule)
{
ASN1BerDecFun_t pfnBER;
/* decode value */
if (NULL != (pfnBER = dec->module->BER.apfnDecoder[id]))
{
if ((*pfnBER)(dec, 0, *valref)) // lonchanc: tag is 0 to make it compiled
{
ASN1BERDecFlush(dec);
}
else
{
// the error code must be an error
if (ASN1_SUCCEEDED(d->parent->info.err))
{
// cannot return here immediately because we need to do cleanup
ASN1DecSetError(dec, ASN1_ERR_CORRUPT);
}
}
}
else
{
ReturnCode = ASN1DecSetError(dec, ASN1_ERR_BADPDU);
goto ErrorExit;
}
}
#endif // ENABLE_BER
else
{
ReturnCode = ASN1DecSetError(dec, ASN1_ERR_RULE);
goto ErrorExit;
}
/* call abort/done function for non-parented decoding stream */
if (ASN1_SUCCEEDED(d->parent->info.err))
{
// not parented
if (d == d->parent)
{
#if defined(TEST_CODER) && defined(_DEBUG)
if (ASN1_PER_RULE & dec->eRule)
{
if (! TestDec_Compare(d, id, *valref, dec->buf, dec->len))
{
MyDebugBreak();
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & dec->eRule)
{
if (! TestDec_Compare(d, id, *valref, dec->buf, dec->len))
{
MyDebugBreak();
}
}
#endif // ENABLE_BER
#endif
ASN1DecDone(dec);
}
}
else
{
ASN1INTERNdecoding_t child, child2;
// not parented
if (d == d->parent)
{
ASN1DecAbort(dec);
}
// clean up...
for (child = d->child; child; child = child2)
{
child2 = child->child;
// make sure it does not touch its parent which may already be freed
child->parent = child;
ASN1_CloseDecoder((ASN1decoding_t) child);
}
d->child = NULL;
}
/* return error code */
ReturnCode = d->parent->info.err;
goto ErrorExit;
}
else
{
ReturnCode = ASN1_ERR_MEMORY;
goto ErrorExit;
}
}
else
{
ReturnCode = ASN1DecSetError(dec, ASN1_ERR_BADPDU);
goto ErrorExit;
}
}
ReturnCode = ASN1_ERR_BADARGS;
ErrorExit:
if (ASN1_FAILED(ReturnCode))
{
if (NULL != valref)
{
ASN1_FreeDecoded(dec ,*valref, id);
*valref = NULL;
}
}
return ReturnCode;
}
/* control function for decoding */
ASN1error_e ASN1_SetDecoderOption
(
ASN1decoding_t dec,
ASN1optionparam_t *pOptParam
)
{
if (NULL != dec)
{
ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t)dec;
ASN1error_e rc = ASN1_SUCCESS;
/* check magic number */
DecAssert(dec, MAGIC_DECODER == dec->magic);
switch (pOptParam->eOption)
{
case ASN1OPT_CHANGE_RULE:
dec->eRule = pOptParam->eRule;
break;
case ASN1OPT_SET_DECODED_BUFFER:
if (NULL != pOptParam->Buffer.pbBuf && 0 != pOptParam->Buffer.cbBufSize)
{
d->fExtBuf = TRUE;
d->lpOrigExtBuf = pOptParam->Buffer.pbBuf;
d->cbOrigExtBufSize = pOptParam->Buffer.cbBufSize;
d->lpRemExtBuf = d->lpOrigExtBuf;
d->cbRemExtBufSize = d->cbOrigExtBufSize;
}
else
{
rc = ASN1_ERR_BADARGS;
}
break;
case ASN1OPT_DEL_DECODED_BUFFER:
d->fExtBuf = FALSE;
d->lpOrigExtBuf = NULL;
d->cbOrigExtBufSize = 0;
d->lpRemExtBuf = NULL;
d->cbRemExtBufSize = 0;
break;
default:
rc = ASN1_ERR_BADARGS;
break;
}
return ASN1DecSetError(dec, rc);
}
return ASN1_ERR_BADARGS;
}
/* control function for decoding */
ASN1error_e ASN1_GetDecoderOption
(
ASN1decoding_t dec,
ASN1optionparam_t *pOptParam
)
{
if (NULL != dec)
{
ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t)dec;
ASN1error_e rc = ASN1_SUCCESS;
/* check magic number */
DecAssert(dec, MAGIC_DECODER == dec->magic);
switch (pOptParam->eOption)
{
case ASN1OPT_GET_RULE:
pOptParam->eRule = dec->eRule;
break;
case ASN1OPT_GET_DECODED_BUFFER_SIZE:
pOptParam->cbRequiredDecodedBufSize = d->cbLinearBufSize;
break;
default:
rc = ASN1_ERR_BADARGS;
break;
}
return ASN1DecSetError(dec, rc);
}
return ASN1_ERR_BADARGS;
}
/* destroy decoding stream */
void ASN1_CloseDecoder
(
ASN1decoding_t dec
)
{
if (NULL != dec)
{
ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t)dec;
/* check magic number */
DecAssert(dec, MAGIC_DECODER == dec->magic);
if (d != d->parent)
{
DecAssert(dec, d == d->parent->child);
d->parent->child = NULL;
}
if ((NULL != d->info.buf)
&& (d->info.dwFlags & ASN1DECODE_AUTOFREEBUFFER))
MemFree(d->info.buf);
/* free decoding stream */
MemFree(d);
}
}
/* free an encoded value */
void ASN1_FreeEncoded
(
ASN1encoding_t enc,
void *val
)
{
if (NULL != enc)
{
/* check magic number */
EncAssert(enc, MAGIC_ENCODER == enc->magic);
EncMemFree(enc, val);
}
}
/* free a unencoded value */
void ASN1_FreeDecoded
(
ASN1decoding_t dec,
void *val,
ASN1uint32_t id
)
{
if (NULL != dec)
{
ASN1INTERNdecoding_t d = (ASN1INTERNdecoding_t)dec;
/* check magic number */
DecAssert(dec, MAGIC_DECODER == dec->magic);
// same behavior of LocalFree
if (val != NULL)
{
if (id != ASN1DECFREE_NON_PDU_ID)
{
ASN1FreeFun_t pfnFreeMemory;
/* free value */
if (id < dec->module->cPDUs)
{
if (NULL != (pfnFreeMemory = dec->module->apfnFreeMemory[id]))
{
(*pfnFreeMemory)(val);
}
}
else
{
return;
}
}
// free the top-level structure
DecMemFree(dec, val);
}
}
}
ASN1module_t ASN1_CreateModule
(
ASN1uint32_t version,
ASN1encodingrule_e eEncodingRule,
ASN1uint32_t dwFlags,
ASN1uint32_t cPDUs,
const ASN1GenericFun_t apfnEncoder[],
const ASN1GenericFun_t apfnDecoder[],
const ASN1FreeFun_t apfnFreeMemory[],
const ASN1uint32_t acbStructSize[],
ASN1magic_t nModuleName
)
{
ASN1module_t module = NULL;
/* compiler output and library version match together? */
if (
// version <= ASN1_THIS_VERSION &&
NULL != apfnEncoder &&
NULL != apfnDecoder &&
NULL != apfnFreeMemory &&
NULL != acbStructSize)
{
if (NULL != (module = (ASN1module_t)MemAlloc(sizeof(*module), nModuleName)))
{
module->nModuleName = nModuleName;
module->eRule = eEncodingRule;
module->dwFlags = dwFlags;
module->cPDUs = cPDUs;
module->apfnFreeMemory = apfnFreeMemory;
module->acbStructSize = acbStructSize;
if (ASN1_PER_RULE & eEncodingRule)
{
module->PER.apfnEncoder = (const ASN1PerEncFun_t *) apfnEncoder;
module->PER.apfnDecoder = (const ASN1PerDecFun_t *) apfnDecoder;
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & eEncodingRule)
{
module->BER.apfnEncoder = (const ASN1BerEncFun_t *) apfnEncoder;
module->BER.apfnDecoder = (const ASN1BerDecFun_t *) apfnDecoder;
}
#endif // ENABLE_BER
}
}
return module;
}
void ASN1_CloseModule(ASN1module_t pModule)
{
MemFree(pModule);
}
#ifdef TEST_CODER
static int MyMemCmp(ASN1octet_t *p1, ASN1octet_t *p2, ASN1uint32_t c)
{
BYTE diff;
while (c--)
{
if ((diff = *p1++ - *p2++) != 0)
return (int) diff;
}
return 0;
}
__inline ASN1INTERNencoding_t TestEnc_GetEnc(ASN1INTERNencoding_t e)
{ return &(((ASN1testcoder_t) (e+1))->e); }
__inline ASN1INTERNdecoding_t TestEnc_GetDec(ASN1INTERNencoding_t e)
{ return &(((ASN1testcoder_t) (e+1))->d); }
__inline ASN1INTERNencoding_t TestDec_GetEnc(ASN1INTERNdecoding_t d)
{ return &(((ASN1testcoder_t) (d+1))->e); }
__inline ASN1INTERNdecoding_t TestDec_GetDec(ASN1INTERNdecoding_t d)
{ return &(((ASN1testcoder_t) (d+1))->d); }
static void Test_InitEnc(ASN1INTERNencoding_t e, ASN1module_t mod, ASN1encodingrule_e eRule)
{
ZeroMemory(e, sizeof(*e));
e->info.magic = MAGIC_ENCODER;
e->info.err = ASN1_SUCCESS;
e->info.module = mod;
e->info.eRule = eRule;
e->parent = e;
e->child = NULL;
}
static void Test_InitDec(ASN1INTERNdecoding_t d, ASN1module_t mod, ASN1encodingrule_e eRule)
{
ZeroMemory(d, sizeof(*d));
d->info.magic = MAGIC_DECODER;
d->info.err = ASN1_SUCCESS;
d->info.module = mod;
d->info.eRule = eRule;
d->parent = d;
d->child = NULL;
}
static int TestEnc_InitCoder(ASN1INTERNencoding_t e, ASN1module_t mod)
{
ASN1INTERNencoding_t ee = TestEnc_GetEnc(e);
ASN1INTERNdecoding_t ed = TestEnc_GetDec(e);
Test_InitEnc(ee, mod, e->info.eRule);
Test_InitDec(ed, mod, e->info.eRule);
return 1;
}
static int TestDec_InitCoder(ASN1INTERNdecoding_t d, ASN1module_t mod)
{
ASN1INTERNencoding_t de = TestDec_GetEnc(d);
ASN1INTERNdecoding_t dd = TestDec_GetDec(d);
Test_InitEnc(de, mod, d->info.eRule);
Test_InitDec(dd, mod, d->info.eRule);
return 1;
}
static int Test_Encode(ASN1INTERNencoding_t e, void *value, ASN1uint32_t id)
{
ASN1encoding_t enc = (ASN1encoding_t) e;
/* clear error */
ASN1EncSetError(enc, ASN1_SUCCESS);
// clean buffer
enc->pos = enc->buf;
enc->bit = enc->len = 0;
if (ASN1_PER_RULE & enc->eRule)
{
/* encode value */
ASN1PerEncFun_t pfnPER;
if (NULL != (pfnPER = enc->module->PER.apfnEncoder[id]))
{
if ((*pfnPER)(enc, value))
{
ASN1PEREncFlush(enc);
}
}
else
{
return ASN1EncSetError(enc, ASN1_ERR_BADPDU);
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & enc->eRule)
{
/* encode value */
ASN1BerEncFun_t pfnBER;
if (NULL != (pfnBER = enc->module->BER.apfnEncoder[id]))
{
if ((*pfnBER)(enc, 0, value)) // lonchanc: tag is 0 to make it compiled
{
ASN1BEREncFlush(enc);
}
}
else
{
return ASN1EncSetError(enc, ASN1_ERR_BADPDU);
}
}
#endif // ENABLE_BER
else
{
return ASN1EncSetError(enc, ASN1_ERR_RULE);
}
/* call abort/done function for non-parented encoding stream */
if (e->parent->info.err >= 0)
{
if (e == e->parent)
{
ASN1EncDone(enc);
}
}
else
{
ASN1INTERNencoding_t child, child2;
if (e == e->parent)
{
ASN1EncAbort(enc);
}
// clean up...
ASN1_FreeEncoded(enc, enc->buf);
enc->pos = enc->buf = NULL;
enc->size = enc->len = enc->bit = 0;
for (child = e->child; child; child = child2)
{
child2 = child->child;
// make sure it does not touch its parent which may already be freed
child->parent = child;
ASN1_CloseEncoder((ASN1encoding_t) child);
}
e->child = NULL;
}
/* return error code */
return e->parent->info.err;
}
static int Test_Decode(ASN1INTERNdecoding_t d, void ** valref, ASN1uint32_t id, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize)
{
ASN1decoding_t dec = (ASN1decoding_t) d;
ASN1uint32_t cbTopLevelStruct;
/* clear error */
ASN1DecSetError(dec, ASN1_SUCCESS);
// set up buffer containing encoded data
dec->pos = dec->buf = pbBuf;
dec->size = cbBufSize;
dec->bit = dec->len = 0;
/* clear length of linear buffer required */
d->cbLinearBufSize = 0;
d->fExtBuf = FALSE;
cbTopLevelStruct = dec->module->acbStructSize[id];
if (NULL != (*valref = DecMemAlloc(dec, cbTopLevelStruct)))
{
if (ASN1_PER_RULE & dec->eRule)
{
ASN1PerDecFun_t pfnPER;
/* decode value */
if (NULL != (pfnPER = dec->module->PER.apfnDecoder[id]))
{
if ((*pfnPER)(dec, *valref))
{
ASN1PERDecFlush(dec);
}
}
else
{
return ASN1DecSetError(dec, ASN1_ERR_BADPDU);
}
}
#ifdef ENABLE_BER
else
if (ASN1_BER_RULE & dec->eRule)
{
ASN1BerDecFun_t pfnBER;
/* decode value */
if (NULL != (pfnBER = dec->module->BER.apfnDecoder[id]))
{
if ((*pfnBER)(dec, 0, *valref))
{
ASN1BERDecFlush(dec);
}
}
else
{
return ASN1DecSetError(dec, ASN1_ERR_BADPDU);
}
}
#endif // ENABLE_BER
else
{
return ASN1DecSetError(dec, ASN1_ERR_RULE);
}
/* call abort/done function for non-parented decoding stream */
if (d->parent->info.err >= 0)
{
// not parented
if (d == d->parent)
{
ASN1DecDone(dec);
}
}
else
{
ASN1INTERNdecoding_t child, child2;
// not parented
if (d == d->parent)
{
ASN1DecAbort(dec);
}
// clean up...
ASN1_FreeDecoded(dec ,*valref, id);
*valref = NULL;
for (child = d->child; child; child = child2)
{
child2 = child->child;
// make sure it does not touch its parent which may already be freed
child->parent = child;
ASN1_CloseDecoder((ASN1decoding_t) child);
}
d->child = NULL;
}
}
else
{
return ASN1_ERR_MEMORY;
}
/* return error code */
return d->parent->info.err;
}
static void Test_CleanEnc(ASN1INTERNencoding_t e)
{
if (e->info.buf)
{
EncMemFree((ASN1encoding_t) e, e->info.buf);
}
Test_InitEnc(e, e->info.module, e->info.eRule);
}
static void Test_CleanDec(ASN1INTERNdecoding_t d)
{
Test_InitDec(d, d->info.module, d->info.eRule);
}
static int TestEnc_Compare(ASN1INTERNencoding_t e, ASN1uint32_t id, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize)
{
ASN1INTERNencoding_t ee = TestEnc_GetEnc(e);
ASN1INTERNdecoding_t ed = TestEnc_GetDec(e);
int ret;
void *val = NULL;
int fRet = 0;
ee->info.eRule = e->info.eRule;
ed->info.eRule = e->info.eRule;
ret = Test_Decode(ed, &val, id, pbBuf, cbBufSize);
if (ret == ASN1_SUCCESS)
{
ret = Test_Encode(ee, val, id);
if (ret == ASN1_SUCCESS)
{
if (ee->info.len == cbBufSize)
{
fRet = (MyMemCmp(pbBuf, ee->info.buf, cbBufSize) == 0);
}
}
}
if (val)
{
ASN1_FreeDecoded((ASN1decoding_t) ed, val, id);
}
Test_CleanEnc(ee);
Test_CleanDec(ed);
return fRet;
}
static int TestDec_Compare(ASN1INTERNdecoding_t d, ASN1uint32_t id, void *val, ASN1octet_t *pbBuf, ASN1uint32_t cbBufSize)
{
ASN1INTERNencoding_t de = TestDec_GetEnc(d);
int ret;
int fRet = 0;
de->info.eRule = d->info.eRule;
ret = Test_Encode(de, val, id);
if (ret == ASN1_SUCCESS)
{
if (de->info.len == cbBufSize)
{
fRet = (MyMemCmp(pbBuf, de->info.buf, cbBufSize) == 0);
}
}
Test_CleanEnc(de);
return fRet;
}
#endif