diff options
Diffstat (limited to 'skeletons/RELATIVE-OID.c')
-rw-r--r-- | skeletons/RELATIVE-OID.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c new file mode 100644 index 00000000..f6572105 --- /dev/null +++ b/skeletons/RELATIVE-OID.c @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include <RELATIVE-OID.h> +#include <assert.h> +#include <errno.h> + +/* + * RELATIVE-OID basic type description. + */ +static ber_tlv_tag_t asn1_DEF_RELATIVE_OID_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (13 << 2)) +}; +asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = { + "RELATIVE-OID", + asn_generic_no_constraint, + INTEGER_decode_ber, /* Implemented in terms of INTEGER type */ + OBJECT_IDENTIFIER_encode_der, + RELATIVE_OID_print, + INTEGER_free, + 0, /* Use generic outmost tag fetcher */ + asn1_DEF_RELATIVE_OID_tags, + sizeof(asn1_DEF_RELATIVE_OID_tags) + / sizeof(asn1_DEF_RELATIVE_OID_tags[0]), + 1, /* Single UNIVERSAL tag may be implicitly overriden */ + 0 /* Always in primitive form */ +}; + +int +RELATIVE_OID_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const RELATIVE_OID_t *st = sptr; + int startn; + int i; + + if(!st || !st->buf) + return cb("<absent>", 8, app_key); + + /* Dump preamble */ + if(cb("{ ", 2, app_key)) + return -1; + + for(i = 0, startn = 0; i < st->size; i++) { + uint8_t b = st->buf[i]; + if((b & 0x80)) /* Continuation expected */ + continue; + if(startn && cb(" ", 1, app_key)) /* Separate arcs */ + return -1; + if(OBJECT_IDENTIFIER_print_arc(&st->buf[startn], + i - startn + 1, 0, cb, app_key)) + return -1; + startn = i + 1; + } + + return cb(" }", 2, app_key); +} + + +int +RELATIVE_OID_get_arcs_l(RELATIVE_OID_t *roid, + unsigned long *arcs, int arcs_slots) { + unsigned long arc_value; + int cur_arc = 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(cur_arc < arcs_slots) { + if(OBJECT_IDENTIFIER_get_arc_l(&roid->buf[startn], + i - startn + 1, 0, &arc_value)) + return -1; + arcs[cur_arc++] = arc_value; + } + + startn = i + 1; + } + + return cur_arc; +} + +int +RELATIVE_OID_set_arcs_l(RELATIVE_OID_t *roid, unsigned long *arcs, int arcs_slots) { + uint8_t *buf; + uint8_t *bp; + int size; + int i; + + if(roid == NULL || arcs == NULL || arcs_slots < 0) { + errno = EINVAL; + return -1; + } + + /* + * Roughly estimate the maximum size necessary to encode these arcs. + */ + size = ((sizeof(arcs[0]) + 1) * 8 / 7) * arcs_slots; + bp = buf = MALLOC(size + 1); + if(!buf) { + /* ENOMEM */ + return -1; + } + + /* + * Encode the arcs and refine the encoding size. + */ + size = 0; + for(i = 0; i < arcs_slots; i++) { + unsigned long value = arcs[i]; + uint8_t tbuf[sizeof(value) * 2]; /* Conservatively sized */ + uint8_t *tp = tbuf; + int arc_len = 0; + int add; + + for(add = 1; value; value >>= 7, add++) { + unsigned int b7 = value & 0x7F; + *tp++ = 0x80 | b7; + if(b7) { + arc_len += add; + add = 0; + } + } + + if(arc_len) { + tp = &tbuf[arc_len - 1]; + /* The last octet does not have bit 8 set. */ + *tbuf &= 0x7f; + for(; tp >= tbuf; tp--) + *bp++ = *tp; + size += arc_len; + } else { + *bp++ = 0; + size++; + } + } + + /* + * Replace buffer. + */ + roid->size = size; + bp = roid->buf; + roid->buf = buf; + if(bp) FREEMEM(bp); + + return 0; +} |