blob: 37f557d788d21e699e1f2e3b8891ad50dab66278 [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001/*-
2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <RELATIVE-OID.h>
6#include <assert.h>
7#include <errno.h>
8
9/*
10 * RELATIVE-OID basic type description.
11 */
12static ber_tlv_tag_t asn1_DEF_RELATIVE_OID_tags[] = {
13 (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
14};
15asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = {
16 "RELATIVE-OID",
17 asn_generic_no_constraint,
18 INTEGER_decode_ber, /* Implemented in terms of INTEGER type */
19 OBJECT_IDENTIFIER_encode_der,
20 RELATIVE_OID_print,
21 INTEGER_free,
22 0, /* Use generic outmost tag fetcher */
23 asn1_DEF_RELATIVE_OID_tags,
24 sizeof(asn1_DEF_RELATIVE_OID_tags)
25 / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
26 1, /* Single UNIVERSAL tag may be implicitly overriden */
vlmb42843a2004-06-05 08:17:50 +000027 0, /* Always in primitive form */
28 0 /* No specifics */
vlmfa67ddc2004-06-03 03:38:44 +000029};
30
31int
32RELATIVE_OID_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
33 asn_app_consume_bytes_f *cb, void *app_key) {
34 const RELATIVE_OID_t *st = sptr;
35 int startn;
36 int i;
37
vlmb42843a2004-06-05 08:17:50 +000038 (void)td; /* Unused argument */
39 (void)ilevel; /* Unused argument */
40
vlmfa67ddc2004-06-03 03:38:44 +000041 if(!st || !st->buf)
42 return cb("<absent>", 8, app_key);
43
44 /* Dump preamble */
45 if(cb("{ ", 2, app_key))
46 return -1;
47
48 for(i = 0, startn = 0; i < st->size; i++) {
49 uint8_t b = st->buf[i];
50 if((b & 0x80)) /* Continuation expected */
51 continue;
52 if(startn && cb(" ", 1, app_key)) /* Separate arcs */
53 return -1;
54 if(OBJECT_IDENTIFIER_print_arc(&st->buf[startn],
55 i - startn + 1, 0, cb, app_key))
56 return -1;
57 startn = i + 1;
58 }
59
60 return cb(" }", 2, app_key);
61}
62
63
64int
vlm2e3dd3b2004-06-14 07:24:36 +000065RELATIVE_OID_get_arcs(RELATIVE_OID_t *roid,
66 void *arcs, unsigned int arc_type_size, unsigned int arc_slots) {
67 void *arcs_end = arcs + (arc_slots * arc_type_size);
68 int num_arcs = 0;
vlmfa67ddc2004-06-03 03:38:44 +000069 int startn = 0;
70 int i;
71
72 if(!roid || !roid->buf) {
73 errno = EINVAL;
74 return -1;
75 }
76
77 for(i = 0; i < roid->size; i++) {
78 uint8_t b = roid->buf[i];
79 if((b & 0x80)) /* Continuation expected */
80 continue;
81
vlm2e3dd3b2004-06-14 07:24:36 +000082 if(arcs < arcs_end) {
83 if(OBJECT_IDENTIFIER_get_single_arc(
84 &roid->buf[startn],
85 i - startn + 1, 0,
86 arcs, arc_type_size))
vlmfa67ddc2004-06-03 03:38:44 +000087 return -1;
vlm2e3dd3b2004-06-14 07:24:36 +000088 arcs += arc_type_size;
89 num_arcs++;
vlmfa67ddc2004-06-03 03:38:44 +000090 }
91
92 startn = i + 1;
93 }
94
vlm2e3dd3b2004-06-14 07:24:36 +000095 return num_arcs;
vlmfa67ddc2004-06-03 03:38:44 +000096}
97
98int
99RELATIVE_OID_set_arcs_l(RELATIVE_OID_t *roid, unsigned long *arcs, int arcs_slots) {
100 uint8_t *buf;
101 uint8_t *bp;
102 int size;
103 int i;
104
105 if(roid == NULL || arcs == NULL || arcs_slots < 0) {
106 errno = EINVAL;
107 return -1;
108 }
109
110 /*
111 * Roughly estimate the maximum size necessary to encode these arcs.
112 */
113 size = ((sizeof(arcs[0]) + 1) * 8 / 7) * arcs_slots;
114 bp = buf = MALLOC(size + 1);
115 if(!buf) {
116 /* ENOMEM */
117 return -1;
118 }
119
120 /*
121 * Encode the arcs and refine the encoding size.
122 */
123 size = 0;
124 for(i = 0; i < arcs_slots; i++) {
125 unsigned long value = arcs[i];
126 uint8_t tbuf[sizeof(value) * 2]; /* Conservatively sized */
127 uint8_t *tp = tbuf;
128 int arc_len = 0;
129 int add;
130
131 for(add = 1; value; value >>= 7, add++) {
132 unsigned int b7 = value & 0x7F;
133 *tp++ = 0x80 | b7;
134 if(b7) {
135 arc_len += add;
136 add = 0;
137 }
138 }
139
140 if(arc_len) {
141 tp = &tbuf[arc_len - 1];
142 /* The last octet does not have bit 8 set. */
143 *tbuf &= 0x7f;
144 for(; tp >= tbuf; tp--)
145 *bp++ = *tp;
146 size += arc_len;
147 } else {
148 *bp++ = 0;
149 size++;
150 }
151 }
152
153 /*
154 * Replace buffer.
155 */
156 roid->size = size;
157 bp = roid->buf;
158 roid->buf = buf;
159 if(bp) FREEMEM(bp);
160
161 return 0;
162}