OBJECT_IDENTIFIER.c
Go to the documentation of this file.
1 /*-
2  * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
9 #include <limits.h> /* for CHAR_BIT */
10 #include <errno.h>
11 #include <inttypes.h>
12 
13 /*
14  * OBJECT IDENTIFIER basic type description.
15  */
17  (ASN_TAG_CLASS_UNIVERSAL | (6 << 2))
18 };
21 #if !defined(ASN_DISABLE_PRINT_SUPPORT)
23 #else
24  0,
25 #endif /* !defined(ASN_DISABLE_PRINT_SUPPORT) */
26  OCTET_STRING_compare, /* Implemented in terms of a string comparison */
27  OCTET_STRING_copy, /* Implemented in terms of a string copy */
28 #if !defined(ASN_DISABLE_BER_SUPPORT)
31 #else
32  0,
33  0,
34 #endif /* !defined(ASN_DISABLE_BER_SUPPORT) */
35 #if !defined(ASN_DISABLE_XER_SUPPORT)
38 #else
39  0,
40  0,
41 #endif /* !defined(ASN_DISABLE_XER_SUPPORT) */
42 #if !defined(ASN_DISABLE_JER_SUPPORT)
45 #else
46  0,
47  0,
48 #endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
49 #if !defined(ASN_DISABLE_OER_SUPPORT)
52 #else
53  0,
54  0,
55 #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
56 #if !defined(ASN_DISABLE_UPER_SUPPORT)
59 #else
60  0,
61  0,
62 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) */
63 #if !defined(ASN_DISABLE_APER_SUPPORT)
66 #else
67  0,
68  0,
69 #endif /* !defined(ASN_DISABLE_APER_SUPPORT) */
70 #if !defined(ASN_DISABLE_RFILL_SUPPORT)
72 #else
73  0,
74 #endif /* !defined(ASN_DISABLE_RFILL_SUPPORT) */
75  0 /* Use generic outmost tag fetcher */
76 };
78  "OBJECT IDENTIFIER",
79  "OBJECT_IDENTIFIER",
83  / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
84  asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */
86  / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]),
87  {
88 #if !defined(ASN_DISABLE_OER_SUPPORT)
89  0,
90 #endif /* !defined(ASN_DISABLE_OER_SUPPORT) */
91 #if !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT)
92  0,
93 #endif /* !defined(ASN_DISABLE_UPER_SUPPORT) || !defined(ASN_DISABLE_APER_SUPPORT) */
94 #if !defined(ASN_DISABLE_JER_SUPPORT)
95  0,
96 #endif /* !defined(ASN_DISABLE_JER_SUPPORT) */
98  },
99  0, 0, /* No members */
100  0 /* No specifics */
101 };
102 
103 int
105  asn_app_constraint_failed_f *ctfailcb,
106  void *app_key) {
107  const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
108 
109  if(st && st->buf) {
110  if(st->size < 1) {
111  ASN__CTFAIL(app_key, td, sptr,
112  "%s: at least one numerical value "
113  "expected (%s:%d)",
114  td->name, __FILE__, __LINE__);
115  return -1;
116  }
117  } else {
118  ASN__CTFAIL(app_key, td, sptr,
119  "%s: value not given (%s:%d)",
120  td->name, __FILE__, __LINE__);
121  return -1;
122  }
123 
124  return 0;
125 }
126 
127 static ssize_t
128 OBJECT_IDENTIFIER_get_first_arcs(const uint8_t *arcbuf, size_t arcbuf_len,
129  asn_oid_arc_t *arc0, asn_oid_arc_t *arc1) {
130  asn_oid_arc_t value;
131 
132  ssize_t rd = OBJECT_IDENTIFIER_get_single_arc(arcbuf, arcbuf_len, &value);
133  if(rd <= 0) return rd;
134 
135  if(value >= 80) {
136  *arc0 = 2;
137  *arc1 = value - 80;
138  } else if(value >= 40) {
139  *arc0 = 1;
140  *arc1 = value - 40;
141  } else {
142  *arc0 = 0;
143  *arc1 = value;
144  }
145 
146  return rd;
147 }
148 
149 ssize_t
150 OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, size_t arcbuf_len,
151  asn_oid_arc_t *ret_value) {
152  const uint8_t *b = arcbuf;
153  const uint8_t *arcend = arcbuf + arcbuf_len; /* End of arc */
154 
155  if(arcbuf == arcend) {
156  return 0;
157  } else {
158  asn_oid_arc_t accum;
159  asn_oid_arc_t upper_limit = (ASN_OID_ARC_MAX >> 7);
160  /* When the value reaches "upper_limit", it can take */
161  /* at most one more digit. If it exceeds "upper_limit" */
162  /* but there are more digits - it's an Overflow condition */
163  /* Gather all bits into the accumulator */
164  for(accum = 0; b < arcend; b++) {
165  accum = (accum << 7) | (*b & ~0x80);
166  if((*b & 0x80) == 0) { // no more digits
167  if(accum <= ASN_OID_ARC_MAX) {
168  *ret_value = accum;
169  return 1 + (b - arcbuf);
170  } else {
171  errno = ERANGE; /* Overflow */
172  return -1;
173  }
174  } else { // to make sure we aren't wrapping around
175  if(accum > upper_limit) {
176  errno = ERANGE; /* Overflow */
177  return -1;
178  }
179  }
180  }
181  errno = EINVAL;
182  return -1;
183  }
184 
185 }
186 
187 ssize_t
189  asn_app_consume_bytes_f *cb, void *app_key) {
190  char scratch[32];
191  asn_oid_arc_t arc0 = 0;
192  asn_oid_arc_t arc1 = 0;
193  size_t produced = 0;
194  size_t off = 0;
195  ssize_t rd;
196  int ret;
197 
198  rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);
199  if(rd <= 0) {
200  return -1;
201  }
202 
203  ret = snprintf(scratch, sizeof(scratch), "%"PRIu32".%"PRIu32, arc0, arc1);
204  if(ret >= (ssize_t)sizeof(scratch)) {
205  return -1;
206  }
207  produced += ret;
208  if(cb(scratch, ret, app_key) < 0)
209  return -1;
210 
211  for(off = rd; ; ) {
212  asn_oid_arc_t arc;
213  rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,
214  &arc);
215  if(rd < 0) {
216  return -1;
217  } else if(rd == 0) {
218  /* No more arcs. */
219  break;
220  } else {
221  off += rd;
222  assert(off <= st->size);
223  ret = snprintf(scratch, sizeof(scratch), ".%" PRIu32, arc);
224  if(ret >= (ssize_t)sizeof(scratch)) {
225  return -1;
226  }
227  produced += ret;
228  if(cb(scratch, ret, app_key) < 0) return -1;
229  }
230  }
231 
232  if(off != st->size) {
233  ASN_DEBUG("Could not scan to the end of Object Identifier");
234  return -1;
235  }
236 
237  return produced;
238 }
239 
240 ssize_t
242  size_t arc_slots) {
243  asn_oid_arc_t arc0 = 0;
244  asn_oid_arc_t arc1 = 0;
245  size_t num_arcs = 0;
246  size_t off;
247  ssize_t rd;
248 
249  if(!st || !st->buf) {
250  errno = EINVAL;
251  return -1;
252  }
253 
254  rd = OBJECT_IDENTIFIER_get_first_arcs(st->buf, st->size, &arc0, &arc1);
255  if(rd <= 0) {
256  return -1;
257  }
258  num_arcs = 2;
259  switch(arc_slots) {
260  default:
261  case 2:
262  arcs[1] = arc1;
263  /* Fall through */
264  case 1:
265  arcs[0] = arc0;
266  /* Fall through */
267  case 0:
268  break;
269  }
270 
271  for(off = rd; ; ) {
272  asn_oid_arc_t arc;
273  rd = OBJECT_IDENTIFIER_get_single_arc(st->buf + off, st->size - off,
274  &arc);
275  if(rd < 0) {
276  return -1;
277  } else if(rd == 0) {
278  /* No more arcs. */
279  break;
280  } else {
281  off += rd;
282  if(num_arcs < arc_slots) {
283  arcs[num_arcs] = arc;
284  }
285  num_arcs++;
286  }
287  }
288 
289  if(off != st->size) {
290  return -1;
291  }
292 
293  return num_arcs;
294 }
295 
296 
297 /*
298  * Save the single value as an object identifier arc.
299  */
300 ssize_t
301 OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len,
302  asn_oid_arc_t value) {
303  /*
304  * The following conditions must hold:
305  * assert(arcbuf);
306  */
307  uint8_t scratch[((sizeof(value) * CHAR_BIT + 6) / 7)];
308  uint8_t *scratch_end = &scratch[sizeof(scratch)-1];
309  uint8_t *b;
310  size_t result_len;
311  uint8_t mask;
312 
313  for(b = scratch_end, mask = 0; ; mask = 0x80, b--) {
314  *b = mask | (value & 0x7f);
315  value >>= 7;
316  if(!value) {
317  break;
318  }
319  }
320 
321  result_len = (scratch_end - b) + 1;
322 
323  if(result_len > arcbuf_len) {
324  return -1;
325  }
326 
327  memcpy(arcbuf, b, result_len);
328 
329  return result_len;
330 }
331 
332 int
334  size_t arc_slots) {
335  uint8_t *buf;
336  uint8_t *bp;
337  ssize_t wrote;
338  asn_oid_arc_t arc0;
339  asn_oid_arc_t arc1;
340  size_t size;
341  size_t i;
342 
343  if(!st || !arcs || arc_slots < 2) {
344  errno = EINVAL;
345  return -1;
346  }
347 
348  arc0 = arcs[0];
349  arc1 = arcs[1];
350 
351  if(arc0 <= 1) {
352  if(arc1 >= 40) {
353  /* 8.19.4: At most 39 subsequent values (including 0) */
354  errno = ERANGE;
355  return -1;
356  }
357  } else if(arc0 == 2) {
358  if(arc1 > ASN_OID_ARC_MAX - 80) {
359  errno = ERANGE;
360  return -1;
361  }
362  } else if(arc0 > 2) {
363  /* 8.19.4: Only three values are allocated from the root node */
364  errno = ERANGE;
365  return -1;
366  }
367 
368  /*
369  * After above tests it is known that the value of arc0 is completely
370  * trustworthy (0..2). However, the arc1's value is still meaningless.
371  */
372 
373  /*
374  * Roughly estimate the maximum size necessary to encode these arcs.
375  * This estimation implicitly takes in account the following facts,
376  * that cancel each other:
377  * * the first two arcs are encoded in a single value.
378  * * the first value may require more space (+1 byte)
379  * * the value of the first arc which is in range (0..2)
380  */
381  size = ((sizeof(asn_oid_arc_t) * CHAR_BIT + 6) / 7) * arc_slots;
382  bp = buf = (uint8_t *)MALLOC(size + 1);
383  if(!buf) {
384  /* ENOMEM */
385  return -1;
386  }
387 
388  wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arc0 * 40 + arc1);
389  if(wrote <= 0) {
390  FREEMEM(buf);
391  return -1;
392  }
393  assert((size_t)wrote <= size);
394  bp += wrote;
395  size -= wrote;
396 
397  for(i = 2; i < arc_slots; i++) {
398  wrote = OBJECT_IDENTIFIER_set_single_arc(bp, size, arcs[i]);
399  if(wrote <= 0) {
400  FREEMEM(buf);
401  return -1;
402  }
403  assert((size_t)wrote <= size);
404  bp += wrote;
405  size -= wrote;
406  }
407 
408  /*
409  * Replace buffer.
410  */
411  st->size = bp - buf;
412  bp = st->buf;
413  st->buf = buf;
414  st->buf[st->size] = '\0';
415  if(bp) FREEMEM(bp);
416 
417  return 0;
418 }
419 
420 ssize_t
421 OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length,
422  asn_oid_arc_t *arcs, size_t arcs_count,
423  const char **opt_oid_text_end) {
424  size_t num_arcs = 0;
425  const char *oid_end;
426  enum {
427  ST_LEADSPACE,
428  ST_TAILSPACE,
429  ST_AFTERVALUE, /* Next character ought to be '.' or a space */
430  ST_WAITDIGITS /* Next character is expected to be a digit */
431  } state = ST_LEADSPACE;
432 
433  if(!oid_text || oid_txt_length < -1 || (arcs_count && !arcs)) {
434  if(opt_oid_text_end) *opt_oid_text_end = oid_text;
435  errno = EINVAL;
436  return -1;
437  }
438 
439  if(oid_txt_length == -1)
440  oid_txt_length = strlen(oid_text);
441 
442 #define _OID_CAPTURE_ARC(oid_text, oid_end) \
443  do { \
444  const char *endp = oid_end; \
445  unsigned long value; \
446  switch(asn_strtoul_lim(oid_text, &endp, &value)) { \
447  case ASN_STRTOX_EXTRA_DATA: \
448  case ASN_STRTOX_OK: \
449  if(value <= ASN_OID_ARC_MAX) { \
450  if(num_arcs < arcs_count) arcs[num_arcs] = value; \
451  num_arcs++; \
452  oid_text = endp - 1; \
453  break; \
454  } \
455  /* Fall through */ \
456  case ASN_STRTOX_ERROR_RANGE: \
457  if(opt_oid_text_end) *opt_oid_text_end = oid_text; \
458  errno = ERANGE; \
459  return -1; \
460  case ASN_STRTOX_ERROR_INVAL: \
461  case ASN_STRTOX_EXPECT_MORE: \
462  if(opt_oid_text_end) *opt_oid_text_end = oid_text; \
463  errno = EINVAL; \
464  return -1; \
465  } \
466  } while(0)
467 
468  for(oid_end = oid_text + oid_txt_length; oid_text<oid_end; oid_text++) {
469  switch(*oid_text) {
470  case 0x09: case 0x0a: case 0x0d: case 0x20: /* whitespace */
471  switch(state) {
472  case ST_LEADSPACE:
473  case ST_TAILSPACE:
474  continue;
475  case ST_AFTERVALUE:
476  state = ST_TAILSPACE;
477  continue;
478  case ST_WAITDIGITS:
479  break; /* Digits expected after ".", got whitespace */
480  }
481  break;
482  case 0x2e: /* '.' */
483  switch(state) {
484  case ST_LEADSPACE:
485  case ST_TAILSPACE:
486  case ST_WAITDIGITS:
487  if(opt_oid_text_end)
488  *opt_oid_text_end = oid_text;
489  errno = EINVAL; /* Broken OID */
490  return -1;
491  break;
492  case ST_AFTERVALUE:
493  state = ST_WAITDIGITS;
494  continue;
495  }
496  break;
497  case 0x30: case 0x31: case 0x32: case 0x33: case 0x34:
498  case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
499  switch(state) {
500  case ST_TAILSPACE:
501  case ST_AFTERVALUE:
502  if(opt_oid_text_end)
503  *opt_oid_text_end = oid_text;
504  errno = EINVAL; /* "1. 1" => broken OID */
505  return -1;
506  case ST_LEADSPACE:
507  case ST_WAITDIGITS:
508  _OID_CAPTURE_ARC(oid_text, oid_end);
509  state = ST_AFTERVALUE;
510  continue;
511  }
512  break;
513  default:
514  /* Unexpected symbols */
515  state = ST_WAITDIGITS;
516  break;
517  } /* switch() */
518  break;
519  } /* for() */
520 
521 
522  if(opt_oid_text_end) *opt_oid_text_end = oid_text;
523 
524  /* Finalize last arc */
525  switch(state) {
526  case ST_LEADSPACE:
527  return 0; /* No OID found in input data */
528  case ST_WAITDIGITS:
529  errno = EINVAL; /* Broken OID */
530  return -1;
531  case ST_AFTERVALUE:
532  case ST_TAILSPACE:
533  return num_arcs;
534  }
535 
536  errno = EINVAL; /* Broken OID */
537  return -1;
538 }
OBJECT_IDENTIFIER_get_first_arcs
static ssize_t OBJECT_IDENTIFIER_get_first_arcs(const uint8_t *arcbuf, size_t arcbuf_len, asn_oid_arc_t *arc0, asn_oid_arc_t *arc1)
Definition: OBJECT_IDENTIFIER.c:128
OBJECT_IDENTIFIER_decode_jer
jer_type_decoder_f OBJECT_IDENTIFIER_decode_jer
Definition: OBJECT_IDENTIFIER.h:50
ASN__PRIMITIVE_TYPE_s
Definition: asn_codecs_prim.h:14
asn_TYPE_operation_s
Definition: constr_TYPE.h:184
asn_DEF_OBJECT_IDENTIFIER
asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER
Definition: OBJECT_IDENTIFIER.c:77
OBJECT_IDENTIFIER_random_fill
asn_random_fill_f OBJECT_IDENTIFIER_random_fill
Definition: OBJECT_IDENTIFIER.h:69
OBJECT_IDENTIFIER_get_arcs
ssize_t OBJECT_IDENTIFIER_get_arcs(const OBJECT_IDENTIFIER_t *st, asn_oid_arc_t *arcs, size_t arc_slots)
Definition: OBJECT_IDENTIFIER.c:241
asn_app_constraint_failed_f
void() asn_app_constraint_failed_f(void *application_specific_key, const struct asn_TYPE_descriptor_s *type_descriptor_which_failed, const void *structure_which_failed_ptr, const char *error_message_format,...) CC_PRINTFLIKE(4
Definition: asn_application.h:167
ber_tlv_tag_t
unsigned ber_tlv_tag_t
Definition: ber_tlv_tag.h:18
ASN__PRIMITIVE_TYPE_s::size
size_t size
Definition: asn_codecs_prim.h:16
asn_oid_arc_t
uint32_t asn_oid_arc_t
Definition: OBJECT_IDENTIFIER.h:16
ASN_TAG_CLASS_UNIVERSAL
@ ASN_TAG_CLASS_UNIVERSAL
Definition: ber_tlv_tag.h:13
asn_TYPE_descriptor_s::name
const char * name
Definition: constr_TYPE.h:225
ber_decode_primitive
ber_type_decoder_f ber_decode_primitive
Definition: asn_codecs_prim.h:22
OBJECT_IDENTIFIER_parse_arcs
ssize_t OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, asn_oid_arc_t *arcs, size_t arcs_count, const char **opt_oid_text_end)
Definition: OBJECT_IDENTIFIER.c:421
OBJECT_IDENTIFIER_set_arcs
int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *st, const asn_oid_arc_t *arcs, size_t arc_slots)
Definition: OBJECT_IDENTIFIER.c:333
OCTET_STRING_encode_aper
per_type_encoder_f OCTET_STRING_encode_aper
Definition: OCTET_STRING.h:67
FREEMEM
#define FREEMEM(ptr)
Definition: asn_internal.h:40
asn_OP_OBJECT_IDENTIFIER
asn_TYPE_operation_t asn_OP_OBJECT_IDENTIFIER
Definition: OBJECT_IDENTIFIER.c:19
OBJECT_IDENTIFIER_print
asn_struct_print_f OBJECT_IDENTIFIER_print
Definition: OBJECT_IDENTIFIER.h:31
asn_codecs_prim.h
OBJECT_IDENTIFIER.h
asn_TYPE_descriptor_s
Definition: constr_TYPE.h:224
OCTET_STRING_decode_aper
per_type_decoder_f OCTET_STRING_decode_aper
Definition: OCTET_STRING.h:66
ASN__PRIMITIVE_TYPE_s::buf
uint8_t * buf
Definition: asn_codecs_prim.h:15
OBJECT_IDENTIFIER_constraint
int OBJECT_IDENTIFIER_constraint(const asn_TYPE_descriptor_t *td, const void *sptr, asn_app_constraint_failed_f *ctfailcb, void *app_key)
Definition: OBJECT_IDENTIFIER.c:104
der_encode_primitive
der_type_encoder_f der_encode_primitive
Definition: asn_codecs_prim.h:23
INTEGER.h
OBJECT_IDENTIFIER_set_single_arc
ssize_t OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, size_t arcbuf_len, asn_oid_arc_t value)
Definition: OBJECT_IDENTIFIER.c:301
MALLOC
#define MALLOC(size)
Definition: asn_internal.h:38
OBJECT_IDENTIFIER_encode_oer
#define OBJECT_IDENTIFIER_encode_oer
Definition: OBJECT_IDENTIFIER.h:56
OBJECT_IDENTIFIER_decode_xer
xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer
Definition: OBJECT_IDENTIFIER.h:45
asn_app_consume_bytes_f
int() asn_app_consume_bytes_f(const void *buffer, size_t size, void *application_specific_key)
Definition: asn_application.h:124
asn_internal.h
ASN__CTFAIL
#define ASN__CTFAIL
Definition: constraints.h:57
asn_DEF_OBJECT_IDENTIFIER_tags
static const ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[]
Definition: OBJECT_IDENTIFIER.c:16
OCTET_STRING_decode_uper
per_type_decoder_f OCTET_STRING_decode_uper
Definition: OCTET_STRING.h:62
ASN__PRIMITIVE_TYPE_free
asn_struct_free_f ASN__PRIMITIVE_TYPE_free
Definition: asn_codecs_prim.h:19
ASN_OID_ARC_MAX
#define ASN_OID_ARC_MAX
Definition: OBJECT_IDENTIFIER.h:17
OBJECT_IDENTIFIER__dump_body
ssize_t OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_bytes_f *cb, void *app_key)
Definition: OBJECT_IDENTIFIER.c:188
OCTET_STRING_copy
asn_struct_copy_f OCTET_STRING_copy
Definition: OCTET_STRING.h:32
OBJECT_IDENTIFIER_encode_jer
jer_type_encoder_f OBJECT_IDENTIFIER_encode_jer
Definition: OBJECT_IDENTIFIER.h:51
OBJECT_IDENTIFIER_decode_oer
#define OBJECT_IDENTIFIER_decode_oer
Definition: OBJECT_IDENTIFIER.h:55
OCTET_STRING_encode_uper
per_type_encoder_f OCTET_STRING_encode_uper
Definition: OCTET_STRING.h:63
OBJECT_IDENTIFIER_encode_xer
xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer
Definition: OBJECT_IDENTIFIER.h:46
_OID_CAPTURE_ARC
#define _OID_CAPTURE_ARC(oid_text, oid_end)
OBJECT_IDENTIFIER_get_single_arc
ssize_t OBJECT_IDENTIFIER_get_single_arc(const uint8_t *arcbuf, size_t arcbuf_len, asn_oid_arc_t *ret_value)
Definition: OBJECT_IDENTIFIER.c:150
OCTET_STRING_compare
asn_struct_compare_f OCTET_STRING_compare
Definition: OCTET_STRING.h:31


etsi_its_denm_coding
Author(s): Jean-Pierre Busch , Guido Küppers , Lennart Reiher
autogenerated on Sun May 18 2025 02:23:48