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 "asn1/asn1c/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  */
29 asn_dec_rval_t
ber_decode(const asn_codec_ctx_t * opt_codec_ctx,const asn_TYPE_descriptor_t * type_descriptor,void ** struct_ptr,const void * ptr,size_t size)30 ber_decode(const asn_codec_ctx_t *opt_codec_ctx,
31            const asn_TYPE_descriptor_t *type_descriptor, void **struct_ptr,
32            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));
47 		s_codec_ctx.max_stack_size = ASN__DEFAULT_STACK_MAX;
48 		opt_codec_ctx = &s_codec_ctx;
49 	}
50 
51 	/*
52 	 * Invoke type-specific decoder.
53 	 */
54 	return type_descriptor->op->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  */
64 asn_dec_rval_t
ber_check_tags(const asn_codec_ctx_t * opt_codec_ctx,const 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)65 ber_check_tags(const asn_codec_ctx_t *opt_codec_ctx,
66                const asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx,
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 == (int)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 < (int)td->tags_count);	/* At least one loop */
138 	}
139 	for((void)tagno; tagno < (int)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 < ((int)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 		 * TODO (fine) As of today, the chain of tags must either
217 		 * contain several indefinite length TLVs, or several definite
218 		 * length ones. No mixing is allowed.
219 		 */
220 		if(tlv_len == -1) {
221 			/*
222 			 * Indefinite length.
223 			 */
224 			if(limit_len == -1) {
225 				expect_00_terminators++;
226 			} else {
227 				ASN_DEBUG("Unexpected indefinite length "
228 					"in a chain of definite lengths");
229 				RETURN(RC_FAIL);
230 			}
231 			ADVANCE(tag_len + len_len);
232 			continue;
233 		} else {
234 			if(expect_00_terminators) {
235 				ASN_DEBUG("Unexpected definite length "
236 					"in a chain of indefinite lengths");
237 				RETURN(RC_FAIL);
238 			}
239 		}
240 
241 		/*
242 		 * Check that multiple TLVs specify ever decreasing length,
243 		 * which is consistent.
244 		 */
245 		if(limit_len == -1) {
246 			limit_len    = tlv_len + tag_len + len_len;
247 			if(limit_len < 0) {
248 				/* Too great tlv_len value? */
249 				RETURN(RC_FAIL);
250 			}
251 		} else if(limit_len != tlv_len + tag_len + len_len) {
252 			/*
253 			 * Inner TLV specifies length which is inconsistent
254 			 * with the outer TLV's length value.
255 			 */
256 			ASN_DEBUG("Outer TLV is %ld and inner is %ld",
257 				(long)limit_len, (long)tlv_len);
258 			RETURN(RC_FAIL);
259 		}
260 
261 		ADVANCE(tag_len + len_len);
262 
263 		limit_len -= (tag_len + len_len);
264 		if((ssize_t)size > limit_len) {
265 			/*
266 			 * Make sure that we won't consume more bytes
267 			 * from the parent frame than the inferred limit.
268 			 */
269 			size = limit_len;
270 		}
271 	}
272 
273 	if(opt_tlv_form)
274 		*opt_tlv_form = tlv_constr;
275 	if(expect_00_terminators)
276 		*last_length = -expect_00_terminators;
277 	else
278 		*last_length = tlv_len;
279 
280 	RETURN(RC_OK);
281 }
282