/*- * Copyright (c) 2003, 2004, 2005 Lev Walkin . * All rights reserved. * Redistribution and modifications are permitted subject to BSD license. */ #include #include #include #include /* Encoder and decoder of a primitive type */ #include /* for CHAR_BIT */ #include /* * RELATIVE-OID basic type description. */ static ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = { (ASN_TAG_CLASS_UNIVERSAL | (13 << 2)) }; asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = { "RELATIVE-OID", "RELATIVE_OID", ASN__PRIMITIVE_TYPE_free, RELATIVE_OID_print, asn_generic_no_constraint, ber_decode_primitive, der_encode_primitive, RELATIVE_OID_decode_xer, RELATIVE_OID_encode_xer, OCTET_STRING_decode_uper, OCTET_STRING_encode_uper, 0, /* Use generic outmost tag fetcher */ asn_DEF_RELATIVE_OID_tags, sizeof(asn_DEF_RELATIVE_OID_tags) / sizeof(asn_DEF_RELATIVE_OID_tags[0]), asn_DEF_RELATIVE_OID_tags, /* Same as above */ sizeof(asn_DEF_RELATIVE_OID_tags) / sizeof(asn_DEF_RELATIVE_OID_tags[0]), 0, /* No PER visible constraints */ 0, 0, /* No members */ 0 /* No specifics */ }; static ssize_t RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) { ssize_t wrote = 0; ssize_t ret; int startn; int i; for(i = 0, startn = 0; i < st->size; i++) { uint8_t b = st->buf[i]; if((b & 0x80)) /* Continuation expected */ continue; if(startn) { /* Separate arcs */ if(cb(".", 1, app_key) < 0) return -1; wrote++; } ret = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn], i - startn + 1, 0, cb, app_key); if(ret < 0) return -1; wrote += ret; startn = i + 1; } return wrote; } int RELATIVE_OID_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr; (void)td; /* Unused argument */ (void)ilevel; /* Unused argument */ if(!st || !st->buf) return (cb("", 8, app_key) < 0) ? -1 : 0; /* Dump preamble */ if(cb("{ ", 2, app_key) < 0) return -1; if(RELATIVE_OID__dump_body(st, cb, app_key) < 0) return -1; return (cb(" }", 2, app_key) < 0) ? -1 : 0; } static enum xer_pbd_rval RELATIVE_OID__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr; const char *chunk_end = (const char *)chunk_buf + chunk_size; const char *endptr; long s_arcs[6]; long *arcs = s_arcs; int arcs_count; int ret; (void)td; arcs_count = OBJECT_IDENTIFIER_parse_arcs( (const char *)chunk_buf, chunk_size, arcs, sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr); if(arcs_count < 0) { /* Expecting at least zero arcs */ return XPBD_BROKEN_ENCODING; } if(endptr < chunk_end) { /* We have a tail of unrecognized data. Check its safety. */ if(!xer_is_whitespace(endptr, chunk_end - endptr)) return XPBD_BROKEN_ENCODING; } if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) { arcs = (long *)MALLOC(arcs_count * sizeof(long)); if(!arcs) return XPBD_SYSTEM_FAILURE; ret = OBJECT_IDENTIFIER_parse_arcs( (const char *)chunk_buf, chunk_size, arcs, arcs_count, &endptr); if(ret != arcs_count) return XPBD_SYSTEM_FAILURE; /* assert?.. */ } /* * Convert arcs into BER representation. */ ret = RELATIVE_OID_set_arcs(st, arcs, sizeof(*arcs), arcs_count); if(arcs != s_arcs) FREEMEM(arcs); return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED; } asn_dec_rval_t RELATIVE_OID_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, const void *buf_ptr, size_t size) { return xer_decode_primitive(opt_codec_ctx, td, sptr, sizeof(RELATIVE_OID_t), opt_mname, buf_ptr, size, RELATIVE_OID__xer_body_decode); } asn_enc_rval_t RELATIVE_OID_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, int ilevel, enum xer_encoder_flags_e flags, asn_app_consume_bytes_f *cb, void *app_key) { RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr; asn_enc_rval_t er; (void)ilevel; /* Unused argument */ (void)flags; /* Unused argument */ if(!st || !st->buf) _ASN_ENCODE_FAILED; er.encoded = RELATIVE_OID__dump_body(st, cb, app_key); if(er.encoded < 0) _ASN_ENCODE_FAILED; _ASN_ENCODED_OK(er); } int RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arc_slots) { void *arcs_end = (char *)arcs + (arc_slots * arc_type_size); int num_arcs = 0; int startn = 0; int i; if(!roid || !roid->buf) { errno = EINVAL; return -1; } for(i = 0; i < roid->size; i++) { uint8_t b = roid->buf[i]; if((b & 0x80)) /* Continuation expected */ continue; if(arcs < arcs_end) { if(OBJECT_IDENTIFIER_get_single_arc( &roid->buf[startn], i - startn + 1, 0, arcs, arc_type_size)) return -1; arcs = ((char *)arcs) + arc_type_size; num_arcs++; } startn = i + 1; } return num_arcs; } int RELATIVE_OID_set_arcs(RELATIVE_OID_t *roid, void *arcs, unsigned int arc_type_size, unsigned int arcs_slots) { uint8_t *buf; uint8_t *bp; unsigned int size; unsigned int i; if(roid == NULL || arcs == NULL || arc_type_size < 1) { errno = EINVAL; return -1; } /* * Roughly estimate the maximum size necessary to encode these arcs. */ size = ((arc_type_size * CHAR_BIT + 6) / 7) * arcs_slots; bp = buf = (uint8_t *)MALLOC(size + 1); if(!buf) { /* ENOMEM */ return -1; } /* * Encode the arcs. */ for(i = 0; i < arcs_slots; i++, arcs = ((char *)arcs) + arc_type_size) { bp += OBJECT_IDENTIFIER_set_single_arc(bp, arcs, arc_type_size, 0); } assert((unsigned)(bp - buf) <= size); /* * Replace buffer. */ roid->size = (int)(bp - buf); bp = roid->buf; roid->buf = buf; if(bp) FREEMEM(bp); return 0; }