X-Git-Url: https://git.stg.codes/stg.git/blobdiff_plain/b27841d687ec9e84983340b5581376dfb24010ea..b2b89723a2427bba8290bd6967a1ab39cbb630be:/libs/smux/OCTET_STRING_oer.c diff --git a/libs/smux/OCTET_STRING_oer.c b/libs/smux/OCTET_STRING_oer.c new file mode 100644 index 00000000..c16faeaf --- /dev/null +++ b/libs/smux/OCTET_STRING_oer.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2017 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_DISABLE_OER_SUPPORT + +#include +#include +#include + +asn_dec_rval_t +OCTET_STRING_decode_oer(const asn_codec_ctx_t *opt_codec_ctx, + const asn_TYPE_descriptor_t *td, + const asn_oer_constraints_t *constraints, void **sptr, + const void *ptr, size_t size) { + const asn_OCTET_STRING_specifics_t *specs = + td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_SPC_OCTET_STRING_specs; + OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr; + const asn_oer_constraints_t *cts = + constraints ? constraints : td->encoding_constraints.oer_constraints; + ssize_t ct_size = cts ? cts->size : -1; + asn_dec_rval_t rval = {RC_OK, 0}; + size_t expected_length = 0; + + size_t unit_bytes; + switch(specs->subvariant) { + default: + case ASN_OSUBV_BIT: + ASN_DEBUG("Invalid use of OCTET STRING to decode BIT STRING"); + ASN__DECODE_FAILED; + case ASN_OSUBV_ANY: + /* Fall through */ + case ASN_OSUBV_STR: + unit_bytes = 1; + break; + case ASN_OSUBV_U16: + unit_bytes = 2; + break; + case ASN_OSUBV_U32: + unit_bytes = 4; + break; + } + + (void)opt_codec_ctx; + + if(!st) { + st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); + if(!st) ASN__DECODE_FAILED; + } + + if(ct_size >= 0) { + expected_length = unit_bytes * ct_size; + } else { + /* + * X.696 (08/2015) #27.2 + * Encode length determinant as _number of octets_, but only + * if upper bound is not equal to lower bound. + */ + ssize_t len_len = oer_fetch_length(ptr, size, &expected_length); + if(len_len > 0) { + rval.consumed = len_len; + ptr = (const char *)ptr + len_len; + size -= len_len; + } else if(len_len == 0) { + ASN__DECODE_STARVED; + } else if(len_len < 0) { + ASN__DECODE_FAILED; + } + + if(expected_length % unit_bytes != 0) { + ASN_DEBUG( + "Data size %" ASN_PRI_SIZE " bytes is not consistent with multiplier %" ASN_PRI_SIZE "", + expected_length, unit_bytes); + ASN__DECODE_FAILED; + } + } + + if(size < expected_length) { + ASN__DECODE_STARVED; + } else { + uint8_t *buf = MALLOC(expected_length + 1); + if(buf == NULL) { + ASN__DECODE_FAILED; + } else { + memcpy(buf, ptr, expected_length); + buf[expected_length] = '\0'; + } + FREEMEM(st->buf); + st->buf = buf; + st->size = expected_length; + + rval.consumed += expected_length; + return rval; + } +} + +/* + * Encode as Canonical OER. + */ +asn_enc_rval_t +OCTET_STRING_encode_oer(const asn_TYPE_descriptor_t *td, + const asn_oer_constraints_t *constraints, + const void *sptr, asn_app_consume_bytes_f *cb, + void *app_key) { + const asn_OCTET_STRING_specifics_t *specs = + td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_SPC_OCTET_STRING_specs; + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + const asn_oer_constraints_t *cts = + constraints ? constraints : td->encoding_constraints.oer_constraints; + ssize_t ct_size = cts ? cts->size : -1; + asn_enc_rval_t er = {0, 0, 0}; + + if(!st) ASN__ENCODE_FAILED; + + ASN_DEBUG("Encoding %s %" ASN_PRI_SIZE " as OCTET STRING", td ? td->name : "", st->size); + + if(ct_size >= 0) { + /* + * Check that available data matches the constraint + */ + size_t unit_bytes; + switch(specs->subvariant) { + default: + case ASN_OSUBV_BIT: + ASN_DEBUG("Invalid use of OCTET STRING to encode BIT STRING"); + ASN__ENCODE_FAILED; + case ASN_OSUBV_ANY: + /* Fall through */ + case ASN_OSUBV_STR: + unit_bytes = 1; + break; + case ASN_OSUBV_U16: + unit_bytes = 2; + break; + case ASN_OSUBV_U32: + unit_bytes = 4; + break; + } + + if(st->size != unit_bytes * (size_t)ct_size) { + ASN_DEBUG( + "Trying to encode %s (%" ASN_PRI_SIZE " bytes) which doesn't fit SIZE " + "constraint (%" ASN_PRI_SIZE ")", + td->name, st->size, ct_size); + ASN__ENCODE_FAILED; + } + } else { + /* + * X.696 (08/2015) #27.2 + * Encode length determinant as _number of octets_, but only + * if upper bound is not equal to lower bound. + */ + ssize_t ret = oer_serialize_length(st->size, cb, app_key); + if(ret < 0) { + ASN__ENCODE_FAILED; + } + er.encoded += ret; + } + + er.encoded += st->size; + if(cb(st->buf, st->size, app_key) < 0) { + ASN__ENCODE_FAILED; + } else { + ASN__ENCODED_OK(er); + } +} + +#endif /* ASN_DISABLE_OER_SUPPORT */