ITS
ber_decoder.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  */
5 #include <asn_internal.h>
6 
7 #undef ADVANCE
8 #define ADVANCE(num_bytes) do { \
9  size_t num = num_bytes; \
10  ptr = ((const char *)ptr) + num; \
11  size -= num; \
12  consumed_myself += num; \
13  } while(0)
14 #undef RETURN
15 #define RETURN(_code) do { \
16  asn_dec_rval_t rval; \
17  rval.code = _code; \
18  if(opt_ctx) opt_ctx->step = step; /* Save context */ \
19  if(_code == RC_OK || opt_ctx) \
20  rval.consumed = consumed_myself; \
21  else \
22  rval.consumed = 0; /* Context-free */ \
23  return rval; \
24  } while(0)
25 
26 /*
27  * The BER decoder of any type.
28  */
30 ber_decode(asn_codec_ctx_t *opt_codec_ctx,
32  void **struct_ptr, const void *ptr, size_t size) {
33  asn_codec_ctx_t s_codec_ctx;
34 
35  /*
36  * Stack checker requires that the codec context
37  * must be allocated on the stack.
38  */
39  if(opt_codec_ctx) {
40  if(opt_codec_ctx->max_stack_size) {
41  s_codec_ctx = *opt_codec_ctx;
42  opt_codec_ctx = &s_codec_ctx;
43  }
44  } else {
45  /* If context is not given, be security-conscious anyway */
46  memset(&s_codec_ctx, 0, sizeof(s_codec_ctx));
48  opt_codec_ctx = &s_codec_ctx;
49  }
50 
51  /*
52  * Invoke type-specific decoder.
53  */
54  return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor,
55  struct_ptr, /* Pointer to the destination structure */
56  ptr, size, /* Buffer and its size */
57  0 /* Default tag mode is 0 */
58  );
59 }
60 
61 /*
62  * Check the set of <TL<TL<TL...>>> tags matches the definition.
63  */
67  const void *ptr, size_t size, int tag_mode, int last_tag_form,
68  ber_tlv_len_t *last_length, int *opt_tlv_form) {
69  ssize_t consumed_myself = 0;
70  ssize_t tag_len;
71  ssize_t len_len;
72  ber_tlv_tag_t tlv_tag;
73  ber_tlv_len_t tlv_len;
74  ber_tlv_len_t limit_len = -1;
75  int expect_00_terminators = 0;
76  int tlv_constr = -1; /* If CHOICE, opt_tlv_form is not given */
77  int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */
78  int tagno;
79 
80  /*
81  * Make sure we didn't exceed the maximum stack size.
82  */
83  if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx))
84  RETURN(RC_FAIL);
85 
86  /*
87  * So what does all this implicit skip stuff mean?
88  * Imagine two types,
89  * A ::= [5] IMPLICIT T
90  * B ::= [2] EXPLICIT T
91  * Where T is defined as
92  * T ::= [4] IMPLICIT SEQUENCE { ... }
93  *
94  * Let's say, we are starting to decode type A, given the
95  * following TLV stream: <5> <0>. What does this mean?
96  * It means that the type A contains type T which is,
97  * in turn, empty.
98  * Remember though, that we are still in A. We cannot
99  * just pass control to the type T decoder. Why? Because
100  * the type T decoder expects <4> <0>, not <5> <0>.
101  * So, we must make sure we are going to receive <5> while
102  * still in A, then pass control to the T decoder, indicating
103  * that the tag <4> was implicitly skipped. The decoder of T
104  * hence will be prepared to treat <4> as valid tag, and decode
105  * it appropriately.
106  */
107 
108  tagno = step /* Continuing where left previously */
109  + (tag_mode==1?-1:0)
110  ;
111  ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
112  td->name, (long)size, tag_mode, step, tagno);
113  /* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */
114 
115  if(tag_mode == 0 && tagno == td->tags_count) {
116  /*
117  * This must be the _untagged_ ANY type,
118  * which outermost tag isn't known in advance.
119  * Fetch the tag and length separately.
120  */
121  tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
122  switch(tag_len) {
123  case -1: RETURN(RC_FAIL);
124  case 0: RETURN(RC_WMORE);
125  }
126  tlv_constr = BER_TLV_CONSTRUCTED(ptr);
127  len_len = ber_fetch_length(tlv_constr,
128  (const char *)ptr + tag_len, size - tag_len, &tlv_len);
129  switch(len_len) {
130  case -1: RETURN(RC_FAIL);
131  case 0: RETURN(RC_WMORE);
132  }
133  ASN_DEBUG("Advancing %ld in ANY case",
134  (long)(tag_len + len_len));
135  ADVANCE(tag_len + len_len);
136  } else {
137  assert(tagno < td->tags_count); /* At least one loop */
138  }
139  for((void)tagno; tagno < td->tags_count; tagno++, step++) {
140 
141  /*
142  * Fetch and process T from TLV.
143  */
144  tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
145  ASN_DEBUG("Fetching tag from {%p,%ld}: "
146  "len %ld, step %d, tagno %d got %s",
147  ptr, (long)size,
148  (long)tag_len, step, tagno,
149  ber_tlv_tag_string(tlv_tag));
150  switch(tag_len) {
151  case -1: RETURN(RC_FAIL);
152  case 0: RETURN(RC_WMORE);
153  }
154 
155  tlv_constr = BER_TLV_CONSTRUCTED(ptr);
156 
157  /*
158  * If {I}, don't check anything.
159  * If {I,B,C}, check B and C unless we're at I.
160  */
161  if(tag_mode != 0 && step == 0) {
162  /*
163  * We don't expect tag to match here.
164  * It's just because we don't know how the tag
165  * is supposed to look like.
166  */
167  } else {
168  assert(tagno >= 0); /* Guaranteed by the code above */
169  if(tlv_tag != td->tags[tagno]) {
170  /*
171  * Unexpected tag. Too bad.
172  */
173  ASN_DEBUG("Expected: %s, "
174  "expectation failed (tn=%d, tm=%d)",
175  ber_tlv_tag_string(td->tags[tagno]),
176  tagno, tag_mode
177  );
178  RETURN(RC_FAIL);
179  }
180  }
181 
182  /*
183  * Attention: if there are more tags expected,
184  * ensure that the current tag is presented
185  * in constructed form (it contains other tags!).
186  * If this one is the last one, check that the tag form
187  * matches the one given in descriptor.
188  */
189  if(tagno < (td->tags_count - 1)) {
190  if(tlv_constr == 0) {
191  ASN_DEBUG("tlv_constr = %d, expfail",
192  tlv_constr);
193  RETURN(RC_FAIL);
194  }
195  } else {
196  if(last_tag_form != tlv_constr
197  && last_tag_form != -1) {
198  ASN_DEBUG("last_tag_form %d != %d",
199  last_tag_form, tlv_constr);
200  RETURN(RC_FAIL);
201  }
202  }
203 
204  /*
205  * Fetch and process L from TLV.
206  */
207  len_len = ber_fetch_length(tlv_constr,
208  (const char *)ptr + tag_len, size - tag_len, &tlv_len);
209  ASN_DEBUG("Fetching len = %ld", (long)len_len);
210  switch(len_len) {
211  case -1: RETURN(RC_FAIL);
212  case 0: RETURN(RC_WMORE);
213  }
214 
215  /*
216  * FIXME
217  * As of today, the chain of tags
218  * must either contain several indefinite length TLVs,
219  * or several definite length ones.
220  * No mixing is allowed.
221  */
222  if(tlv_len == -1) {
223  /*
224  * Indefinite length.
225  */
226  if(limit_len == -1) {
227  expect_00_terminators++;
228  } else {
229  ASN_DEBUG("Unexpected indefinite length "
230  "in a chain of definite lengths");
231  RETURN(RC_FAIL);
232  }
233  ADVANCE(tag_len + len_len);
234  continue;
235  } else {
236  if(expect_00_terminators) {
237  ASN_DEBUG("Unexpected definite length "
238  "in a chain of indefinite lengths");
239  RETURN(RC_FAIL);
240  }
241  }
242 
243  /*
244  * Check that multiple TLVs specify ever decreasing length,
245  * which is consistent.
246  */
247  if(limit_len == -1) {
248  limit_len = tlv_len + tag_len + len_len;
249  if(limit_len < 0) {
250  /* Too great tlv_len value? */
251  RETURN(RC_FAIL);
252  }
253  } else if(limit_len != tlv_len + tag_len + len_len) {
254  /*
255  * Inner TLV specifies length which is inconsistent
256  * with the outer TLV's length value.
257  */
258  ASN_DEBUG("Outer TLV is %ld and inner is %ld",
259  (long)limit_len, (long)tlv_len);
260  RETURN(RC_FAIL);
261  }
262 
263  ADVANCE(tag_len + len_len);
264 
265  limit_len -= (tag_len + len_len);
266  if((ssize_t)size > limit_len) {
267  /*
268  * Make sure that we won't consume more bytes
269  * from the parent frame than the inferred limit.
270  */
271  size = limit_len;
272  }
273  }
274 
275  if(opt_tlv_form)
276  *opt_tlv_form = tlv_constr;
277  if(expect_00_terminators)
278  *last_length = -expect_00_terminators;
279  else
280  *last_length = tlv_len;
281 
282  RETURN(RC_OK);
283 }
#define _ASN_DEFAULT_STACK_MAX
Definition: asn_internal.h:103
ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r)
Definition: ber_tlv_tag.c:10
#define BER_TLV_CONSTRUCTED(tagptr)
Definition: ber_tlv_tag.h:25
ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, ber_tlv_len_t *len_r)
char * ber_tlv_tag_string(ber_tlv_tag_t tag)
Definition: ber_tlv_tag.c:94
ssize_t ber_tlv_len_t
static int _ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx)
Definition: asn_internal.h:105
asn_dec_rval_t ber_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr, const void *ptr, size_t size)
Definition: ber_decoder.c:30
#define RETURN(_code)
Definition: ber_decoder.c:15
ber_tlv_tag_t * tags
Definition: constr_TYPE.h:111
size_t max_stack_size
Definition: asn_codecs.h:36
static void ASN_DEBUG(const char *fmt,...)
Definition: asn_internal.h:62
ber_type_decoder_f * ber_decoder
Definition: constr_TYPE.h:96
asn_TYPE_descriptor_t * type_descriptor
asn_dec_rval_t ber_check_tags(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx, const void *ptr, size_t size, int tag_mode, int last_tag_form, ber_tlv_len_t *last_length, int *opt_tlv_form)
Definition: ber_decoder.c:65
#define ADVANCE(num_bytes)
Definition: ber_decoder.c:8
unsigned ber_tlv_tag_t
Definition: ber_tlv_tag.h:18