2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <OCTET_STRING.h>
8 #include <BIT_STRING.h> /* for .bits_unused member */
11 #define _CH_PHASE(ctx, inc) do {\
18 #define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
20 #define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
23 #define ADVANCE(num_bytes) do {\
24 size_t num = (num_bytes);\
25 buf_ptr = ((const char *)buf_ptr) + num;\
27 consumed_myself += num;\
31 #define RETURN(_code) do {\
32 asn_dec_rval_t tmprval;\
33 tmprval.code = _code;\
34 tmprval.consumed = consumed_myself;\
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);\
47 /* Be nice and round to the memory allocator */\
48 do { _ns = _ns ? _ns << 1 : 16; }\
50 /* int is really a typeof(st->size): */\
51 if((int)_ns < 0) RETURN(RC_FAIL);\
52 ptr = REALLOC(st->buf, _ns);\
54 st->buf = (uint8_t *)ptr;\
59 ASN_DEBUG("Reallocating into %ld", (long)_ns);\
61 memcpy(st->buf + st->size, bufptr, _bs);\
62 /* Convenient nul-termination */\
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.
73 static struct _stack_el *
74 OS__add_stack_el(struct _stack *st) {
75 struct _stack_el *nel;
78 * Reuse the old stack frame or allocate a new one.
80 if(st->cur_ptr && st->cur_ptr->next) {
81 nel = st->cur_ptr->next;
82 nel->bits_chopped = 0;
84 /* Retain the nel->cont_level, it's correct. */
86 nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
91 /* Increase a subcontainment depth */
92 nel->cont_level = st->tail->cont_level + 1;
104 static struct _stack *
106 return (struct _stack *)CALLOC(1, sizeof(struct _stack));
110 * Decode OCTET STRING type.
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;
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 */
126 enum asn_OS_Subvariant type_variant = specs->subvariant;
128 ASN_DEBUG("Decoding %s as %s (frame %ld)",
130 (type_variant == ASN_OSUBV_STR) ?
131 "OCTET STRING" : "OS-SpecialCase",
135 * Create the string if does not exist.
138 st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
139 if(st == NULL) RETURN(RC_FAIL);
142 /* Restore parsing context */
143 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
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)
158 * Complex operation, requires stack of expectations.
160 ctx->ptr = _new_stack();
166 * Jump into stackless primitive decoding.
169 if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
170 APPEND(buf_ptr, rval.consumed);
171 ADVANCE(rval.consumed);
180 * Fill the stack with expectations.
182 stck = (struct _stack *)ctx->ptr;
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);
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)
199 if(sel && sel->left <= 0 && sel->want_nulls == 0) {
201 struct _stack_el *prev = sel->prev;
202 if(prev->left != -1) {
203 if(prev->left < sel->got)
205 prev->left -= sel->got;
207 prev->got += sel->got;
208 sel = stck->cur_ptr = prev;
213 sel = stck->cur_ptr = 0;
214 break; /* Nothing to wait */
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),
225 case -1: RETURN(RC_FAIL);
226 case 0: RETURN(RC_WMORE);
229 tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
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);
237 case -1: RETURN(RC_FAIL);
238 case 0: RETURN(RC_WMORE);
241 if(sel && sel->want_nulls
242 && ((const uint8_t *)buf_ptr)[0] == 0
243 && ((const uint8_t *)buf_ptr)[1] == 0)
245 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
247 if(type_variant == ASN_OSUBV_ANY
248 && (tag_mode != 1 || sel->cont_level))
253 if(sel->left != -1) {
254 sel->left -= 2; /* assert(sel->left >= 2) */
258 if(sel->want_nulls == 0) {
259 /* Move to the next expectation */
268 * Set up expected tags,
269 * depending on ASN.1 type being decoded.
271 switch(type_variant) {
273 /* X.690: 8.6.4.1, NOTE 2 */
278 unsigned level = sel->cont_level;
279 if(level < td->all_tags_count) {
280 expected_tag = td->all_tags[level];
282 } else if(td->all_tags_count) {
283 expected_tag = td->all_tags
284 [td->all_tags_count - 1];
287 /* else, Fall through */
291 expected_tag = tlv_tag;
295 if(tlv_tag != expected_tag) {
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",
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",
315 * Append a new expectation.
317 sel = OS__add_stack_el(stck);
318 if(!sel) RETURN(RC_FAIL);
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))
328 sel->left = sel->prev->left - tlvl;
334 if(type_variant == ASN_OSUBV_ANY
335 && (tag_mode != 1 || sel->cont_level))
336 APPEND(buf_ptr, tlvl);
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);
346 /* Finished operation, "phase out" */
347 ASN_DEBUG("Phase out");
355 stck = (struct _stack *)ctx->ptr;
357 ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
358 (long)sel->left, (long)size, (long)sel->got,
363 assert(sel->left >= 0);
365 len = ((ber_tlv_len_t)size < sel->left)
366 ? (ber_tlv_len_t)size : sel->left;
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;
375 APPEND(buf_ptr, len);
383 ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
384 (long)sel->left, (long)size, sel->want_nulls);
395 * Primitive form, no stack required.
397 assert(ctx->left >= 0);
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;
406 APPEND(buf_ptr, size);
407 assert(ctx->context > 0);
412 if(type_variant == ASN_OSUBV_BIT
413 && !ctx->context && ctx->left) {
414 st->bits_unused = *(const uint8_t *)buf_ptr;
418 APPEND(buf_ptr, ctx->left);
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) {
437 * BIT STRING-specific processing.
439 if(type_variant == ASN_OSUBV_BIT) {
441 if(st->bits_unused < 0 || st->bits_unused > 7) {
444 /* Finalize BIT STRING: zero out unused bits. */
445 st->buf[st->size-1] &= 0xff << st->bits_unused;
447 if(st->bits_unused) {
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>",
463 * Encode OCTET STRING type using DER.
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;
477 ASN_DEBUG("%s %s as OCTET STRING",
478 cb?"Estimating":"Encoding", td->name);
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,
488 if(er.encoded == -1) {
490 er.structure_ptr = sptr;
494 /* Disallow: [<tag>] IMPLICIT ANY */
495 assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
500 er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
505 * Prepare to deal with the last octet of BIT STRING.
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);
513 /* Invoke callback for the main part of the buffer */
514 ASN__CALLBACK(st->buf, st->size - fix_last_byte);
516 /* The last octet should be stripped off the unused bits */
518 uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
519 ASN__CALLBACK(&b, 1);