SIM-115: update simulator to use latest E2SM KPM version 3
[sim/e2-interface.git] / e2sim / asn1c / OCTET_STRING_ber.c
1 /*
2  * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
3  * All rights reserved.
4  * Redistribution and modifications are permitted subject to BSD license.
5  */
6 #include <asn_internal.h>
7 #include <OCTET_STRING.h>
8 #include <BIT_STRING.h> /* for .bits_unused member */
9
10 #undef _CH_PHASE
11 #define _CH_PHASE(ctx, inc) do {\
12         if(ctx->phase == 0)\
13             ctx->context = 0;\
14         ctx->phase += inc;\
15     } while(0)
16
17 #undef NEXT_PHASE
18 #define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
19 #undef PREV_PHASE
20 #define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
21
22 #undef ADVANCE
23 #define ADVANCE(num_bytes) do {\
24         size_t num = (num_bytes);\
25         buf_ptr = ((const char *)buf_ptr) + num;\
26         size -= num;\
27         consumed_myself += num;\
28     } while(0)
29
30 #undef RETURN
31 #define RETURN(_code) do {\
32         asn_dec_rval_t tmprval;\
33         tmprval.code = _code;\
34         tmprval.consumed = consumed_myself;\
35         return tmprval;\
36     } while(0)
37
38 #undef APPEND
39 #define APPEND(bufptr, bufsize) do {\
40         size_t _bs = (bufsize);  /* Append size */\
41         size_t _ns = ctx->context;  /* Allocated now */\
42         size_t _es = st->size + _bs;  /* Expected size */\
43         /* int is really a typeof(st->size): */\
44         if((int)_es < 0) RETURN(RC_FAIL);\
45         if(_ns <= _es) {\
46             void *ptr;\
47             /* Be nice and round to the memory allocator */\
48             do { _ns = _ns ? _ns << 1 : 16; }\
49                 while(_ns <= _es);\
50             /* int is really a typeof(st->size): */\
51             if((int)_ns < 0) RETURN(RC_FAIL);\
52             ptr = REALLOC(st->buf, _ns);\
53             if(ptr) {\
54                 st->buf = (uint8_t *)ptr;\
55                 ctx->context = _ns;\
56             } else {\
57                 RETURN(RC_FAIL);\
58             }\
59             ASN_DEBUG("Reallocating into %ld", (long)_ns);\
60         }\
61         memcpy(st->buf + st->size, bufptr, _bs);\
62         /* Convenient nul-termination */\
63         st->buf[_es] = '\0';\
64         st->size = _es;\
65     } while(0)
66
67 /*
68  * The main reason why ASN.1 is still alive is that too much time and effort
69  * is necessary for learning it more or less adequately, thus creating a gut
70  * necessity to demonstrate that acquired skill everywhere afterwards.
71  * No, I am not going to explain what the following stuff is.
72  */
73 static struct _stack_el *
74 OS__add_stack_el(struct _stack *st) {
75     struct _stack_el *nel;
76
77     /*
78      * Reuse the old stack frame or allocate a new one.
79      */
80     if(st->cur_ptr && st->cur_ptr->next) {
81         nel = st->cur_ptr->next;
82         nel->bits_chopped = 0;
83         nel->got = 0;
84         /* Retain the nel->cont_level, it's correct. */
85     } else {
86         nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
87         if(nel == NULL)
88             return NULL;
89
90         if(st->tail) {
91             /* Increase a subcontainment depth */
92             nel->cont_level = st->tail->cont_level + 1;
93             st->tail->next = nel;
94         }
95         nel->prev = st->tail;
96         st->tail = nel;
97     }
98
99     st->cur_ptr = nel;
100
101     return nel;
102 }
103
104 static struct _stack *
105 _new_stack(void) {
106     return (struct _stack *)CALLOC(1, sizeof(struct _stack));
107 }
108
109 /*
110  * Decode OCTET STRING type.
111  */
112 asn_dec_rval_t
113 OCTET_STRING_decode_ber(const asn_codec_ctx_t *opt_codec_ctx,
114                         const asn_TYPE_descriptor_t *td, void **sptr,
115                         const void *buf_ptr, size_t size, int tag_mode) {
116     const asn_OCTET_STRING_specifics_t *specs = td->specifics
117         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
118         : &asn_SPC_OCTET_STRING_specs;
119     BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
120     asn_dec_rval_t rval;
121     asn_struct_ctx_t *ctx;
122     ssize_t consumed_myself = 0;
123     struct _stack *stck;  /* Expectations stack structure */
124     struct _stack_el *sel = 0;  /* Stack element */
125     int tlv_constr;
126     enum asn_OS_Subvariant type_variant = specs->subvariant;
127
128     ASN_DEBUG("Decoding %s as %s (frame %ld)",
129         td->name,
130         (type_variant == ASN_OSUBV_STR) ?
131             "OCTET STRING" : "OS-SpecialCase",
132         (long)size);
133
134     /*
135      * Create the string if does not exist.
136      */
137     if(st == NULL) {
138         st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
139         if(st == NULL) RETURN(RC_FAIL);
140     }
141
142     /* Restore parsing context */
143     ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
144
145     switch(ctx->phase) {
146     case 0:
147         /*
148          * Check tags.
149          */
150         rval = ber_check_tags(opt_codec_ctx, td, ctx,
151             buf_ptr, size, tag_mode, -1,
152             &ctx->left, &tlv_constr);
153         if(rval.code != RC_OK)
154             return rval;
155
156         if(tlv_constr) {
157             /*
158              * Complex operation, requires stack of expectations.
159              */
160             ctx->ptr = _new_stack();
161             if(!ctx->ptr) {
162                 RETURN(RC_FAIL);
163             }
164         } else {
165             /*
166              * Jump into stackless primitive decoding.
167              */
168             _CH_PHASE(ctx, 3);
169             if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
170                 APPEND(buf_ptr, rval.consumed);
171             ADVANCE(rval.consumed);
172             goto phase3;
173         }
174
175         NEXT_PHASE(ctx);
176         /* Fall through */
177     case 1:
178     phase1:
179         /*
180          * Fill the stack with expectations.
181          */
182         stck = (struct _stack *)ctx->ptr;
183         sel = stck->cur_ptr;
184         do {
185             ber_tlv_tag_t tlv_tag;
186             ber_tlv_len_t tlv_len;
187             ber_tlv_tag_t expected_tag;
188             ssize_t tl, ll, tlvl;
189             /* This one works even if (sel->left == -1) */
190             size_t Left = ((!sel||(size_t)sel->left >= size)
191                 ?size:(size_t)sel->left);
192
193
194             ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", (void *)sel,
195                       (long)(sel?sel->left:0),
196                       (long)(sel?sel->want_nulls:0),
197                       (long)(sel?sel->got:0)
198             );
199             if(sel && sel->left <= 0 && sel->want_nulls == 0) {
200                 if(sel->prev) {
201                     struct _stack_el *prev = sel->prev;
202                     if(prev->left != -1) {
203                         if(prev->left < sel->got)
204                             RETURN(RC_FAIL);
205                         prev->left -= sel->got;
206                     }
207                     prev->got += sel->got;
208                     sel = stck->cur_ptr = prev;
209                     if(!sel) break;
210                     tlv_constr = 1;
211                     continue;
212                 } else {
213                     sel = stck->cur_ptr = 0;
214                     break;  /* Nothing to wait */
215                 }
216             }
217
218             tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
219             ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
220                       (long)size, (long)Left, sel?"":"!",
221                       (long)(sel?sel->left:0),
222                       (long)(sel?sel->want_nulls:0),
223                       (long)tl);
224             switch(tl) {
225             case -1: RETURN(RC_FAIL);
226             case 0: RETURN(RC_WMORE);
227             }
228
229             tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
230
231             ll = ber_fetch_length(tlv_constr,
232                                   (const char *)buf_ptr + tl,Left - tl,&tlv_len);
233             ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
234                       ber_tlv_tag_string(tlv_tag), tlv_constr,
235                       (long)Left, (long)tl, (long)tlv_len, (long)ll);
236             switch(ll) {
237             case -1: RETURN(RC_FAIL);
238             case 0: RETURN(RC_WMORE);
239             }
240
241             if(sel && sel->want_nulls
242                 && ((const uint8_t *)buf_ptr)[0] == 0
243                 && ((const uint8_t *)buf_ptr)[1] == 0)
244             {
245                 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
246
247                 if(type_variant == ASN_OSUBV_ANY
248                 && (tag_mode != 1 || sel->cont_level))
249                     APPEND("\0\0", 2);
250
251                 ADVANCE(2);
252                 sel->got += 2;
253                 if(sel->left != -1) {
254                     sel->left -= 2;  /* assert(sel->left >= 2) */
255                 }
256
257                 sel->want_nulls--;
258                 if(sel->want_nulls == 0) {
259                     /* Move to the next expectation */
260                     sel->left = 0;
261                     tlv_constr = 1;
262                 }
263
264                 continue;
265             }
266
267             /*
268              * Set up expected tags,
269              * depending on ASN.1 type being decoded.
270              */
271             switch(type_variant) {
272             case ASN_OSUBV_BIT:
273                 /* X.690: 8.6.4.1, NOTE 2 */
274                 /* Fall through */
275             case ASN_OSUBV_STR:
276             default:
277                 if(sel) {
278                     unsigned level = sel->cont_level;
279                     if(level < td->all_tags_count) {
280                         expected_tag = td->all_tags[level];
281                         break;
282                     } else if(td->all_tags_count) {
283                         expected_tag = td->all_tags
284                             [td->all_tags_count - 1];
285                         break;
286                     }
287                     /* else, Fall through */
288                 }
289                 /* Fall through */
290             case ASN_OSUBV_ANY:
291                 expected_tag = tlv_tag;
292                 break;
293             }
294
295             if(tlv_tag != expected_tag) {
296                 char buf[2][32];
297                 ber_tlv_tag_snprint(tlv_tag,
298                                     buf[0], sizeof(buf[0]));
299                 ber_tlv_tag_snprint(td->tags[td->tags_count-1],
300                                     buf[1], sizeof(buf[1]));
301                 ASN_DEBUG("Tag does not match expectation: %s != %s",
302                           buf[0], buf[1]);
303                 RETURN(RC_FAIL);
304             }
305
306             tlvl = tl + ll;  /* Combined length of T and L encoding */
307             if((tlv_len + tlvl) < 0) {
308                 /* tlv_len value is too big */
309                 ASN_DEBUG("TLV encoding + length (%ld) is too big",
310                           (long)tlv_len);
311                 RETURN(RC_FAIL);
312             }
313
314             /*
315              * Append a new expectation.
316              */
317             sel = OS__add_stack_el(stck);
318             if(!sel) RETURN(RC_FAIL);
319
320             sel->tag = tlv_tag;
321
322             sel->want_nulls = (tlv_len==-1);
323             if(sel->prev && sel->prev->left != -1) {
324                 /* Check that the parent frame is big enough */
325                 if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
326                     RETURN(RC_FAIL);
327                 if(tlv_len == -1)
328                     sel->left = sel->prev->left - tlvl;
329                 else
330                     sel->left = tlv_len;
331             } else {
332                 sel->left = tlv_len;
333             }
334             if(type_variant == ASN_OSUBV_ANY
335             && (tag_mode != 1 || sel->cont_level))
336                 APPEND(buf_ptr, tlvl);
337             sel->got += tlvl;
338             ADVANCE(tlvl);
339
340             ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%u",
341                       (long)sel->got, (long)sel->left,
342                       sel->want_nulls, sel->cont_level);
343
344         } while(tlv_constr);
345         if(sel == NULL) {
346             /* Finished operation, "phase out" */
347             ASN_DEBUG("Phase out");
348             _CH_PHASE(ctx, +3);
349             break;
350         }
351
352         NEXT_PHASE(ctx);
353         /* Fall through */
354     case 2:
355         stck = (struct _stack *)ctx->ptr;
356         sel = stck->cur_ptr;
357         ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
358                   (long)sel->left, (long)size, (long)sel->got,
359                   sel->want_nulls);
360         {
361         ber_tlv_len_t len;
362
363         assert(sel->left >= 0);
364
365         len = ((ber_tlv_len_t)size < sel->left)
366             ? (ber_tlv_len_t)size : sel->left;
367         if(len > 0) {
368             if(type_variant == ASN_OSUBV_BIT
369             && sel->bits_chopped == 0) {
370                 /* Put the unused-bits-octet away */
371                 st->bits_unused = *(const uint8_t *)buf_ptr;
372                 APPEND(((const char *)buf_ptr+1), (len - 1));
373                 sel->bits_chopped = 1;
374             } else {
375                 APPEND(buf_ptr, len);
376             }
377             ADVANCE(len);
378             sel->left -= len;
379             sel->got += len;
380         }
381
382         if(sel->left) {
383             ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
384                       (long)sel->left, (long)size, sel->want_nulls);
385             RETURN(RC_WMORE);
386         }
387
388         PREV_PHASE(ctx);
389         goto phase1;
390         }
391         break;
392     case 3:
393     phase3:
394         /*
395          * Primitive form, no stack required.
396          */
397         assert(ctx->left >= 0);
398
399         if(size < (size_t)ctx->left) {
400             if(!size) RETURN(RC_WMORE);
401             if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
402                 st->bits_unused = *(const uint8_t *)buf_ptr;
403                 ctx->left--;
404                 ADVANCE(1);
405             }
406             APPEND(buf_ptr, size);
407             assert(ctx->context > 0);
408             ctx->left -= size;
409             ADVANCE(size);
410             RETURN(RC_WMORE);
411         } else {
412             if(type_variant == ASN_OSUBV_BIT
413             && !ctx->context && ctx->left) {
414                 st->bits_unused = *(const uint8_t *)buf_ptr;
415                 ctx->left--;
416                 ADVANCE(1);
417             }
418             APPEND(buf_ptr, ctx->left);
419             ADVANCE(ctx->left);
420             ctx->left = 0;
421
422             NEXT_PHASE(ctx);
423         }
424         break;
425     }
426
427     if(sel) {
428         ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
429                   (void *)sel->prev, sel->want_nulls,
430                   (long)sel->left, (long)sel->got, (long)size);
431         if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
432             RETURN(RC_WMORE);
433         }
434     }
435
436     /*
437      * BIT STRING-specific processing.
438      */
439     if(type_variant == ASN_OSUBV_BIT) {
440         if(st->size) {
441             if(st->bits_unused < 0 || st->bits_unused > 7) {
442                 RETURN(RC_FAIL);
443             }
444             /* Finalize BIT STRING: zero out unused bits. */
445             st->buf[st->size-1] &= 0xff << st->bits_unused;
446         } else {
447             if(st->bits_unused) {
448                 RETURN(RC_FAIL);
449             }
450         }
451     }
452
453     ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
454               (long)consumed_myself, td->name,
455               (type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "<data>",
456               (long)st->size);
457
458
459     RETURN(RC_OK);
460 }
461
462 /*
463  * Encode OCTET STRING type using DER.
464  */
465 asn_enc_rval_t
466 OCTET_STRING_encode_der(const asn_TYPE_descriptor_t *td, const void *sptr,
467                         int tag_mode, ber_tlv_tag_t tag,
468                         asn_app_consume_bytes_f *cb, void *app_key) {
469     asn_enc_rval_t er = { 0, 0, 0 };
470     const asn_OCTET_STRING_specifics_t *specs = td->specifics
471         ? (const asn_OCTET_STRING_specifics_t *)td->specifics
472         : &asn_SPC_OCTET_STRING_specs;
473     const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
474     enum asn_OS_Subvariant type_variant = specs->subvariant;
475     int fix_last_byte = 0;
476
477     ASN_DEBUG("%s %s as OCTET STRING",
478               cb?"Estimating":"Encoding", td->name);
479
480     /*
481      * Write tags.
482      */
483     if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
484         er.encoded = der_write_tags(td,
485                                     (type_variant == ASN_OSUBV_BIT) + st->size,
486                                     tag_mode, type_variant == ASN_OSUBV_ANY, tag,
487                                     cb, app_key);
488         if(er.encoded == -1) {
489             er.failed_type = td;
490             er.structure_ptr = sptr;
491             return er;
492         }
493     } else {
494         /* Disallow: [<tag>] IMPLICIT ANY */
495         assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
496         er.encoded = 0;
497     }
498
499     if(!cb) {
500         er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
501         ASN__ENCODED_OK(er);
502     }
503
504     /*
505      * Prepare to deal with the last octet of BIT STRING.
506      */
507     if(type_variant == ASN_OSUBV_BIT) {
508         uint8_t b = st->bits_unused & 0x07;
509         if(b && st->size) fix_last_byte = 1;
510         ASN__CALLBACK(&b, 1);
511     }
512
513     /* Invoke callback for the main part of the buffer */
514     ASN__CALLBACK(st->buf, st->size - fix_last_byte);
515
516     /* The last octet should be stripped off the unused bits */
517     if(fix_last_byte) {
518         uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
519         ASN__CALLBACK(&b, 1);
520     }
521
522     ASN__ENCODED_OK(er);
523 cb_failed:
524     ASN__ENCODE_FAILED;
525 }