blob: 511207d2a3bcb8b3ccbdf01307156f5ac67fd728 [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 <constr_SET_OF.h>
6#include <asn_SET_OF.h>
7
8/*
9 * Number of bytes left for this structure.
10 * (ctx->left) indicates the number of bytes _transferred_ for the structure.
11 * (size) contains the number of bytes in the buffer passed.
12 */
vlmc5190612004-08-18 04:53:32 +000013#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left)
vlmfa67ddc2004-06-03 03:38:44 +000014
15/*
16 * If the subprocessor function returns with an indication that it wants
17 * more data, it may well be a fatal decoding problem, because the
18 * size is constrained by the <TLV>'s L, even if the buffer size allows
19 * reading more data.
20 * For example, consider the buffer containing the following TLVs:
21 * <T:5><L:1><V> <T:6>...
22 * The TLV length clearly indicates that one byte is expected in V, but
23 * if the V processor returns with "want more data" even if the buffer
24 * contains way more data than the V processor have seen.
25 */
vlmb42843a2004-06-05 08:17:50 +000026#define SIZE_VIOLATION (ctx->left != -1 && (size_t)ctx->left <= size)
vlmfa67ddc2004-06-03 03:38:44 +000027
28/*
29 * This macro "eats" the part of the buffer which is definitely "consumed",
30 * i.e. was correctly converted into local representation or rightfully skipped.
31 */
32#define ADVANCE(num_bytes) do { \
33 size_t num = num_bytes; \
vlm1ff928d2004-08-11 08:10:13 +000034 (char *)ptr += num; \
vlmfa67ddc2004-06-03 03:38:44 +000035 size -= num; \
36 if(ctx->left >= 0) \
37 ctx->left -= num; \
38 consumed_myself += num; \
39 } while(0)
40
41/*
42 * Switch to the next phase of parsing.
43 */
44#define NEXT_PHASE(ctx) do { \
45 ctx->phase++; \
46 ctx->step = 0; \
47 } while(0)
48#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0)
49
50/*
51 * Return a standardized complex structure.
52 */
53#define RETURN(_code) do { \
54 rval.code = _code; \
55 rval.consumed = consumed_myself;\
56 return rval; \
57 } while(0)
58
59/*
60 * The decoder of the SET OF type.
61 */
62ber_dec_rval_t
63SET_OF_decode_ber(asn1_TYPE_descriptor_t *sd,
64 void **struct_ptr, void *ptr, size_t size, int tag_mode) {
65 /*
66 * Bring closer parts of structure description.
67 */
vlmda674682004-08-11 09:07:36 +000068 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)sd->specifics;
vlmfa67ddc2004-06-03 03:38:44 +000069 asn1_SET_OF_element_t *element = specs->element;
70
71 /*
72 * Parts of the structure being constructed.
73 */
74 void *st = *struct_ptr; /* Target structure. */
75 ber_dec_ctx_t *ctx; /* Decoder context */
76
77 ber_tlv_tag_t tlv_tag; /* T from TLV */
78 //ber_tlv_len_t tlv_len; /* L from TLV */
79 ber_dec_rval_t rval; /* Return code from subparsers */
80
81 ssize_t consumed_myself = 0; /* Consumed bytes from ptr */
82
83 ASN_DEBUG("Decoding %s as SET OF", sd->name);
84
85 /*
86 * Create the target structure if it is not present already.
87 */
88 if(st == 0) {
89 st = *struct_ptr = CALLOC(1, specs->struct_size);
90 if(st == 0) {
91 RETURN(RC_FAIL);
92 }
93 }
94
95 /*
96 * Restore parsing context.
97 */
vlm1ff928d2004-08-11 08:10:13 +000098 ctx = (ber_dec_ctx_t *)((char *)st + specs->ctx_offset);
vlmfa67ddc2004-06-03 03:38:44 +000099
100 /*
101 * Start to parse where left previously
102 */
103 switch(ctx->phase) {
104 case 0:
105 /*
106 * PHASE 0.
107 * Check that the set of tags associated with given structure
108 * perfectly fits our expectations.
109 */
110
111 rval = ber_check_tags(sd, ctx, ptr, size,
112 tag_mode, &ctx->left, 0);
113 if(rval.code != RC_OK) {
114 ASN_DEBUG("%s tagging check failed: %d",
115 sd->name, rval.code);
116 consumed_myself += rval.consumed;
117 RETURN(rval.code);
118 }
119
120 if(ctx->left >= 0)
121 ctx->left += rval.consumed; /* ?Substracted below! */
122 ADVANCE(rval.consumed);
123
124 ASN_DEBUG("Structure consumes %ld bytes, "
125 "buffer %ld", (long)ctx->left, (long)size);
126
127 NEXT_PHASE(ctx);
128 /* Fall through */
129 case 1:
130 /*
131 * PHASE 1.
132 * From the place where we've left it previously,
133 * try to decode the next item.
134 */
135 for(;; ctx->step = 0) {
136 ssize_t tag_len; /* Length of TLV's T */
137
138 if(ctx->step & 1)
139 goto microphase2;
140
141 /*
142 * MICROPHASE 1: Synchronize decoding.
143 */
144
145 if(ctx->left == 0) {
146 ASN_DEBUG("End of SET OF %s", sd->name);
147 /*
148 * No more things to decode.
149 * Exit out of here.
150 */
151 PHASE_OUT(ctx);
152 RETURN(RC_OK);
153 }
154
155 /*
156 * Fetch the T from TLV.
157 */
158 tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag);
159 switch(tag_len) {
160 case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE);
161 /* Fall through */
162 case -1: RETURN(RC_FAIL);
163 }
164
165 if(ctx->left < 0 && ((uint8_t *)ptr)[0] == 0) {
166 if(LEFT < 2) {
167 if(SIZE_VIOLATION)
168 RETURN(RC_FAIL);
169 else
170 RETURN(RC_WMORE);
171 } else if(((uint8_t *)ptr)[1] == 0) {
172 /*
173 * Found the terminator of the
174 * indefinite length structure.
175 */
176 break;
177 }
178 }
179
180 /* Outmost tag may be unknown and cannot be fetched/compared */
vlmb42843a2004-06-05 08:17:50 +0000181 if(element->tag != (ber_tlv_tag_t)-1) {
vlmfa67ddc2004-06-03 03:38:44 +0000182 if(BER_TAGS_EQUAL(tlv_tag, element->tag)) {
183 /*
184 * The new list member of expected type has arrived.
185 */
186 } else {
187 ASN_DEBUG("Unexpected tag %s fixed SET OF %s",
188 ber_tlv_tag_string(tlv_tag), sd->name);
189 ASN_DEBUG("%s SET OF has tag %s",
190 sd->name, ber_tlv_tag_string(element->tag));
191 RETURN(RC_FAIL);
192 }
193 }
194
195 /*
196 * MICROPHASE 2: Invoke the member-specific decoder.
197 */
198 ctx->step |= 1; /* Confirm entering next microphase */
199 microphase2:
200
201 /*
202 * Invoke the member fetch routine according to member's type
203 */
vlmda674682004-08-11 09:07:36 +0000204 rval = element->type->ber_decoder(element->type,
vlmfa67ddc2004-06-03 03:38:44 +0000205 &ctx->ptr, ptr, LEFT, 0);
206 ASN_DEBUG("In %s SET OF %s code %d consumed %d",
207 sd->name, element->type->name,
208 rval.code, (int)rval.consumed);
209 switch(rval.code) {
210 case RC_OK:
211 {
vlmda674682004-08-11 09:07:36 +0000212 A_SET_OF(void) *list;
213 (void *)list = st;
vlmfa67ddc2004-06-03 03:38:44 +0000214 if(ASN_SET_ADD(list, ctx->ptr) != 0)
215 RETURN(RC_FAIL);
216 else
217 ctx->ptr = 0;
218 }
219 break;
220 case RC_WMORE: /* More data expected */
221 if(!SIZE_VIOLATION) {
222 ADVANCE(rval.consumed);
223 RETURN(RC_WMORE);
224 }
225 /* Fall through */
226 case RC_FAIL: /* Fatal error */
227 RETURN(RC_FAIL);
228 } /* switch(rval) */
229
230 ADVANCE(rval.consumed);
231 } /* for(all list members) */
232
233 NEXT_PHASE(ctx);
234 case 2:
235 /*
236 * Read in all "end of content" TLVs.
237 */
238 while(ctx->left < 0) {
239 if(LEFT < 2) {
240 if(LEFT > 0 && ((char *)ptr)[0] != 0) {
241 /* Unexpected tag */
242 RETURN(RC_FAIL);
243 } else {
244 RETURN(RC_WMORE);
245 }
246 }
247 if(((char *)ptr)[0] == 0
248 && ((char *)ptr)[1] == 0) {
249 ADVANCE(2);
250 ctx->left++;
251 } else {
252 RETURN(RC_FAIL);
253 }
254 }
255
256 PHASE_OUT(ctx);
257 }
258
259 RETURN(RC_OK);
260}
261
262/*
263 * Internally visible buffer holding a single encoded element.
264 */
265struct _el_buffer {
266 uint8_t *buf;
267 size_t length;
268 size_t size;
269};
270/* Append bytes to the above structure */
271static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) {
vlmda674682004-08-11 09:07:36 +0000272 struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000273
274 if(el_buf->length + size > el_buf->size)
275 return -1;
276
277 memcpy(el_buf->buf + el_buf->length, buffer, size);
278
279 el_buf->length += size;
280 return 0;
281}
282static int _el_buf_cmp(const void *ap, const void *bp) {
vlmda674682004-08-11 09:07:36 +0000283 const struct _el_buffer *a = (const struct _el_buffer *)ap;
284 const struct _el_buffer *b = (const struct _el_buffer *)bp;
vlmfa67ddc2004-06-03 03:38:44 +0000285 int ret;
286 size_t common_len;
287
288 if(a->length < b->length)
289 common_len = a->length;
290 else
291 common_len = b->length;
292
293 ret = memcmp(a->buf, b->buf, common_len);
294 if(ret == 0) {
295 if(a->length < b->length)
296 ret = -1;
297 else if(a->length > b->length)
298 ret = 1;
299 }
300
301 return ret;
302}
303
304/*
305 * The DER encoder of the SET OF type.
306 */
307der_enc_rval_t
308SET_OF_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
309 int tag_mode, ber_tlv_tag_t tag,
310 asn_app_consume_bytes_f *cb, void *app_key) {
vlmda674682004-08-11 09:07:36 +0000311 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)sd->specifics;
vlmfa67ddc2004-06-03 03:38:44 +0000312 asn1_SET_OF_element_t *elm = specs->element;
313 asn1_TYPE_descriptor_t *elm_type = elm->type;
314 der_type_encoder_f *der_encoder = elm_type->der_encoder;
vlmda674682004-08-11 09:07:36 +0000315 A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000316 size_t computed_size = 0;
317 ssize_t encoding_size = 0;
318 struct _el_buffer *encoded_els;
319 size_t max_encoded_len = 1;
320 der_enc_rval_t erval;
321 int ret;
322 int edx;
323
324 ASN_DEBUG("Estimating size for SET OF %s", sd->name);
325
326 /*
327 * Gather the length of the underlying members sequence.
328 */
vlmda674682004-08-11 09:07:36 +0000329 (void *)list = ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000330 for(edx = 0; edx < list->count; edx++) {
331 void *memb_ptr = list->array[edx];
332 erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0);
333 if(erval.encoded == -1)
334 return erval;
335 computed_size += erval.encoded;
336
337 /* Compute maximum encoding's size */
vlmb42843a2004-06-05 08:17:50 +0000338 if(max_encoded_len < (size_t)erval.encoded)
vlmfa67ddc2004-06-03 03:38:44 +0000339 max_encoded_len = erval.encoded;
340 }
341
342 /*
343 * Encode the TLV for the sequence itself.
344 */
345 encoding_size = der_write_tags(sd, computed_size, tag_mode, tag,
346 cb, app_key);
347 if(encoding_size == -1) {
348 erval.encoded = -1;
349 erval.failed_type = sd;
350 erval.structure_ptr = ptr;
351 return erval;
352 }
353 computed_size += encoding_size;
354
355 if(!cb) {
356 erval.encoded = computed_size;
357 return erval;
358 }
359
360 /*
361 * DER mandates dynamic sorting of the SET OF elements
362 * according to their encodings. Build an array of the
363 * encoded elements.
364 */
vlmda674682004-08-11 09:07:36 +0000365 (void *)encoded_els = MALLOC(list->count * sizeof(encoded_els[0]));
vlmfa67ddc2004-06-03 03:38:44 +0000366 if(encoded_els == NULL) {
367 erval.encoded = -1;
368 erval.failed_type = sd;
369 erval.structure_ptr = ptr;
370 return erval;
371 }
372
373 ASN_DEBUG("Encoding members of %s SET OF", sd->name);
374
375 /*
376 * Encode all members.
377 */
378 for(edx = 0; edx < list->count; edx++) {
379 void *memb_ptr = list->array[edx];
380 struct _el_buffer *encoded_el = &encoded_els[edx];
381
382 /*
383 * Prepare space for encoding.
384 */
vlmda674682004-08-11 09:07:36 +0000385 encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len);
vlmfa67ddc2004-06-03 03:38:44 +0000386 if(encoded_el->buf) {
387 encoded_el->length = 0;
388 encoded_el->size = max_encoded_len;
389 } else {
390 for(edx--; edx >= 0; edx--)
391 FREEMEM(encoded_els[edx].buf);
392 FREEMEM(encoded_els);
393 erval.encoded = -1;
394 erval.failed_type = sd;
395 erval.structure_ptr = ptr;
396 return erval;
397 }
398
399 /*
400 * Encode the member into the prepared space.
401 */
402 erval = der_encoder(elm_type, memb_ptr, 0, elm->tag,
403 _el_addbytes, encoded_el);
404 if(erval.encoded == -1) {
405 for(; edx >= 0; edx--)
406 FREEMEM(encoded_els[edx].buf);
407 FREEMEM(encoded_els);
408 return erval;
409 }
410 encoding_size += erval.encoded;
411 }
412
413 /*
414 * Sort the encoded elements according to their encoding.
415 */
416 qsort(encoded_els, list->count, sizeof(encoded_els[0]), _el_buf_cmp);
417
418 /*
419 * Report encoded elements to the application.
420 * Dispose of temporary sorted members table.
421 */
422 ret = 0;
423 for(edx = 0; edx < list->count; edx++) {
424 struct _el_buffer *encoded_el = &encoded_els[edx];
425 /* Report encoded chunks to the application */
426 if(ret == 0
427 && cb(encoded_el->buf, encoded_el->length, app_key) == -1)
428 ret = -1;
429 FREEMEM(encoded_el->buf);
430 }
431 FREEMEM(encoded_els);
432
vlmb42843a2004-06-05 08:17:50 +0000433 if(ret || computed_size != (size_t)encoding_size) {
vlmfa67ddc2004-06-03 03:38:44 +0000434 /*
435 * Standard callback failed, or
436 * encoded size is not equal to the computed size.
437 */
438 erval.encoded = -1;
439 erval.failed_type = sd;
440 erval.structure_ptr = ptr;
441 } else {
442 erval.encoded = computed_size;
443 }
444
445 return erval;
446}
447
448int
449SET_OF_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
450 asn_app_consume_bytes_f *cb, void *app_key) {
vlmda674682004-08-11 09:07:36 +0000451 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
vlmfa67ddc2004-06-03 03:38:44 +0000452 asn1_SET_OF_element_t *element = specs->element;
vlmda674682004-08-11 09:07:36 +0000453 const A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000454 int ret;
455 int i;
456
457 if(!sptr) return cb("<absent>", 8, app_key);
458
459 /* Dump preamble */
460 if(cb(td->name, strlen(td->name), app_key)
461 || cb(" ::= {\n", 7, app_key))
462 return -1;
463
vlme5174082004-08-11 09:34:42 +0000464 (const void *)list = sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000465 for(i = 0; i < list->count; i++) {
466 const void *memb_ptr = list->array[i];
467 if(!memb_ptr) continue;
468
469 /* Indentation */
470 for(ret = 0; ret < ilevel; ret++) cb(" ", 1, app_key);
471
472 ret = element->type->print_struct(element->type, memb_ptr,
473 ilevel + 4, cb, app_key);
474 if(ret) return ret;
475
476 ret = cb("\n", 1, app_key);
477 if(ret) return ret;
478 }
479
480 /* Indentation */
481 for(ret = 0; ret < ilevel - 4; ret++) cb(" ", 1, app_key);
482
483 return cb("}", 1, app_key);
484}
485
486void
487SET_OF_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
488 if(td && ptr) {
vlmda674682004-08-11 09:07:36 +0000489 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
vlmfa67ddc2004-06-03 03:38:44 +0000490 asn1_SET_OF_element_t *element = specs->element;
vlmda674682004-08-11 09:07:36 +0000491 A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000492 int i;
493
494 /*
495 * Could not use set_of_empty() because of (*free)
496 * incompatibility.
497 */
vlmda674682004-08-11 09:07:36 +0000498 (void *)list = ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000499 for(i = 0; i < list->count; i++) {
500 void *memb_ptr = list->array[i];
501 if(memb_ptr)
502 element->type->free_struct(element->type, memb_ptr, 0);
503 }
vlm7ebd67c2004-07-15 10:51:26 +0000504 list->count = 0; /* No meaningful elements left */
505
506 asn_set_empty(list); /* Remove (list->array) */
vlmfa67ddc2004-06-03 03:38:44 +0000507
508 if(!contents_only) {
509 FREEMEM(ptr);
510 }
511 }
512}
513
514int
515SET_OF_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
516 asn_app_consume_bytes_f *app_errlog, void *app_key) {
vlmda674682004-08-11 09:07:36 +0000517 asn1_SET_OF_specifics_t *specs = (asn1_SET_OF_specifics_t *)td->specifics;
vlmfa67ddc2004-06-03 03:38:44 +0000518 asn1_SET_OF_element_t *element = specs->element;
vlmda674682004-08-11 09:07:36 +0000519 const A_SET_OF(void) *list;
vlmfa67ddc2004-06-03 03:38:44 +0000520 int i;
521
522 if(!sptr) {
vlme3f0f282004-08-11 09:44:13 +0000523 _ASN_ERRLOG(app_errlog, app_key,
524 "%s: value not given", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000525 return -1;
526 }
527
vlme5174082004-08-11 09:34:42 +0000528 (const void *)list = sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000529 for(i = 0; i < list->count; i++) {
530 const void *memb_ptr = list->array[i];
531 if(!memb_ptr) continue;
532 return element->type->check_constraints(element->type, memb_ptr,
533 app_errlog, app_key);
534 }
535
536 return 0;
537}