diff --git a/include/winpr/asn1.h b/include/winpr/asn1.h index b1c90acfe..3b64a4636 100644 --- a/include/winpr/asn1.h +++ b/include/winpr/asn1.h @@ -253,7 +253,7 @@ struct tagASN1module_t const ASN1FreeFun_t* apfnFreeMemory; const ASN1uint32_t* acbStructSize; ASN1BerFunArr_t BER; -} +}; typedef struct tagASN1module_t* ASN1module_t; struct ASN1encoding_s @@ -289,8 +289,8 @@ struct ASN1decoding_s enum { - ASN1FLAGS_NONE = 0x00000000L, - ASN1FLAGS_NOASSERT = 0x00001000L, + ASN1FLAGS_NONE = 0x00000000L, + ASN1FLAGS_NOASSERT = 0x00001000L, }; enum @@ -350,7 +350,7 @@ enum tagASN1option_e ASN1OPT_DEL_DECODED_BUFFER = 0x502, ASN1OPT_GET_DECODED_BUFFER_SIZE = 0x601, }; -typedef enum ASN1option_e; +typedef enum tagASN1option_e ASN1option_e; struct tagASN1optionparam_t { @@ -377,6 +377,137 @@ WINPR_API ASN1error_e ASN1_GetEncoderOption(ASN1encoding_t pEncoderInfo, ASN1opt WINPR_API ASN1error_e ASN1_SetDecoderOption(ASN1decoding_t pDecoderInfo, ASN1optionparam_t* pOptParam); WINPR_API ASN1error_e ASN1_GetDecoderOption(ASN1decoding_t pDecoderInfo, ASN1optionparam_t* pOptParam); +WINPR_API void ASN1bitstring_free(ASN1bitstring_t* bitstring); +WINPR_API void ASN1octetstring_free(ASN1octetstring_t* octetstring); +WINPR_API void ASN1objectidentifier_free(ASN1objectidentifier_t* objectidentifier); +WINPR_API void ASN1charstring_free(ASN1charstring_t* charstring); +WINPR_API void ASN1char16string_free(ASN1char16string_t* char16string); +WINPR_API void ASN1char32string_free(ASN1char32string_t* char32string); +WINPR_API void ASN1ztcharstring_free(ASN1ztcharstring_t ztcharstring); +WINPR_API void ASN1ztchar16string_free(ASN1ztchar16string_t ztchar16string); +WINPR_API void ASN1ztchar32string_free(ASN1ztchar32string_t ztchar32string); +WINPR_API void ASN1open_free(ASN1open_t* open); +WINPR_API void ASN1utf8string_free(ASN1wstring_t* utf8string); + +WINPR_API LPVOID ASN1DecAlloc(ASN1decoding_t dec, ASN1uint32_t size); +WINPR_API LPVOID ASN1DecRealloc(ASN1decoding_t dec, LPVOID ptr, ASN1uint32_t size); + +WINPR_API void ASN1Free(LPVOID ptr); + +WINPR_API ASN1error_e ASN1EncSetError(ASN1encoding_t enc, ASN1error_e err); +WINPR_API ASN1error_e ASN1DecSetError(ASN1decoding_t dec, ASN1error_e err); + +WINPR_API ASN1uint32_t ASN1intx_uoctets(ASN1intx_t* intx); +WINPR_API void ASN1intx_free(ASN1intx_t* intx); +WINPR_API ASN1int32_t ASN1intx2int32(ASN1intx_t* intx); +WINPR_API ASN1uint32_t ASN1intx2uint32(ASN1intx_t* intx); +WINPR_API int ASN1intxisuint32(ASN1intx_t* intx); +WINPR_API void ASN1intx_setuint32(ASN1intx_t* dst, ASN1uint32_t val); + +WINPR_API ASN1uint32_t ASN1uint32_uoctets(ASN1uint32_t val); + +WINPR_API int ASN1intx_cmp(ASN1intx_t* intx1, ASN1intx_t* intx2); +WINPR_API int ASN1objectidentifier_cmp(ASN1objectidentifier_t* oid1, ASN1objectidentifier_t* oid2); +WINPR_API int ASN1objectidentifier2_cmp(ASN1objectidentifier2_t* oid1, ASN1objectidentifier2_t* oid2); +WINPR_API int ASN1bitstring_cmp(ASN1bitstring_t* str1, ASN1bitstring_t* str2, int length); +WINPR_API int ASN1octetstring_cmp(ASN1octetstring_t* str1, ASN1octetstring_t* str2); +WINPR_API int ASN1charstring_cmp(ASN1charstring_t* str1, ASN1charstring_t* str2); +WINPR_API int ASN1char16string_cmp(ASN1char16string_t* str1, ASN1char16string_t* str2); +WINPR_API int ASN1char32string_cmp(ASN1char32string_t* str1, ASN1char32string_t* str2); +WINPR_API int ASN1ztcharstring_cmp(ASN1ztcharstring_t str1, ASN1ztcharstring_t str2); +WINPR_API int ASN1ztchar16string_cmp(ASN1ztchar16string_t str1, ASN1ztchar16string_t str2); +WINPR_API int ASN1ztchar32string_cmp(ASN1ztchar32string_t str1, ASN1ztchar32string_t str2); +WINPR_API int ASN1open_cmp(ASN1open_t* open1, ASN1open_t* open2); +WINPR_API int ASN1generalizedtime_cmp(ASN1generalizedtime_t* t1, ASN1generalizedtime_t* t2); +WINPR_API int ASN1utctime_cmp(ASN1utctime_t* t1, ASN1utctime_t* t2); + +WINPR_API int ASN1BEREncCharString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char_t* val); +WINPR_API int ASN1DEREncCharString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char_t* val); +WINPR_API int ASN1BEREncChar16String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char16_t* val); +WINPR_API int ASN1DEREncChar16String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char16_t* val); +WINPR_API int ASN1BEREncChar32String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char32_t* val); +WINPR_API int ASN1DEREncChar32String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1char32_t* val); +WINPR_API int ASN1BEREncOctetString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1octet_t* val); +WINPR_API int ASN1DEREncOctetString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t len, ASN1octet_t* val); +WINPR_API int ASN1BEREncBitString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t bitlen, ASN1octet_t* val); +WINPR_API int ASN1DEREncBitString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t bitlen, ASN1octet_t* val); +WINPR_API int ASN1BEREncGeneralizedTime(ASN1encoding_t enc, ASN1uint32_t tag, ASN1generalizedtime_t* val); +WINPR_API int ASN1DEREncGeneralizedTime(ASN1encoding_t enc, ASN1uint32_t tag, ASN1generalizedtime_t* val); +WINPR_API int ASN1BEREncS32(ASN1encoding_t enc, ASN1uint32_t tag, ASN1int32_t val); +WINPR_API int ASN1BEREncSX(ASN1encoding_t enc, ASN1uint32_t tag, ASN1intx_t* val); +WINPR_API int ASN1BEREncZeroMultibyteString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1ztcharstring_t val); +WINPR_API int ASN1DEREncZeroMultibyteString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1ztcharstring_t val); +WINPR_API int ASN1BEREncMultibyteString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1charstring_t* val); +WINPR_API int ASN1DEREncMultibyteString(ASN1encoding_t enc, ASN1uint32_t tag, ASN1charstring_t* val); +WINPR_API int ASN1BEREncNull(ASN1encoding_t enc, ASN1uint32_t tag); +WINPR_API int ASN1BEREncObjectIdentifier(ASN1encoding_t enc, ASN1uint32_t tag, ASN1objectidentifier_t* val); +WINPR_API int ASN1BEREncObjectIdentifier2(ASN1encoding_t enc, ASN1uint32_t tag, ASN1objectidentifier2_t* val); +WINPR_API int ASN1BEREncRemoveZeroBits(ASN1uint32_t* nbits,ASN1octet_t* val); +WINPR_API int ASN1BEREncRemoveZeroBits2(ASN1uint32_t* nbits,ASN1octet_t* val,ASN1uint32_t minlen); +WINPR_API int ASN1BEREncUTCTime(ASN1encoding_t enc, ASN1uint32_t tag, ASN1utctime_t* val); +WINPR_API int ASN1DEREncUTCTime(ASN1encoding_t enc, ASN1uint32_t tag, ASN1utctime_t* val); +WINPR_API int ASN1BEREncFlush(ASN1encoding_t enc); +WINPR_API int ASN1BEREncOpenType(ASN1encoding_t enc, ASN1open_t* val); +WINPR_API int ASN1BERDecExplicitTag(ASN1decoding_t dec, ASN1uint32_t tag, ASN1decoding_t* dd, ASN1octet_t* *ppBufEnd); + +WINPR_API int ASN1BERDecEndOfContents(ASN1decoding_t dec, ASN1decoding_t dd, ASN1octet_t* pBufEnd); +WINPR_API int ASN1BERDecOctetString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1octetstring_t* val); +WINPR_API int ASN1BERDecOctetString2(ASN1decoding_t dec, ASN1uint32_t tag, ASN1octetstring_t* val); +WINPR_API int ASN1BERDecBitString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t* val); +WINPR_API int ASN1BERDecBitString2(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bitstring_t* val); +WINPR_API int ASN1BERDecChar16String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1char16string_t* val); +WINPR_API int ASN1BERDecChar32String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1char32string_t* val); +WINPR_API int ASN1BERDecCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1charstring_t* val); +WINPR_API int ASN1BERDecGeneralizedTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1generalizedtime_t* val); +WINPR_API int ASN1BERDecZeroMultibyteString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t* val); +WINPR_API int ASN1BERDecMultibyteString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1charstring_t* val); +WINPR_API int ASN1BERDecNull(ASN1decoding_t dec, ASN1uint32_t tag); +WINPR_API int ASN1BERDecObjectIdentifier(ASN1decoding_t dec, ASN1uint32_t tag, ASN1objectidentifier_t* val); +WINPR_API int ASN1BERDecObjectIdentifier2(ASN1decoding_t dec, ASN1uint32_t tag, ASN1objectidentifier2_t* val); +WINPR_API int ASN1BERDecS8Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int8_t* val); +WINPR_API int ASN1BERDecS16Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int16_t* val); +WINPR_API int ASN1BERDecS32Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1int32_t* val); +WINPR_API int ASN1BERDecSXVal(ASN1decoding_t dec, ASN1uint32_t tag, ASN1intx_t* val); +WINPR_API int ASN1BERDecU8Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint8_t* val); +WINPR_API int ASN1BERDecU16Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint16_t* val); +WINPR_API int ASN1BERDecU32Val(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint32_t* val); +WINPR_API int ASN1BERDecUTCTime(ASN1decoding_t dec, ASN1uint32_t tag, ASN1utctime_t* val); +WINPR_API int ASN1BERDecZeroCharString(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztcharstring_t* val); +WINPR_API int ASN1BERDecZeroChar16String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztchar16string_t* val); +WINPR_API int ASN1BERDecZeroChar32String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1ztchar32string_t* val); +WINPR_API int ASN1BERDecSkip(ASN1decoding_t dec); +WINPR_API int ASN1BERDecFlush(ASN1decoding_t dec); +WINPR_API int ASN1BERDecOpenType(ASN1decoding_t dec, ASN1open_t* val); +WINPR_API int ASN1BERDecOpenType2(ASN1decoding_t dec, ASN1open_t* val); + +WINPR_API int ASN1BEREncCheck(ASN1encoding_t enc, ASN1uint32_t noctets); +WINPR_API int ASN1BEREncTag(ASN1encoding_t enc, ASN1uint32_t tag); +WINPR_API int ASN1BEREncExplicitTag(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t* pnLenOff); +WINPR_API int ASN1BEREncEndOfContents(ASN1encoding_t enc, ASN1uint32_t nLenOff); +WINPR_API int ASN1BEREncLength(ASN1encoding_t enc, ASN1uint32_t len); + +WINPR_API int ASN1BERDecCheck(ASN1decoding_t dec, ASN1uint32_t len); +WINPR_API int ASN1BERDecTag(ASN1decoding_t dec, ASN1uint32_t tag, ASN1uint32_t* constructed); +WINPR_API int ASN1BERDecLength(ASN1decoding_t dec, ASN1uint32_t* len, ASN1uint32_t* infinite); +WINPR_API int ASN1BERDecNotEndOfContents(ASN1decoding_t dec, ASN1octet_t* pBufEnd); +WINPR_API int ASN1BERDecPeekTag(ASN1decoding_t dec, ASN1uint32_t* tag); + +WINPR_API int ASN1BEREncU32(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t val); +WINPR_API int ASN1BEREncBool(ASN1encoding_t enc, ASN1uint32_t tag, ASN1bool_t val); +WINPR_API int ASN1BERDecBool(ASN1decoding_t dec, ASN1uint32_t tag, ASN1bool_t* val); +WINPR_API int ASN1BEREncEoid(ASN1encoding_t enc, ASN1uint32_t tag, ASN1encodedOID_t* val); +WINPR_API int ASN1BERDecEoid(ASN1decoding_t dec, ASN1uint32_t tag, ASN1encodedOID_t* val); +WINPR_API int ASN1BERDotVal2Eoid(ASN1encoding_t enc, char* pszDotVal, ASN1encodedOID_t* pOut); +WINPR_API int ASN1BEREoid2DotVal(ASN1decoding_t dec, ASN1encodedOID_t* pIn, char** ppszDotVal); +WINPR_API void ASN1BEREoid_free(ASN1encodedOID_t* val); +WINPR_API int ASN1BEREncUTF8String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t length, WCHAR* value); +WINPR_API int ASN1DEREncUTF8String(ASN1encoding_t enc, ASN1uint32_t tag, ASN1uint32_t length, WCHAR* value); +WINPR_API int ASN1BERDecUTF8String(ASN1decoding_t dec, ASN1uint32_t tag, ASN1wstring_t* val); +WINPR_API int ASN1DEREncBeginBlk(ASN1encoding_t enc, ASN1blocktype_e eBlkType, void** ppBlk); +WINPR_API int ASN1DEREncNewBlkElement(void* pBlk, ASN1encoding_t* enc2); +WINPR_API int ASN1DEREncFlushBlkElement(void* pBlk); +WINPR_API int ASN1DEREncEndBlk(void* pBlk); + #endif #endif /* WINPR_ASN1_H */ diff --git a/include/winpr/crt.h b/include/winpr/crt.h index 6bc32dd6c..21abb332a 100644 --- a/include/winpr/crt.h +++ b/include/winpr/crt.h @@ -22,6 +22,7 @@ #include #include +#include #include diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 177734588..3d8d5ea26 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(synch) add_subdirectory(sysinfo) add_subdirectory(bcrypt) add_subdirectory(dsparse) +add_subdirectory(asn1) add_subdirectory(rpc) add_subdirectory(sspicli) add_subdirectory(sspi) diff --git a/winpr/asn1/asn1.c b/winpr/asn1/asn1.c index 0dbff7601..765e1a7b5 100644 --- a/winpr/asn1/asn1.c +++ b/winpr/asn1/asn1.c @@ -19,9 +19,284 @@ #include +#include #ifndef _WIN32 +ASN1module_t ASN1_CreateModule(ASN1uint32_t nVersion, ASN1encodingrule_e eRule, + ASN1uint32_t dwFlags, ASN1uint32_t cPDU, const ASN1GenericFun_t apfnEncoder[], + const ASN1GenericFun_t apfnDecoder[], const ASN1FreeFun_t apfnFreeMemory[], + const ASN1uint32_t acbStructSize[], ASN1magic_t nModuleName) +{ + ASN1module_t module = NULL; + if (!((apfnEncoder) && (apfnDecoder) && (apfnFreeMemory) && (acbStructSize))) + return NULL; + + module = (ASN1module_t) malloc(sizeof(struct tagASN1module_t)); + ZeroMemory(module, sizeof(struct tagASN1module_t)); + + if (module) + { + module->nModuleName = nModuleName; + module->dwFlags = dwFlags; + module->eRule = eRule; + module->cPDUs = cPDU; + module->apfnFreeMemory = apfnFreeMemory; + module->acbStructSize = acbStructSize; + + if (eRule & ASN1_BER_RULE) + { + module->BER.apfnEncoder = (const ASN1BerEncFun_t*) apfnEncoder; + module->BER.apfnDecoder = (const ASN1BerDecFun_t*) apfnDecoder; + } + } + + return module; +} + +void ASN1_CloseModule(ASN1module_t pModule) +{ + if (!pModule) + free(pModule); +} + +ASN1error_e ASN1_CreateEncoder(ASN1module_t pModule, ASN1encoding_t* ppEncoderInfo, + ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize, ASN1encoding_t pParent) +{ + ASN1error_e status; + ASN1encoding_t encoder; + ASN1encodingrule_e rule; + + if (pModule && ppEncoderInfo) + { + *ppEncoderInfo = 0; + encoder = (ASN1encoding_t) malloc(sizeof(struct ASN1encoding_s)); + + if (encoder) + { + ZeroMemory(encoder, sizeof(struct ASN1encoding_s)); + encoder->magic = 0x44434E45; + encoder->err = 0; + encoder->dwFlags = pModule->dwFlags; + encoder->module = pModule; + + if (pbBuf && cbBufSize) + { + encoder->dwFlags |= ASN1ENCODE_SETBUFFER; + encoder->buf = pbBuf; + encoder->pos = pbBuf; + encoder->size = cbBufSize; + } + + if (pParent) + { + encoder[1].magic = (ASN1magic_t) pParent; + rule = pParent->eRule; + } + else + { + encoder[1].magic = (ASN1magic_t) encoder; + rule = pModule->eRule; + } + + encoder->eRule = rule; + + if (encoder->dwFlags & ASN1ENCODE_SETBUFFER) + goto LABEL_SET_BUFFER; + + if (!pParent) + { +LABEL_ENCODER_COMPLETE: + *ppEncoderInfo = encoder; + return 0; + } + + if (rule & ASN1_BER_RULE) + { + //if (ASN1BEREncCheck(encoder, 1)) + { + *encoder->buf = 0; +LABEL_SET_BUFFER: + if (pParent) + pParent[1].version = (ASN1uint32_t) encoder; + + goto LABEL_ENCODER_COMPLETE; + } + + status = ASN1_ERR_MEMORY; + } + else + { + status = ASN1_ERR_RULE; + } + + free(encoder); + } + else + { + status = ASN1_ERR_MEMORY; + } + } + else + { + status = ASN1_ERR_BADARGS; + } + + return status; +} + +ASN1error_e ASN1_Encode(ASN1encoding_t pEncoderInfo, void* pDataStruct, ASN1uint32_t nPduNum, + ASN1uint32_t dwFlags, ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize) +{ + int flags; + ASN1error_e status; + ASN1module_t module; + ASN1BerEncFun_t pfnEncoder; + + if (!pEncoderInfo) + return ASN1_ERR_BADARGS; + + ASN1EncSetError(pEncoderInfo, ASN1_SUCCESS); + + if (dwFlags & 8) + { + pEncoderInfo->dwFlags |= 8; + pEncoderInfo->buf = pbBuf; + pEncoderInfo->pos = pbBuf; + pEncoderInfo->size = cbBufSize; + } + else + { + flags = dwFlags | pEncoderInfo->dwFlags; + + if (flags & 0x10) + { + pEncoderInfo->dwFlags &= 0xFFFFFFF7; + pEncoderInfo->buf = 0; + pEncoderInfo->pos = 0; + pEncoderInfo->size = 0; + } + else + { + if (!(dwFlags & ASN1ENCODE_REUSEBUFFER) && (flags & ASN1ENCODE_APPEND)) + goto LABEL_MODULE; + + pEncoderInfo->pos = pEncoderInfo->buf; + } + } + + pEncoderInfo->len = 0; + pEncoderInfo->bit = 0; + +LABEL_MODULE: + module = pEncoderInfo->module; + + if (nPduNum >= module->cPDUs) + goto LABEL_BAD_PDU; + + if (!(pEncoderInfo->eRule & ASN1_BER_RULE)) + { + status = ASN1_ERR_RULE; + return ASN1EncSetError(pEncoderInfo, status); + } + + pfnEncoder = module->BER.apfnEncoder[nPduNum]; + + if (!pfnEncoder) + { +LABEL_BAD_PDU: + status = ASN1_ERR_BADPDU; + return ASN1EncSetError(pEncoderInfo, status); + } + + if (pfnEncoder(pEncoderInfo, 0, pDataStruct)) + { + //ASN1BEREncFlush(pEncoderInfo); + } + else + { + if (pEncoderInfo[1].err >= 0) + ASN1EncSetError(pEncoderInfo, ASN1_ERR_CORRUPT); + } + + if (pEncoderInfo[1].err < 0) + { + if (((dwFlags & 0xFF) | (pEncoderInfo->dwFlags & 0xFF)) & 0x10) + { + ASN1_FreeEncoded(pEncoderInfo, pEncoderInfo->buf); + pEncoderInfo->buf = 0; + pEncoderInfo->pos = 0; + pEncoderInfo->bit = 0; + pEncoderInfo->len = 0; + pEncoderInfo->size = 0; + } + } + + return pEncoderInfo[1].err; +} + +void ASN1_CloseEncoder(ASN1encoding_t pEncoderInfo) +{ + ASN1magic_t magic; + + if (pEncoderInfo) + { + magic = pEncoderInfo[1].magic; + + if (pEncoderInfo != (ASN1encoding_t) magic) + pEncoderInfo[1].version = 0; + + free(pEncoderInfo); + } +} + +ASN1error_e ASN1EncSetError(ASN1encoding_t enc, ASN1error_e err) +{ + ASN1error_e status; + ASN1encoding_t encoder; + ASN1encoding_t nextEncoder; + + status = err; + encoder = enc; + + while (encoder) + { + nextEncoder = (ASN1encoding_t) &encoder[1]; + + encoder->err = err; + + if (encoder == nextEncoder) + break; + + encoder = nextEncoder; + } + + return status; +} + +ASN1error_e ASN1DecSetError(ASN1decoding_t dec, ASN1error_e err) +{ + ASN1error_e status; + ASN1decoding_t decoder; + ASN1decoding_t nextDecoder; + + status = err; + decoder = dec; + + while (decoder) + { + nextDecoder = (ASN1decoding_t) &decoder[1]; + + decoder->err = err; + + if (decoder == nextDecoder) + break; + + decoder = nextDecoder; + } + + return status; +} #endif