/*- * Copyright (c) 2003-2017 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include #include /* * OCTET STRING basic type description. */ static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) }; asn_OCTET_STRING_specifics_t asn_SPC_OCTET_STRING_specs = { sizeof(OCTET_STRING_t), offsetof(OCTET_STRING_t, _asn_ctx), ASN_OSUBV_STR }; asn_TYPE_operation_t asn_OP_OCTET_STRING = { OCTET_STRING_free, #if !defined(ASN_DISABLE_PRINT_SUPPORT) OCTET_STRING_print, /* OCTET STRING generally means a non-ascii sequence */ #else 0, #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */ OCTET_STRING_compare, #if !defined(ASN_DISABLE_BER_SUPPORT) OCTET_STRING_decode_ber, OCTET_STRING_encode_der, #else 0, 0, #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */ #if !defined(ASN_DISABLE_XER_SUPPORT) OCTET_STRING_decode_xer_hex, OCTET_STRING_encode_xer, #else 0, 0, #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */ #if !defined(ASN_DISABLE_JER_SUPPORT) OCTET_STRING_encode_jer, #else 0, #endif /* !defined(ASN_DISABLE_JER_SUPPORT) */ #if !defined(ASN_DISABLE_OER_SUPPORT) OCTET_STRING_decode_oer, OCTET_STRING_encode_oer, #else 0, 0, #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */ #if !defined(ASN_DISABLE_UPER_SUPPORT) OCTET_STRING_decode_uper, /* Unaligned PER decoder */ OCTET_STRING_encode_uper, /* Unaligned PER encoder */ #else 0, 0, #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */ #if !defined(ASN_DISABLE_APER_SUPPORT) OCTET_STRING_decode_aper, /* Aligned PER decoder */ OCTET_STRING_encode_aper, /* Aligned PER encoder */ #else 0, 0, #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */ #if !defined(ASN_DISABLE_RFILL_SUPPORT) OCTET_STRING_random_fill, #else 0, #endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */ 0 /* Use generic outmost tag fetcher */ }; asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { "OCTET STRING", /* Canonical name */ "OCTET_STRING", /* XML tag name */ &asn_OP_OCTET_STRING, asn_DEF_OCTET_STRING_tags, sizeof(asn_DEF_OCTET_STRING_tags) / sizeof(asn_DEF_OCTET_STRING_tags[0]), asn_DEF_OCTET_STRING_tags, /* Same as above */ sizeof(asn_DEF_OCTET_STRING_tags) / sizeof(asn_DEF_OCTET_STRING_tags[0]), { #if !defined(ASN_DISABLE_OER_SUPPORT) 0, #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */ #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) 0, #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */ asn_generic_no_constraint }, 0, 0, /* No members */ &asn_SPC_OCTET_STRING_specs }; void OCTET_STRING_free(const asn_TYPE_descriptor_t *td, void *sptr, enum asn_struct_free_method method) { OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; if(!td || !st) return; ASN_DEBUG("Freeing %s as OCTET STRING", td->name); if(st->buf) { FREEMEM(st->buf); st->buf = 0; } #if !defined(ASN_DISABLE_BER_SUPPORT) const asn_OCTET_STRING_specifics_t *specs; asn_struct_ctx_t *ctx; specs = td->specifics ? (const asn_OCTET_STRING_specifics_t *)td->specifics : &asn_SPC_OCTET_STRING_specs; ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); /* * Remove decode-time stack. */ struct _stack *stck; stck = (struct _stack *)ctx->ptr; if(stck) { while(stck->tail) { struct _stack_el *sel = stck->tail; stck->tail = sel->prev; FREEMEM(sel); } FREEMEM(stck); } #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */ switch(method) { case ASFM_FREE_EVERYTHING: FREEMEM(sptr); break; case ASFM_FREE_UNDERLYING: break; case ASFM_FREE_UNDERLYING_AND_RESET: memset(sptr, 0, td->specifics ? ((const asn_OCTET_STRING_specifics_t *)(td->specifics)) ->struct_size : sizeof(OCTET_STRING_t)); break; } } /* * Conversion routines. */ int OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) { void *buf; if(st == 0 || (str == 0 && len)) { errno = EINVAL; return -1; } /* * Clear the OCTET STRING. */ if(str == NULL) { FREEMEM(st->buf); st->buf = 0; st->size = 0; return 0; } /* Determine the original string size, if not explicitly given */ if(len < 0) len = strlen(str); /* Allocate and fill the memory */ buf = MALLOC(len + 1); if(buf == NULL) return -1; memcpy(buf, str, len); ((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */ FREEMEM(st->buf); st->buf = (uint8_t *)buf; st->size = len; return 0; } OCTET_STRING_t * OCTET_STRING_new_fromBuf(const asn_TYPE_descriptor_t *td, const char *str, int len) { 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; st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size); if(st && str && OCTET_STRING_fromBuf(st, str, len)) { FREEMEM(st); st = NULL; } return st; } /* * Lexicographically compare the common prefix of both strings, * and if it is the same return -1 for the smallest string. */ int OCTET_STRING_compare(const asn_TYPE_descriptor_t *td, const void *aptr, const void *bptr) { const asn_OCTET_STRING_specifics_t *specs = td->specifics; const OCTET_STRING_t *a = aptr; const OCTET_STRING_t *b = bptr; (void)specs; assert(!specs || specs->subvariant != ASN_OSUBV_BIT); if(a && b) { size_t common_prefix_size = a->size <= b->size ? a->size : b->size; int ret = memcmp(a->buf, b->buf, common_prefix_size); if(ret == 0) { /* Figure out which string with equal prefixes is longer. */ if(a->size < b->size) { return -1; } else if(a->size > b->size) { return 1; } else { return 0; } } else { return ret < 0 ? -1 : 1; } } else if(!a && !b) { return 0; } else if(!a) { return -1; } else { return 1; } } #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) int OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf, size_t units, unsigned int bpc, unsigned int unit_bits, long lb, long ub, const asn_per_constraints_t *pc) { uint8_t *end = buf + units * bpc; ASN_DEBUG("Expanding %d characters into (%ld..%ld):%d", (int)units, lb, ub, unit_bits); /* X.691: 27.5.4 */ if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) { /* Decode without translation */ lb = 0; } else if(pc && pc->code2value) { if(unit_bits > 16) return 1; /* FATAL: can't have constrained * UniversalString with more than * 16 million code points */ for(; buf < end; buf += bpc) { int value; int code = per_get_few_bits(po, unit_bits); if(code < 0) return -1; /* WMORE */ value = pc->code2value(code); if(value < 0) { ASN_DEBUG("Code %d (0x%02x) is" " not in map (%ld..%ld)", code, code, lb, ub); return 1; /* FATAL */ } switch(bpc) { case 1: *buf = value; break; case 2: buf[0] = value >> 8; buf[1] = value; break; case 4: buf[0] = value >> 24; buf[1] = value >> 16; buf[2] = value >> 8; buf[3] = value; break; } } return 0; } /* Shortcut the no-op copying to the aligned structure */ if(lb == 0 && (unit_bits == 8 * bpc)) { return per_get_many_bits(po, buf, 0, unit_bits * units); } for(; buf < end; buf += bpc) { int32_t code = per_get_few_bits(po, unit_bits); int32_t ch = code + lb; if(code < 0) return -1; /* WMORE */ if(ch > ub) { ASN_DEBUG("Code %d is out of range (%ld..%ld)", ch, lb, ub); return 1; /* FATAL */ } switch(bpc) { case 1: *buf = ch; break; case 2: buf[0] = ch >> 8; buf[1] = ch; break; case 4: buf[0] = ch >> 24; buf[1] = ch >> 16; buf[2] = ch >> 8; buf[3] = ch; break; } } return 0; } int OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf, size_t units, unsigned int bpc, unsigned int unit_bits, long lb, long ub, const asn_per_constraints_t *pc) { const uint8_t *end = buf + units * bpc; ASN_DEBUG("Squeezing %d characters into (%ld..%ld):%d (%d bpc)", (int)units, lb, ub, unit_bits, bpc); /* X.691: 27.5.4 */ if((unsigned long)ub <= ((unsigned long)2 << (unit_bits - 1))) { /* Encode as is */ lb = 0; } else if(pc && pc->value2code) { for(; buf < end; buf += bpc) { int code; uint32_t value; switch(bpc) { case 1: value = *(const uint8_t *)buf; break; case 2: value = (buf[0] << 8) | buf[1]; break; case 4: value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; break; default: return -1; } code = pc->value2code(value); if(code < 0) { ASN_DEBUG("Character %d (0x%02x) is" " not in map (%ld..%ld)", *buf, *buf, lb, ub); return -1; } if(per_put_few_bits(po, code, unit_bits)) return -1; } } /* Shortcut the no-op copying to the aligned structure */ if(lb == 0 && (unit_bits == 8 * bpc)) { return per_put_many_bits(po, buf, unit_bits * units); } for(ub -= lb; buf < end; buf += bpc) { int ch; uint32_t value; switch(bpc) { case 1: value = *(const uint8_t *)buf; break; case 2: value = (buf[0] << 8) | buf[1]; break; case 4: value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; break; default: return -1; } ch = value - lb; if(ch < 0 || ch > ub) { ASN_DEBUG("Character %d (0x%02x) is out of range (%ld..%ld)", *buf, value, lb, ub + lb); return -1; } if(per_put_few_bits(po, ch, unit_bits)) return -1; } return 0; } #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */