blob: 2f6295b192e4f0c107ee9e03f3c76bbc41aedaf4 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*-
Lev Walkina5972be2017-09-29 23:15:58 -07002 * Copyright (c) 2003-2017 Lev Walkin <vlm@lionet.info>.
Lev Walkin2c34aad2005-03-10 11:50:24 +00003 * All rights reserved.
Lev Walkinf15320b2004-06-03 03:38:44 +00004 * Redistribution and modifications are permitted subject to BSD license.
5 */
Lev Walkina9cc46e2004-09-22 16:06:28 +00006#include <asn_internal.h>
Lev Walkinf15320b2004-06-03 03:38:44 +00007#include <RELATIVE-OID.h>
Lev Walkin725883b2006-10-09 12:07:58 +00008#include <OCTET_STRING.h>
Lev Walkin3256d6f2004-10-21 11:22:12 +00009#include <asn_codecs_prim.h> /* Encoder and decoder of a primitive type */
Lev Walkin0787ff02004-06-17 23:43:39 +000010#include <limits.h> /* for CHAR_BIT */
Lev Walkinf15320b2004-06-03 03:38:44 +000011#include <errno.h>
12
13/*
14 * RELATIVE-OID basic type description.
15 */
Wim Lewis18c2ec92014-07-29 11:30:10 -070016static const ber_tlv_tag_t asn_DEF_RELATIVE_OID_tags[] = {
Lev Walkinf15320b2004-06-03 03:38:44 +000017 (ASN_TAG_CLASS_UNIVERSAL | (13 << 2))
18};
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080019asn_TYPE_operation_t asn_OP_RELATIVE_OID = {
Lev Walkin8e8078a2004-09-26 13:10:40 +000020 ASN__PRIMITIVE_TYPE_free,
Lev Walkina9cc46e2004-09-22 16:06:28 +000021 RELATIVE_OID_print,
Lev Walkincd2f48e2017-08-10 02:14:59 -070022 OCTET_STRING_compare, /* Implemented in terms of opaque comparison */
Lev Walkin8e8078a2004-09-26 13:10:40 +000023 ber_decode_primitive,
24 der_encode_primitive,
Lev Walkin92302252004-10-23 10:16:51 +000025 RELATIVE_OID_decode_xer,
Lev Walkina9cc46e2004-09-22 16:06:28 +000026 RELATIVE_OID_encode_xer,
Lev Walkincc159472017-07-06 08:26:36 -070027#ifdef ASN_DISABLE_OER_SUPPORT
28 0,
29 0,
30#else
Lev Walkinb5b524b2017-10-13 03:14:03 -070031 RELATIVE_OID_decode_oer,
32 RELATIVE_OID_encode_oer,
Lev Walkincc159472017-07-06 08:26:36 -070033#endif /* ASN_DISABLE_OER_SUPPORT */
Lev Walkinb33425f2017-07-14 14:59:52 +040034#ifdef ASN_DISABLE_PER_SUPPORT
35 0,
36 0,
37#else
38 OCTET_STRING_decode_uper,
39 OCTET_STRING_encode_uper,
40#endif /* ASN_DISABLE_PER_SUPPORT */
Lev Walkina5972be2017-09-29 23:15:58 -070041 RELATIVE_OID_random_fill,
Bi-Ruei, Chiu1f87ac02017-08-20 01:25:45 +080042 0 /* Use generic outmost tag fetcher */
43};
44asn_TYPE_descriptor_t asn_DEF_RELATIVE_OID = {
45 "RELATIVE-OID",
46 "RELATIVE_OID",
47 &asn_OP_RELATIVE_OID,
Lev Walkin5e033762004-09-29 13:26:15 +000048 asn_DEF_RELATIVE_OID_tags,
49 sizeof(asn_DEF_RELATIVE_OID_tags)
50 / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
51 asn_DEF_RELATIVE_OID_tags, /* Same as above */
52 sizeof(asn_DEF_RELATIVE_OID_tags)
53 / sizeof(asn_DEF_RELATIVE_OID_tags[0]),
Lev Walkina5972be2017-09-29 23:15:58 -070054 { 0, 0, asn_generic_no_constraint },
Lev Walkin449f8322004-08-20 13:23:42 +000055 0, 0, /* No members */
Lev Walkind9bd7752004-06-05 08:17:50 +000056 0 /* No specifics */
Lev Walkinf15320b2004-06-03 03:38:44 +000057};
58
Lev Walkina9cc46e2004-09-22 16:06:28 +000059static ssize_t
60RELATIVE_OID__dump_body(const RELATIVE_OID_t *st, asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin588bf0f2017-10-13 23:51:16 -070061 char scratch[32];
62 size_t produced = 0;
63 size_t off = 0;
Lev Walkina9cc46e2004-09-22 16:06:28 +000064
Lev Walkin588bf0f2017-10-13 23:51:16 -070065 for(;;) {
66 asn_oid_arc_t arc;
67 ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
68 st->size - off, &arc);
69 if(rd < 0) {
70 return -1;
71 } else if(rd == 0) {
72 /* No more arcs. */
73 break;
74 } else {
75 int ret = snprintf(scratch, sizeof(scratch), "%s%" PRIu32,
76 off ? "." : "", arc);
77 if(ret >= (ssize_t)sizeof(scratch)) {
78 return -1;
79 }
80 produced += ret;
81 off += rd;
82 assert(off <= st->size);
83 if(cb(scratch, ret, app_key) < 0) return -1;
84 }
85 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000086
Lev Walkin588bf0f2017-10-13 23:51:16 -070087 if(off != st->size) {
88 ASN_DEBUG("Could not scan to the end of Object Identifier");
89 return -1;
90 }
Lev Walkina9cc46e2004-09-22 16:06:28 +000091
Lev Walkin588bf0f2017-10-13 23:51:16 -070092 return produced;
Lev Walkina9cc46e2004-09-22 16:06:28 +000093}
94
Lev Walkinf15320b2004-06-03 03:38:44 +000095int
Lev Walkin20696a42017-10-17 21:27:33 -070096RELATIVE_OID_print(const asn_TYPE_descriptor_t *td, const void *sptr,
97 int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
98 const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
Lev Walkinf15320b2004-06-03 03:38:44 +000099
Lev Walkind9bd7752004-06-05 08:17:50 +0000100 (void)td; /* Unused argument */
101 (void)ilevel; /* Unused argument */
102
Lev Walkinf15320b2004-06-03 03:38:44 +0000103 if(!st || !st->buf)
Lev Walkin8e8078a2004-09-26 13:10:40 +0000104 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000105
106 /* Dump preamble */
Lev Walkin8e8078a2004-09-26 13:10:40 +0000107 if(cb("{ ", 2, app_key) < 0)
Lev Walkinf15320b2004-06-03 03:38:44 +0000108 return -1;
109
Lev Walkina9cc46e2004-09-22 16:06:28 +0000110 if(RELATIVE_OID__dump_body(st, cb, app_key) < 0)
111 return -1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000112
Lev Walkin8e8078a2004-09-26 13:10:40 +0000113 return (cb(" }", 2, app_key) < 0) ? -1 : 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000114}
115
Lev Walkin0fab1a62005-03-09 22:19:25 +0000116static enum xer_pbd_rval
Lev Walkin20696a42017-10-17 21:27:33 -0700117RELATIVE_OID__xer_body_decode(const asn_TYPE_descriptor_t *td, void *sptr,
118 const void *chunk_buf, size_t chunk_size) {
119 RELATIVE_OID_t *st = (RELATIVE_OID_t *)sptr;
Lev Walkin2c34aad2005-03-10 11:50:24 +0000120 const char *chunk_end = (const char *)chunk_buf + chunk_size;
121 const char *endptr;
Lev Walkin588bf0f2017-10-13 23:51:16 -0700122 asn_oid_arc_t s_arcs[6];
123 asn_oid_arc_t *arcs = s_arcs;
124 ssize_t num_arcs;
Lev Walkin92302252004-10-23 10:16:51 +0000125 int ret;
126
Lev Walkine0b56e02005-02-25 12:10:27 +0000127 (void)td;
128
Lev Walkin588bf0f2017-10-13 23:51:16 -0700129 num_arcs = OBJECT_IDENTIFIER_parse_arcs(
130 (const char *)chunk_buf, chunk_size, arcs,
131 sizeof(s_arcs) / sizeof(s_arcs[0]), &endptr);
132 if(num_arcs < 0) {
133 /* Expecting at least one arc arcs */
134 return XPBD_BROKEN_ENCODING;
135 } else if(num_arcs == 0) {
136 return XPBD_NOT_BODY_IGNORE;
137 }
138 assert(endptr == chunk_end);
Lev Walkin0fab1a62005-03-09 22:19:25 +0000139
Lev Walkin588bf0f2017-10-13 23:51:16 -0700140 if((size_t)num_arcs > sizeof(s_arcs) / sizeof(s_arcs[0])) {
141 arcs = (asn_oid_arc_t *)MALLOC(num_arcs * sizeof(arcs[0]));
142 if(!arcs) return XPBD_SYSTEM_FAILURE;
143 ret = OBJECT_IDENTIFIER_parse_arcs((const char *)chunk_buf, chunk_size,
144 arcs, num_arcs, &endptr);
145 if(ret != num_arcs) {
146 return XPBD_SYSTEM_FAILURE; /* assert?.. */
147 }
148 }
Lev Walkin92302252004-10-23 10:16:51 +0000149
Lev Walkin588bf0f2017-10-13 23:51:16 -0700150 /*
151 * Convert arcs into BER representation.
152 */
153 ret = RELATIVE_OID_set_arcs(st, arcs, num_arcs);
154 if(arcs != s_arcs) FREEMEM(arcs);
Lev Walkin92302252004-10-23 10:16:51 +0000155
Lev Walkin588bf0f2017-10-13 23:51:16 -0700156 return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED;
Lev Walkin92302252004-10-23 10:16:51 +0000157}
158
159asn_dec_rval_t
Lev Walkinafbf2a92017-09-12 23:30:27 -0700160RELATIVE_OID_decode_xer(const asn_codec_ctx_t *opt_codec_ctx,
Lev Walkin20696a42017-10-17 21:27:33 -0700161 const asn_TYPE_descriptor_t *td, void **sptr,
162 const char *opt_mname, const void *buf_ptr,
163 size_t size) {
164 return xer_decode_primitive(opt_codec_ctx, td,
Lev Walkin92302252004-10-23 10:16:51 +0000165 sptr, sizeof(RELATIVE_OID_t), opt_mname,
166 buf_ptr, size, RELATIVE_OID__xer_body_decode);
167}
168
Lev Walkina9cc46e2004-09-22 16:06:28 +0000169asn_enc_rval_t
Lev Walkin20696a42017-10-17 21:27:33 -0700170RELATIVE_OID_encode_xer(const asn_TYPE_descriptor_t *td, const void *sptr,
171 int ilevel, enum xer_encoder_flags_e flags,
172 asn_app_consume_bytes_f *cb, void *app_key) {
173 const RELATIVE_OID_t *st = (const RELATIVE_OID_t *)sptr;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000174 asn_enc_rval_t er;
175
176 (void)ilevel; /* Unused argument */
177 (void)flags; /* Unused argument */
178
179 if(!st || !st->buf)
Lev Walkin7c1dc052016-03-14 03:08:15 -0700180 ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000181
182 er.encoded = RELATIVE_OID__dump_body(st, cb, app_key);
Lev Walkin7c1dc052016-03-14 03:08:15 -0700183 if(er.encoded < 0) ASN__ENCODE_FAILED;
Lev Walkina9cc46e2004-09-22 16:06:28 +0000184
Lev Walkin7c1dc052016-03-14 03:08:15 -0700185 ASN__ENCODED_OK(er);
Lev Walkina9cc46e2004-09-22 16:06:28 +0000186}
Lev Walkinf15320b2004-06-03 03:38:44 +0000187
Lev Walkin588bf0f2017-10-13 23:51:16 -0700188ssize_t
189RELATIVE_OID_get_arcs(const RELATIVE_OID_t *st, asn_oid_arc_t *arcs,
190 size_t arcs_count) {
191 size_t num_arcs = 0;
192 size_t off;
Lev Walkinf15320b2004-06-03 03:38:44 +0000193
Lev Walkin588bf0f2017-10-13 23:51:16 -0700194 if(!st || !st->buf) {
195 errno = EINVAL;
196 return -1;
197 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000198
Lev Walkin588bf0f2017-10-13 23:51:16 -0700199 for(off = 0;;) {
200 asn_oid_arc_t arc;
201 ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off,
202 st->size - off, &arc);
203 if(rd < 0) {
204 return -1;
205 } else if(rd == 0) {
206 /* No more arcs. */
207 break;
208 } else {
209 off += rd;
210 if(num_arcs < arcs_count) {
211 arcs[num_arcs] = arc;
212 }
213 num_arcs++;
214 }
215 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000216
Lev Walkin588bf0f2017-10-13 23:51:16 -0700217 if(off != st->size) {
218 return -1;
219 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000220
Lev Walkin29a044b2004-06-14 07:24:36 +0000221 return num_arcs;
Lev Walkinf15320b2004-06-03 03:38:44 +0000222}
223
224int
Lev Walkin588bf0f2017-10-13 23:51:16 -0700225RELATIVE_OID_set_arcs(RELATIVE_OID_t *st, const asn_oid_arc_t *arcs,
226 size_t arcs_count) {
227 uint8_t *buf;
Lev Walkinf15320b2004-06-03 03:38:44 +0000228 uint8_t *bp;
Lev Walkin588bf0f2017-10-13 23:51:16 -0700229 size_t size;
230 size_t i;
Lev Walkinf15320b2004-06-03 03:38:44 +0000231
Lev Walkin588bf0f2017-10-13 23:51:16 -0700232 if(!st || !arcs) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000233 errno = EINVAL;
234 return -1;
235 }
236
237 /*
238 * Roughly estimate the maximum size necessary to encode these arcs.
239 */
Lev Walkin588bf0f2017-10-13 23:51:16 -0700240 size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arcs_count;
241 bp = buf = (uint8_t *)MALLOC(size + 1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000242 if(!buf) {
243 /* ENOMEM */
244 return -1;
245 }
246
247 /*
Lev Walkin0787ff02004-06-17 23:43:39 +0000248 * Encode the arcs.
Lev Walkinf15320b2004-06-03 03:38:44 +0000249 */
Lev Walkin588bf0f2017-10-13 23:51:16 -0700250 for(i = 0; i < arcs_count; i++) {
251 ssize_t wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
252 if(wrote <= 0) {
253 FREEMEM(buf);
254 return -1;
255 }
256 assert((size_t)wrote <= size);
257 bp += wrote;
258 size -= wrote;
259 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000260
261 /*
262 * Replace buffer.
263 */
Lev Walkin588bf0f2017-10-13 23:51:16 -0700264 st->size = bp - buf;
265 bp = st->buf;
266 st->buf = buf;
267 st->buf[st->size] = '\0';
Lev Walkinf15320b2004-06-03 03:38:44 +0000268 if(bp) FREEMEM(bp);
269
270 return 0;
271}
Lev Walkin0787ff02004-06-17 23:43:39 +0000272
Lev Walkina5972be2017-09-29 23:15:58 -0700273
274/*
275 * Generate values from the list of interesting values, or just a random value.
276 */
Lev Walkin588bf0f2017-10-13 23:51:16 -0700277static asn_oid_arc_t
Lev Walkina5972be2017-09-29 23:15:58 -0700278RELATIVE_OID__biased_random_arc() {
279 static const uint16_t values[] = {0, 1, 127, 128, 129, 254, 255, 256};
280
Lev Walkinb5b524b2017-10-13 03:14:03 -0700281 switch(asn_random_between(0, 2)) {
282 case 0:
283 return values[asn_random_between(
284 0, sizeof(values) / sizeof(values[0]) - 1)];
285 case 1:
286 return asn_random_between(0, UINT_MAX);
287 case 2:
288 default:
289 return UINT_MAX;
Lev Walkina5972be2017-09-29 23:15:58 -0700290 }
Lev Walkina5972be2017-09-29 23:15:58 -0700291}
292
293asn_random_fill_result_t
294RELATIVE_OID_random_fill(const asn_TYPE_descriptor_t *td, void **sptr,
Lev Walkin588bf0f2017-10-13 23:51:16 -0700295 const asn_encoding_constraints_t *constraints,
296 size_t max_length) {
Lev Walkina5972be2017-09-29 23:15:58 -0700297 asn_random_fill_result_t result_ok = {ARFILL_OK, 1};
298 asn_random_fill_result_t result_failed = {ARFILL_FAILED, 0};
299 asn_random_fill_result_t result_skipped = {ARFILL_SKIPPED, 0};
300 RELATIVE_OID_t *st;
Lev Walkinb5b524b2017-10-13 03:14:03 -0700301 const int min_arcs = 1; /* A minimum of 1 arc is required */
Lev Walkin588bf0f2017-10-13 23:51:16 -0700302 asn_oid_arc_t arcs[3];
303 size_t arcs_len =
304 asn_random_between(min_arcs, sizeof(arcs) / sizeof(arcs[0]));
Lev Walkina5972be2017-09-29 23:15:58 -0700305 size_t i;
306
307 (void)constraints;
308
309 if(max_length < arcs_len) return result_skipped;
310
311 if(*sptr) {
312 st = *sptr;
313 } else {
314 st = CALLOC(1, sizeof(*st));
315 }
316
317 for(i = 0; i < arcs_len; i++) {
318 arcs[i] = RELATIVE_OID__biased_random_arc();
319 }
320
Lev Walkin588bf0f2017-10-13 23:51:16 -0700321 if(RELATIVE_OID_set_arcs(st, arcs, arcs_len)) {
Lev Walkina5972be2017-09-29 23:15:58 -0700322 if(st != *sptr) {
323 ASN_STRUCT_FREE(*td, st);
324 }
325 return result_failed;
326 }
327
328 *sptr = st;
329
Lev Walkin588bf0f2017-10-13 23:51:16 -0700330 result_ok.length = st->size;
Lev Walkina5972be2017-09-29 23:15:58 -0700331 return result_ok;
332}