326 lines
6.5 KiB
C
326 lines
6.5 KiB
C
/**
|
|
* WinPR: Windows Portable Runtime
|
|
* ASN.1 Encoding & Decoding Engine
|
|
*
|
|
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <winpr/asn1.h>
|
|
|
|
#include <winpr/crt.h>
|
|
|
|
#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) calloc(1, 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)
|
|
{
|
|
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) calloc(1, sizeof(struct ASN1encoding_s));
|
|
|
|
if (encoder)
|
|
{
|
|
encoder->magic = 0x44434E45;
|
|
encoder->err = ASN1_SUCCESS;
|
|
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 ASN1_SUCCESS;
|
|
}
|
|
|
|
if (rule & ASN1_BER_RULE)
|
|
{
|
|
//if (ASN1BEREncCheck(encoder, 1))
|
|
{
|
|
if (encoder->buf)
|
|
*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;
|
|
}
|
|
|
|
void ASN1_FreeEncoded(ASN1encoding_t pEncoderInfo, void* pBuf)
|
|
{
|
|
return;
|
|
}
|
|
|
|
void ASN1_FreeDecoded(ASN1decoding_t pDecoderInfo, void* pDataStruct, ASN1uint32_t nPduNum)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ASN1error_e ASN1_CreateDecoder(ASN1module_t pModule, ASN1decoding_t* ppDecoderInfo,
|
|
ASN1octet_t* pbBuf, ASN1uint32_t cbBufSize, ASN1decoding_t pParent)
|
|
{
|
|
return ASN1_ERR_BADARGS;
|
|
}
|
|
|
|
ASN1error_e ASN1_Decode(ASN1decoding_t pDecoderInfo,void **ppDataStruct,ASN1uint32_t nPduNum,ASN1uint32_t dwFlags,ASN1octet_t *pbBuf,ASN1uint32_t cbBufSize)
|
|
{
|
|
return ASN1_ERR_BADARGS;
|
|
}
|
|
|
|
#endif
|