blob: 3e424e7f97be59774f5f5f287443b983efdc7dbf [file] [log] [blame]
Harald Welte92c45f32010-06-12 18:59:38 +02001/*-
2 * Copyright (c) 2003, 2004, 2005, 2006 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#include <errno.h>
10
11/*
12 * OCTET STRING basic type description.
13 */
Harald Welte41b85d52015-08-31 08:56:53 +020014static const ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = {
Harald Welte92c45f32010-06-12 18:59:38 +020015 (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
16};
Harald Welte41b85d52015-08-31 08:56:53 +020017static const asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = {
Harald Welte92c45f32010-06-12 18:59:38 +020018 sizeof(OCTET_STRING_t),
19 offsetof(OCTET_STRING_t, _asn_ctx),
Harald Welteec0e2172010-07-20 00:03:44 +020020 ASN_OSUBV_STR
Harald Welte92c45f32010-06-12 18:59:38 +020021};
Harald Welte41b85d52015-08-31 08:56:53 +020022static const asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
Harald Welteec0e2172010-07-20 00:03:44 +020023 { APC_CONSTRAINED, 8, 8, 0, 255 },
24 { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
25 0, 0
Harald Welte92c45f32010-06-12 18:59:38 +020026};
27asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = {
28 "OCTET STRING", /* Canonical name */
29 "OCTET_STRING", /* XML tag name */
30 OCTET_STRING_free,
31 OCTET_STRING_print, /* non-ascii stuff, generally */
32 asn_generic_no_constraint,
33 OCTET_STRING_decode_ber,
34 OCTET_STRING_encode_der,
35 OCTET_STRING_decode_xer_hex,
36 OCTET_STRING_encode_xer,
37 OCTET_STRING_decode_uper, /* Unaligned PER decoder */
38 OCTET_STRING_encode_uper, /* Unaligned PER encoder */
Harald Welte41b85d52015-08-31 08:56:53 +020039 OCTET_STRING_decode_aper, /* Aligned PER decoder */
40 OCTET_STRING_encode_aper, /* Aligned PER encoder */
Harald Welte92c45f32010-06-12 18:59:38 +020041 0, /* Use generic outmost tag fetcher */
42 asn_DEF_OCTET_STRING_tags,
43 sizeof(asn_DEF_OCTET_STRING_tags)
44 / sizeof(asn_DEF_OCTET_STRING_tags[0]),
45 asn_DEF_OCTET_STRING_tags, /* Same as above */
46 sizeof(asn_DEF_OCTET_STRING_tags)
47 / sizeof(asn_DEF_OCTET_STRING_tags[0]),
48 0, /* No PER visible constraints */
49 0, 0, /* No members */
50 &asn_DEF_OCTET_STRING_specs
51};
52
53#undef _CH_PHASE
54#undef NEXT_PHASE
55#undef PREV_PHASE
56#define _CH_PHASE(ctx, inc) do { \
57 if(ctx->phase == 0) \
58 ctx->context = 0; \
59 ctx->phase += inc; \
60 } while(0)
61#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
62#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
63
64#undef ADVANCE
65#define ADVANCE(num_bytes) do { \
66 size_t num = (num_bytes); \
67 buf_ptr = ((const char *)buf_ptr) + num; \
68 size -= num; \
69 consumed_myself += num; \
70 } while(0)
71
72#undef RETURN
73#define RETURN(_code) do { \
74 asn_dec_rval_t tmprval; \
75 tmprval.code = _code; \
76 tmprval.consumed = consumed_myself; \
77 return tmprval; \
78 } while(0)
79
80#undef APPEND
81#define APPEND(bufptr, bufsize) do { \
82 size_t _bs = (bufsize); /* Append size */ \
83 size_t _ns = ctx->context; /* Allocated now */ \
84 size_t _es = st->size + _bs; /* Expected size */ \
85 /* int is really a typeof(st->size): */ \
86 if((int)_es < 0) RETURN(RC_FAIL); \
87 if(_ns <= _es) { \
88 void *ptr; \
89 /* Be nice and round to the memory allocator */ \
90 do { _ns = _ns ? _ns << 1 : 16; } \
91 while(_ns <= _es); \
92 /* int is really a typeof(st->size): */ \
93 if((int)_ns < 0) RETURN(RC_FAIL); \
94 ptr = REALLOC(st->buf, _ns); \
95 if(ptr) { \
96 st->buf = (uint8_t *)ptr; \
97 ctx->context = _ns; \
98 } else { \
99 RETURN(RC_FAIL); \
100 } \
101 ASN_DEBUG("Reallocating into %ld", (long)_ns); \
102 } \
103 memcpy(st->buf + st->size, bufptr, _bs); \
104 /* Convenient nul-termination */ \
105 st->buf[_es] = '\0'; \
106 st->size = _es; \
107 } while(0)
108
109/*
Harald Welte92c45f32010-06-12 18:59:38 +0200110 * The main reason why ASN.1 is still alive is that too much time and effort
111 * is necessary for learning it more or less adequately, thus creating a gut
112 * necessity to demonstrate that aquired skill everywhere afterwards.
113 * No, I am not going to explain what the following stuff is.
114 */
115struct _stack_el {
116 ber_tlv_len_t left; /* What's left to read (or -1) */
117 ber_tlv_len_t got; /* What was actually processed */
118 int cont_level; /* Depth of subcontainment */
119 int want_nulls; /* Want null "end of content" octets? */
120 int bits_chopped; /* Flag in BIT STRING mode */
121 ber_tlv_tag_t tag; /* For debugging purposes */
122 struct _stack_el *prev;
123 struct _stack_el *next;
124};
125struct _stack {
126 struct _stack_el *tail;
127 struct _stack_el *cur_ptr;
128};
129
130static struct _stack_el *
131OS__add_stack_el(struct _stack *st) {
132 struct _stack_el *nel;
133
134 /*
135 * Reuse the old stack frame or allocate a new one.
136 */
137 if(st->cur_ptr && st->cur_ptr->next) {
138 nel = st->cur_ptr->next;
139 nel->bits_chopped = 0;
140 nel->got = 0;
141 /* Retain the nel->cont_level, it's correct. */
142 } else {
143 nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el));
144 if(nel == NULL)
145 return NULL;
146
147 if(st->tail) {
148 /* Increase a subcontainment depth */
149 nel->cont_level = st->tail->cont_level + 1;
150 st->tail->next = nel;
151 }
152 nel->prev = st->tail;
153 st->tail = nel;
154 }
155
156 st->cur_ptr = nel;
157
158 return nel;
159}
160
161static struct _stack *
162_new_stack() {
163 return (struct _stack *)CALLOC(1, sizeof(struct _stack));
164}
165
166/*
167 * Decode OCTET STRING type.
168 */
169asn_dec_rval_t
170OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
171 asn_TYPE_descriptor_t *td,
172 void **sptr, const void *buf_ptr, size_t size, int tag_mode) {
173 asn_OCTET_STRING_specifics_t *specs = td->specifics
174 ? (asn_OCTET_STRING_specifics_t *)td->specifics
175 : &asn_DEF_OCTET_STRING_specs;
176 BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
177 asn_dec_rval_t rval;
178 asn_struct_ctx_t *ctx;
179 ssize_t consumed_myself = 0;
180 struct _stack *stck; /* Expectations stack structure */
181 struct _stack_el *sel = 0; /* Stack element */
182 int tlv_constr;
Harald Welteec0e2172010-07-20 00:03:44 +0200183 enum asn_OS_Subvariant type_variant = specs->subvariant;
Harald Welte92c45f32010-06-12 18:59:38 +0200184
185 ASN_DEBUG("Decoding %s as %s (frame %ld)",
186 td->name,
Harald Welteec0e2172010-07-20 00:03:44 +0200187 (type_variant == ASN_OSUBV_STR) ?
Harald Welte92c45f32010-06-12 18:59:38 +0200188 "OCTET STRING" : "OS-SpecialCase",
189 (long)size);
190
191 /*
192 * Create the string if does not exist.
193 */
194 if(st == NULL) {
195 st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
196 if(st == NULL) RETURN(RC_FAIL);
197 }
198
199 /* Restore parsing context */
200 ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset);
201
202 switch(ctx->phase) {
203 case 0:
204 /*
205 * Check tags.
206 */
207 rval = ber_check_tags(opt_codec_ctx, td, ctx,
208 buf_ptr, size, tag_mode, -1,
209 &ctx->left, &tlv_constr);
210 if(rval.code != RC_OK)
211 return rval;
212
213 if(tlv_constr) {
214 /*
215 * Complex operation, requires stack of expectations.
216 */
217 ctx->ptr = _new_stack();
218 if(ctx->ptr) {
219 stck = (struct _stack *)ctx->ptr;
220 } else {
221 RETURN(RC_FAIL);
222 }
223 } else {
224 /*
225 * Jump into stackless primitive decoding.
226 */
227 _CH_PHASE(ctx, 3);
Harald Welteec0e2172010-07-20 00:03:44 +0200228 if(type_variant == ASN_OSUBV_ANY && tag_mode != 1)
Harald Welte92c45f32010-06-12 18:59:38 +0200229 APPEND(buf_ptr, rval.consumed);
230 ADVANCE(rval.consumed);
231 goto phase3;
232 }
233
234 NEXT_PHASE(ctx);
235 /* Fall through */
236 case 1:
237 phase1:
238 /*
239 * Fill the stack with expectations.
240 */
241 stck = (struct _stack *)ctx->ptr;
242 sel = stck->cur_ptr;
243 do {
244 ber_tlv_tag_t tlv_tag;
245 ber_tlv_len_t tlv_len;
246 ber_tlv_tag_t expected_tag;
247 ssize_t tl, ll, tlvl;
248 /* This one works even if (sel->left == -1) */
249 ssize_t Left = ((!sel||(size_t)sel->left >= size)
250 ?(ssize_t)size:sel->left);
251
252
253 ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel,
254 (long)(sel?sel->left:0),
255 (long)(sel?sel->want_nulls:0),
256 (long)(sel?sel->got:0)
257 );
258 if(sel && sel->left <= 0 && sel->want_nulls == 0) {
259 if(sel->prev) {
260 struct _stack_el *prev = sel->prev;
261 if(prev->left != -1) {
262 if(prev->left < sel->got)
263 RETURN(RC_FAIL);
264 prev->left -= sel->got;
265 }
266 prev->got += sel->got;
267 sel = stck->cur_ptr = prev;
268 if(!sel) break;
269 tlv_constr = 1;
270 continue;
271 } else {
272 sel = stck->cur_ptr = 0;
273 break; /* Nothing to wait */
274 }
275 }
276
277 tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag);
278 ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld",
279 (long)size, (long)Left, sel?"":"!",
280 (long)(sel?sel->left:0),
281 (long)(sel?sel->want_nulls:0),
282 (long)tl);
283 switch(tl) {
284 case -1: RETURN(RC_FAIL);
285 case 0: RETURN(RC_WMORE);
286 }
287
288 tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
289
290 ll = ber_fetch_length(tlv_constr,
291 (const char *)buf_ptr + tl,Left - tl,&tlv_len);
292 ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld",
293 ber_tlv_tag_string(tlv_tag), tlv_constr,
294 (long)Left, (long)tl, (long)tlv_len, (long)ll);
295 switch(ll) {
296 case -1: RETURN(RC_FAIL);
297 case 0: RETURN(RC_WMORE);
298 }
299
300 if(sel && sel->want_nulls
301 && ((const uint8_t *)buf_ptr)[0] == 0
302 && ((const uint8_t *)buf_ptr)[1] == 0)
303 {
304
305 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
306
Harald Welteec0e2172010-07-20 00:03:44 +0200307 if(type_variant == ASN_OSUBV_ANY
Harald Welte92c45f32010-06-12 18:59:38 +0200308 && (tag_mode != 1 || sel->cont_level))
309 APPEND("\0\0", 2);
310
311 ADVANCE(2);
312 sel->got += 2;
313 if(sel->left != -1) {
314 sel->left -= 2; /* assert(sel->left >= 2) */
315 }
316
317 sel->want_nulls--;
318 if(sel->want_nulls == 0) {
319 /* Move to the next expectation */
320 sel->left = 0;
321 tlv_constr = 1;
322 }
323
324 continue;
325 }
326
327 /*
328 * Set up expected tags,
329 * depending on ASN.1 type being decoded.
330 */
331 switch(type_variant) {
Harald Welteec0e2172010-07-20 00:03:44 +0200332 case ASN_OSUBV_BIT:
Harald Welte92c45f32010-06-12 18:59:38 +0200333 /* X.690: 8.6.4.1, NOTE 2 */
334 /* Fall through */
Harald Welteec0e2172010-07-20 00:03:44 +0200335 case ASN_OSUBV_STR:
Harald Welte92c45f32010-06-12 18:59:38 +0200336 default:
337 if(sel) {
338 int level = sel->cont_level;
339 if(level < td->all_tags_count) {
340 expected_tag = td->all_tags[level];
341 break;
342 } else if(td->all_tags_count) {
343 expected_tag = td->all_tags
344 [td->all_tags_count - 1];
345 break;
346 }
347 /* else, Fall through */
348 }
349 /* Fall through */
Harald Welteec0e2172010-07-20 00:03:44 +0200350 case ASN_OSUBV_ANY:
Harald Welte92c45f32010-06-12 18:59:38 +0200351 expected_tag = tlv_tag;
352 break;
353 }
354
355
356 if(tlv_tag != expected_tag) {
357 char buf[2][32];
358 ber_tlv_tag_snprint(tlv_tag,
359 buf[0], sizeof(buf[0]));
360 ber_tlv_tag_snprint(td->tags[td->tags_count-1],
361 buf[1], sizeof(buf[1]));
362 ASN_DEBUG("Tag does not match expectation: %s != %s",
363 buf[0], buf[1]);
364 RETURN(RC_FAIL);
365 }
366
367 tlvl = tl + ll; /* Combined length of T and L encoding */
368 if((tlv_len + tlvl) < 0) {
369 /* tlv_len value is too big */
370 ASN_DEBUG("TLV encoding + length (%ld) is too big",
371 (long)tlv_len);
372 RETURN(RC_FAIL);
373 }
374
375 /*
376 * Append a new expectation.
377 */
378 sel = OS__add_stack_el(stck);
379 if(!sel) RETURN(RC_FAIL);
380
381 sel->tag = tlv_tag;
382
383 sel->want_nulls = (tlv_len==-1);
384 if(sel->prev && sel->prev->left != -1) {
385 /* Check that the parent frame is big enough */
386 if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len))
387 RETURN(RC_FAIL);
388 if(tlv_len == -1)
389 sel->left = sel->prev->left - tlvl;
390 else
391 sel->left = tlv_len;
392 } else {
393 sel->left = tlv_len;
394 }
Harald Welteec0e2172010-07-20 00:03:44 +0200395 if(type_variant == ASN_OSUBV_ANY
Harald Welte92c45f32010-06-12 18:59:38 +0200396 && (tag_mode != 1 || sel->cont_level))
397 APPEND(buf_ptr, tlvl);
398 sel->got += tlvl;
399 ADVANCE(tlvl);
400
401 ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d",
402 (long)sel->got, (long)sel->left,
403 sel->want_nulls, sel->cont_level);
404
405 } while(tlv_constr);
406 if(sel == NULL) {
407 /* Finished operation, "phase out" */
408 ASN_DEBUG("Phase out");
409 _CH_PHASE(ctx, +3);
410 break;
411 }
412
413 NEXT_PHASE(ctx);
414 /* Fall through */
415 case 2:
416 stck = (struct _stack *)ctx->ptr;
417 sel = stck->cur_ptr;
418 ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d",
419 (long)sel->left, (long)size, (long)sel->got,
420 sel->want_nulls);
421 {
422 ber_tlv_len_t len;
423
424 assert(sel->left >= 0);
425
426 len = ((ber_tlv_len_t)size < sel->left)
427 ? (ber_tlv_len_t)size : sel->left;
428 if(len > 0) {
Harald Welteec0e2172010-07-20 00:03:44 +0200429 if(type_variant == ASN_OSUBV_BIT
Harald Welte92c45f32010-06-12 18:59:38 +0200430 && sel->bits_chopped == 0) {
431 /* Put the unused-bits-octet away */
432 st->bits_unused = *(const uint8_t *)buf_ptr;
433 APPEND(((const char *)buf_ptr+1), (len - 1));
434 sel->bits_chopped = 1;
435 } else {
436 APPEND(buf_ptr, len);
437 }
438 ADVANCE(len);
439 sel->left -= len;
440 sel->got += len;
441 }
442
443 if(sel->left) {
444 ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n",
445 (long)sel->left, (long)size, sel->want_nulls);
446 RETURN(RC_WMORE);
447 }
448
449 PREV_PHASE(ctx);
450 goto phase1;
451 }
452 break;
453 case 3:
454 phase3:
455 /*
456 * Primitive form, no stack required.
457 */
458 assert(ctx->left >= 0);
459
460 if(size < (size_t)ctx->left) {
461 if(!size) RETURN(RC_WMORE);
Harald Welteec0e2172010-07-20 00:03:44 +0200462 if(type_variant == ASN_OSUBV_BIT && !ctx->context) {
Harald Welte92c45f32010-06-12 18:59:38 +0200463 st->bits_unused = *(const uint8_t *)buf_ptr;
464 ctx->left--;
465 ADVANCE(1);
466 }
467 APPEND(buf_ptr, size);
468 assert(ctx->context > 0);
469 ctx->left -= size;
470 ADVANCE(size);
471 RETURN(RC_WMORE);
472 } else {
Harald Welteec0e2172010-07-20 00:03:44 +0200473 if(type_variant == ASN_OSUBV_BIT
Harald Welte92c45f32010-06-12 18:59:38 +0200474 && !ctx->context && ctx->left) {
475 st->bits_unused = *(const uint8_t *)buf_ptr;
476 ctx->left--;
477 ADVANCE(1);
478 }
479 APPEND(buf_ptr, ctx->left);
480 ADVANCE(ctx->left);
481 ctx->left = 0;
482
483 NEXT_PHASE(ctx);
484 }
485 break;
486 }
487
488 if(sel) {
489 ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld",
490 sel->prev, sel->want_nulls,
491 (long)sel->left, (long)sel->got, (long)size);
492 if(sel->prev || sel->want_nulls > 1 || sel->left > 0) {
493 RETURN(RC_WMORE);
494 }
495 }
496
497 /*
498 * BIT STRING-specific processing.
499 */
Harald Welteec0e2172010-07-20 00:03:44 +0200500 if(type_variant == ASN_OSUBV_BIT && st->size) {
Harald Welte92c45f32010-06-12 18:59:38 +0200501 /* Finalize BIT STRING: zero out unused bits. */
502 st->buf[st->size-1] &= 0xff << st->bits_unused;
503 }
504
505 ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld",
506 (long)consumed_myself, td->name,
Harald Welteec0e2172010-07-20 00:03:44 +0200507 (type_variant == ASN_OSUBV_STR) ? (char *)st->buf : "<data>",
Harald Welte92c45f32010-06-12 18:59:38 +0200508 (long)st->size);
509
510
511 RETURN(RC_OK);
512}
513
514/*
515 * Encode OCTET STRING type using DER.
516 */
517asn_enc_rval_t
518OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
519 int tag_mode, ber_tlv_tag_t tag,
520 asn_app_consume_bytes_f *cb, void *app_key) {
521 asn_enc_rval_t er;
522 asn_OCTET_STRING_specifics_t *specs = td->specifics
523 ? (asn_OCTET_STRING_specifics_t *)td->specifics
524 : &asn_DEF_OCTET_STRING_specs;
525 BIT_STRING_t *st = (BIT_STRING_t *)sptr;
Harald Welteec0e2172010-07-20 00:03:44 +0200526 enum asn_OS_Subvariant type_variant = specs->subvariant;
Harald Welte92c45f32010-06-12 18:59:38 +0200527 int fix_last_byte = 0;
528
529 ASN_DEBUG("%s %s as OCTET STRING",
530 cb?"Estimating":"Encoding", td->name);
531
532 /*
533 * Write tags.
534 */
Harald Welteec0e2172010-07-20 00:03:44 +0200535 if(type_variant != ASN_OSUBV_ANY || tag_mode == 1) {
Harald Welte92c45f32010-06-12 18:59:38 +0200536 er.encoded = der_write_tags(td,
Harald Welteec0e2172010-07-20 00:03:44 +0200537 (type_variant == ASN_OSUBV_BIT) + st->size,
538 tag_mode, type_variant == ASN_OSUBV_ANY, tag,
539 cb, app_key);
Harald Welte92c45f32010-06-12 18:59:38 +0200540 if(er.encoded == -1) {
541 er.failed_type = td;
542 er.structure_ptr = sptr;
543 return er;
544 }
545 } else {
546 /* Disallow: [<tag>] IMPLICIT ANY */
Harald Welteec0e2172010-07-20 00:03:44 +0200547 assert(type_variant != ASN_OSUBV_ANY || tag_mode != -1);
Harald Welte92c45f32010-06-12 18:59:38 +0200548 er.encoded = 0;
549 }
550
551 if(!cb) {
Harald Welteec0e2172010-07-20 00:03:44 +0200552 er.encoded += (type_variant == ASN_OSUBV_BIT) + st->size;
Harald Welte92c45f32010-06-12 18:59:38 +0200553 _ASN_ENCODED_OK(er);
554 }
555
556 /*
557 * Prepare to deal with the last octet of BIT STRING.
558 */
Harald Welteec0e2172010-07-20 00:03:44 +0200559 if(type_variant == ASN_OSUBV_BIT) {
Harald Welte92c45f32010-06-12 18:59:38 +0200560 uint8_t b = st->bits_unused & 0x07;
561 if(b && st->size) fix_last_byte = 1;
562 _ASN_CALLBACK(&b, 1);
563 er.encoded++;
564 }
565
566 /* Invoke callback for the main part of the buffer */
567 _ASN_CALLBACK(st->buf, st->size - fix_last_byte);
568
569 /* The last octet should be stripped off the unused bits */
570 if(fix_last_byte) {
571 uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused);
572 _ASN_CALLBACK(&b, 1);
573 }
574
575 er.encoded += st->size;
576 _ASN_ENCODED_OK(er);
577cb_failed:
578 _ASN_ENCODE_FAILED;
579}
580
581asn_enc_rval_t
582OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
583 int ilevel, enum xer_encoder_flags_e flags,
584 asn_app_consume_bytes_f *cb, void *app_key) {
Harald Welte41b85d52015-08-31 08:56:53 +0200585 const char * const h2c = "0123456789ABCDEF";
Harald Welte92c45f32010-06-12 18:59:38 +0200586 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
587 asn_enc_rval_t er;
588 char scratch[16 * 3 + 4];
589 char *p = scratch;
590 uint8_t *buf;
591 uint8_t *end;
592 size_t i;
593
Harald Welteec0e2172010-07-20 00:03:44 +0200594 if(!st || (!st->buf && st->size))
Harald Welte92c45f32010-06-12 18:59:38 +0200595 _ASN_ENCODE_FAILED;
596
597 er.encoded = 0;
598
599 /*
600 * Dump the contents of the buffer in hexadecimal.
601 */
602 buf = st->buf;
603 end = buf + st->size;
604 if(flags & XER_F_CANONICAL) {
605 char *scend = scratch + (sizeof(scratch) - 2);
606 for(; buf < end; buf++) {
607 if(p >= scend) {
608 _ASN_CALLBACK(scratch, p - scratch);
609 er.encoded += p - scratch;
610 p = scratch;
611 }
612 *p++ = h2c[(*buf >> 4) & 0x0F];
613 *p++ = h2c[*buf & 0x0F];
614 }
615
616 _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
617 er.encoded += p - scratch;
618 } else {
619 for(i = 0; buf < end; buf++, i++) {
620 if(!(i % 16) && (i || st->size > 16)) {
621 _ASN_CALLBACK(scratch, p-scratch);
622 er.encoded += (p-scratch);
623 p = scratch;
624 _i_ASN_TEXT_INDENT(1, ilevel);
625 }
626 *p++ = h2c[(*buf >> 4) & 0x0F];
627 *p++ = h2c[*buf & 0x0F];
628 *p++ = 0x20;
629 }
630 if(p - scratch) {
631 p--; /* Remove the tail space */
632 _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
633 er.encoded += p - scratch;
634 if(st->size > 16)
635 _i_ASN_TEXT_INDENT(1, ilevel-1);
636 }
637 }
638
639 _ASN_ENCODED_OK(er);
640cb_failed:
641 _ASN_ENCODE_FAILED;
642}
643
Harald Welte41b85d52015-08-31 08:56:53 +0200644static const struct OCTET_STRING__xer_escape_table_s {
645 const char *string;
Harald Welte92c45f32010-06-12 18:59:38 +0200646 int size;
647} OCTET_STRING__xer_escape_table[] = {
648#define OSXET(s) { s, sizeof(s) - 1 }
649 OSXET("\074\156\165\154\057\076"), /* <nul/> */
650 OSXET("\074\163\157\150\057\076"), /* <soh/> */
651 OSXET("\074\163\164\170\057\076"), /* <stx/> */
652 OSXET("\074\145\164\170\057\076"), /* <etx/> */
653 OSXET("\074\145\157\164\057\076"), /* <eot/> */
654 OSXET("\074\145\156\161\057\076"), /* <enq/> */
655 OSXET("\074\141\143\153\057\076"), /* <ack/> */
656 OSXET("\074\142\145\154\057\076"), /* <bel/> */
657 OSXET("\074\142\163\057\076"), /* <bs/> */
658 OSXET("\011"), /* \t */
659 OSXET("\012"), /* \n */
660 OSXET("\074\166\164\057\076"), /* <vt/> */
661 OSXET("\074\146\146\057\076"), /* <ff/> */
662 OSXET("\015"), /* \r */
663 OSXET("\074\163\157\057\076"), /* <so/> */
664 OSXET("\074\163\151\057\076"), /* <si/> */
665 OSXET("\074\144\154\145\057\076"), /* <dle/> */
666 OSXET("\074\144\143\061\057\076"), /* <de1/> */
667 OSXET("\074\144\143\062\057\076"), /* <de2/> */
668 OSXET("\074\144\143\063\057\076"), /* <de3/> */
669 OSXET("\074\144\143\064\057\076"), /* <de4/> */
670 OSXET("\074\156\141\153\057\076"), /* <nak/> */
671 OSXET("\074\163\171\156\057\076"), /* <syn/> */
672 OSXET("\074\145\164\142\057\076"), /* <etb/> */
673 OSXET("\074\143\141\156\057\076"), /* <can/> */
674 OSXET("\074\145\155\057\076"), /* <em/> */
675 OSXET("\074\163\165\142\057\076"), /* <sub/> */
676 OSXET("\074\145\163\143\057\076"), /* <esc/> */
677 OSXET("\074\151\163\064\057\076"), /* <is4/> */
678 OSXET("\074\151\163\063\057\076"), /* <is3/> */
679 OSXET("\074\151\163\062\057\076"), /* <is2/> */
680 OSXET("\074\151\163\061\057\076"), /* <is1/> */
681 { 0, 0 }, /* " " */
682 { 0, 0 }, /* ! */
683 { 0, 0 }, /* \" */
684 { 0, 0 }, /* # */
685 { 0, 0 }, /* $ */
686 { 0, 0 }, /* % */
687 OSXET("\046\141\155\160\073"), /* &amp; */
688 { 0, 0 }, /* ' */
689 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */
690 {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */
691 {0,0},{0,0},{0,0},{0,0}, /* 89:; */
692 OSXET("\046\154\164\073"), /* &lt; */
693 { 0, 0 }, /* = */
694 OSXET("\046\147\164\073"), /* &gt; */
695};
696
697static int
698OS__check_escaped_control_char(const void *buf, int size) {
699 size_t i;
700 /*
701 * Inefficient algorithm which translates the escape sequences
702 * defined above into characters. Returns -1 if not found.
703 * TODO: replace by a faster algorithm (bsearch(), hash or
704 * nested table lookups).
705 */
706 for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) {
Harald Welte41b85d52015-08-31 08:56:53 +0200707 const struct OCTET_STRING__xer_escape_table_s *el;
Harald Welte92c45f32010-06-12 18:59:38 +0200708 el = &OCTET_STRING__xer_escape_table[i];
709 if(el->size == size && memcmp(buf, el->string, size) == 0)
710 return i;
711 }
712 return -1;
713}
714
715static int
716OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) {
717 /*
718 * This might be one of the escape sequences
719 * for control characters. Check it out.
720 * #11.15.5
721 */
722 int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size);
723 if(control_char >= 0) {
724 OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr;
725 void *p = REALLOC(st->buf, st->size + 2);
726 if(p) {
727 st->buf = (uint8_t *)p;
728 st->buf[st->size++] = control_char;
729 st->buf[st->size] = '\0'; /* nul-termination */
730 return 0;
731 }
732 }
733
734 return -1; /* No, it's not */
735}
736
737asn_enc_rval_t
738OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr,
739 int ilevel, enum xer_encoder_flags_e flags,
740 asn_app_consume_bytes_f *cb, void *app_key) {
741 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
742 asn_enc_rval_t er;
743 uint8_t *buf, *end;
744 uint8_t *ss; /* Sequence start */
745 ssize_t encoded_len = 0;
746
747 (void)ilevel; /* Unused argument */
748 (void)flags; /* Unused argument */
749
Harald Welteec0e2172010-07-20 00:03:44 +0200750 if(!st || (!st->buf && st->size))
Harald Welte92c45f32010-06-12 18:59:38 +0200751 _ASN_ENCODE_FAILED;
752
753 buf = st->buf;
754 end = buf + st->size;
755 for(ss = buf; buf < end; buf++) {
756 unsigned int ch = *buf;
757 int s_len; /* Special encoding sequence length */
758
759 /*
760 * Escape certain characters: X.680/11.15
761 */
762 if(ch < sizeof(OCTET_STRING__xer_escape_table)
763 /sizeof(OCTET_STRING__xer_escape_table[0])
764 && (s_len = OCTET_STRING__xer_escape_table[ch].size)) {
765 if(((buf - ss) && cb(ss, buf - ss, app_key) < 0)
766 || cb(OCTET_STRING__xer_escape_table[ch].string, s_len,
767 app_key) < 0)
768 _ASN_ENCODE_FAILED;
769 encoded_len += (buf - ss) + s_len;
770 ss = buf + 1;
771 }
772 }
773
774 encoded_len += (buf - ss);
775 if((buf - ss) && cb(ss, buf - ss, app_key) < 0)
776 _ASN_ENCODE_FAILED;
777
778 er.encoded = encoded_len;
779 _ASN_ENCODED_OK(er);
780}
781
782/*
783 * Convert from hexadecimal format (cstring): "AB CD EF"
784 */
785static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
786 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
787 const char *chunk_stop = (const char *)chunk_buf;
788 const char *p = chunk_stop;
789 const char *pend = p + chunk_size;
790 unsigned int clv = 0;
791 int half = 0; /* Half bit */
792 uint8_t *buf;
793
794 /* Reallocate buffer according to high cap estimation */
795 ssize_t _ns = st->size + (chunk_size + 1) / 2;
796 void *nptr = REALLOC(st->buf, _ns + 1);
797 if(!nptr) return -1;
798 st->buf = (uint8_t *)nptr;
799 buf = st->buf + st->size;
800
801 /*
802 * If something like " a b c " appears here, the " a b":3 will be
803 * converted, and the rest skipped. That is, unless buf_size is greater
804 * than chunk_size, then it'll be equivalent to "ABC0".
805 */
806 for(; p < pend; p++) {
807 int ch = *(const unsigned char *)p;
808 switch(ch) {
809 case 0x09: case 0x0a: case 0x0c: case 0x0d:
810 case 0x20:
811 /* Ignore whitespace */
812 continue;
813 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
814 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
815 clv = (clv << 4) + (ch - 0x30);
816 break;
817 case 0x41: case 0x42: case 0x43: /* ABC */
818 case 0x44: case 0x45: case 0x46: /* DEF */
819 clv = (clv << 4) + (ch - 0x41 + 10);
820 break;
821 case 0x61: case 0x62: case 0x63: /* abc */
822 case 0x64: case 0x65: case 0x66: /* def */
823 clv = (clv << 4) + (ch - 0x61 + 10);
824 break;
825 default:
826 *buf = 0; /* JIC */
827 return -1;
828 }
829 if(half++) {
830 half = 0;
831 *buf++ = clv;
832 chunk_stop = p + 1;
833 }
834 }
835
836 /*
837 * Check partial decoding.
838 */
839 if(half) {
840 if(have_more) {
841 /*
842 * Partial specification is fine,
843 * because no more more PXER_TEXT data is available.
844 */
845 *buf++ = clv << 4;
846 chunk_stop = p;
847 }
848 } else {
849 chunk_stop = p;
850 }
851
852 st->size = buf - st->buf; /* Adjust the buffer size */
853 assert(st->size <= _ns);
854 st->buf[st->size] = 0; /* Courtesy termination */
855
856 return (chunk_stop - (const char *)chunk_buf); /* Converted size */
857}
858
859/*
860 * Convert from binary format: "00101011101"
861 */
862static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
863 BIT_STRING_t *st = (BIT_STRING_t *)sptr;
864 const char *p = (const char *)chunk_buf;
865 const char *pend = p + chunk_size;
866 int bits_unused = st->bits_unused & 0x7;
867 uint8_t *buf;
868
869 /* Reallocate buffer according to high cap estimation */
870 ssize_t _ns = st->size + (chunk_size + 7) / 8;
871 void *nptr = REALLOC(st->buf, _ns + 1);
872 if(!nptr) return -1;
873 st->buf = (uint8_t *)nptr;
874 buf = st->buf + st->size;
875
876 (void)have_more;
877
878 if(bits_unused == 0)
879 bits_unused = 8;
880 else if(st->size)
881 buf--;
882
883 /*
884 * Convert series of 0 and 1 into the octet string.
885 */
886 for(; p < pend; p++) {
887 int ch = *(const unsigned char *)p;
888 switch(ch) {
889 case 0x09: case 0x0a: case 0x0c: case 0x0d:
890 case 0x20:
891 /* Ignore whitespace */
892 break;
893 case 0x30:
894 case 0x31:
895 if(bits_unused-- <= 0) {
896 *++buf = 0; /* Clean the cell */
897 bits_unused = 7;
898 }
899 *buf |= (ch&1) << bits_unused;
900 break;
901 default:
902 st->bits_unused = bits_unused;
903 return -1;
904 }
905 }
906
907 if(bits_unused == 8) {
908 st->size = buf - st->buf;
909 st->bits_unused = 0;
910 } else {
911 st->size = buf - st->buf + 1;
912 st->bits_unused = bits_unused;
913 }
914
915 assert(st->size <= _ns);
916 st->buf[st->size] = 0; /* Courtesy termination */
917
918 return chunk_size; /* Converted in full */
919}
920
921/*
922 * Something like strtod(), but with stricter rules.
923 */
924static int
925OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) {
926 int32_t val = 0;
927 const char *p;
928
929 for(p = buf; p < end; p++) {
930 int ch = *p;
931
932 /* Strange huge value */
933 if((val * base + base) < 0)
934 return -1;
935
936 switch(ch) {
937 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/
938 case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/
939 val = val * base + (ch - 0x30);
940 break;
941 case 0x41: case 0x42: case 0x43: /* ABC */
942 case 0x44: case 0x45: case 0x46: /* DEF */
943 val = val * base + (ch - 0x41 + 10);
944 break;
945 case 0x61: case 0x62: case 0x63: /* abc */
946 case 0x64: case 0x65: case 0x66: /* def */
947 val = val * base + (ch - 0x61 + 10);
948 break;
949 case 0x3b: /* ';' */
950 *ret_value = val;
951 return (p - buf) + 1;
952 default:
953 return -1; /* Character set error */
954 }
955 }
956
957 *ret_value = -1;
958 return (p - buf);
959}
960
961/*
962 * Convert from the plain UTF-8 format, expanding entity references: "2 &lt; 3"
963 */
964static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) {
965 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
966 const char *p = (const char *)chunk_buf;
967 const char *pend = p + chunk_size;
968 uint8_t *buf;
969
970 /* Reallocate buffer */
971 ssize_t _ns = st->size + chunk_size;
972 void *nptr = REALLOC(st->buf, _ns + 1);
973 if(!nptr) return -1;
974 st->buf = (uint8_t *)nptr;
975 buf = st->buf + st->size;
976
977 /*
978 * Convert series of 0 and 1 into the octet string.
979 */
980 for(; p < pend; p++) {
981 int ch = *(const unsigned char *)p;
982 int len; /* Length of the rest of the chunk */
983
984 if(ch != 0x26 /* '&' */) {
985 *buf++ = ch;
986 continue; /* That was easy... */
987 }
988
989 /*
990 * Process entity reference.
991 */
992 len = chunk_size - (p - (const char *)chunk_buf);
993 if(len == 1 /* "&" */) goto want_more;
994 if(p[1] == 0x23 /* '#' */) {
995 const char *pval; /* Pointer to start of digits */
996 int32_t val = 0; /* Entity reference value */
997 int base;
998
999 if(len == 2 /* "&#" */) goto want_more;
1000 if(p[2] == 0x78 /* 'x' */)
1001 pval = p + 3, base = 16;
1002 else
1003 pval = p + 2, base = 10;
1004 len = OS__strtoent(base, pval, p + len, &val);
1005 if(len == -1) {
1006 /* Invalid charset. Just copy verbatim. */
1007 *buf++ = ch;
1008 continue;
1009 }
1010 if(!len || pval[len-1] != 0x3b) goto want_more;
1011 assert(val > 0);
1012 p += (pval - p) + len - 1; /* Advance past entref */
1013
1014 if(val < 0x80) {
1015 *buf++ = (char)val;
1016 } else if(val < 0x800) {
1017 *buf++ = 0xc0 | ((val >> 6));
1018 *buf++ = 0x80 | ((val & 0x3f));
1019 } else if(val < 0x10000) {
1020 *buf++ = 0xe0 | ((val >> 12));
1021 *buf++ = 0x80 | ((val >> 6) & 0x3f);
1022 *buf++ = 0x80 | ((val & 0x3f));
1023 } else if(val < 0x200000) {
1024 *buf++ = 0xf0 | ((val >> 18));
1025 *buf++ = 0x80 | ((val >> 12) & 0x3f);
1026 *buf++ = 0x80 | ((val >> 6) & 0x3f);
1027 *buf++ = 0x80 | ((val & 0x3f));
1028 } else if(val < 0x4000000) {
1029 *buf++ = 0xf8 | ((val >> 24));
1030 *buf++ = 0x80 | ((val >> 18) & 0x3f);
1031 *buf++ = 0x80 | ((val >> 12) & 0x3f);
1032 *buf++ = 0x80 | ((val >> 6) & 0x3f);
1033 *buf++ = 0x80 | ((val & 0x3f));
1034 } else {
1035 *buf++ = 0xfc | ((val >> 30) & 0x1);
1036 *buf++ = 0x80 | ((val >> 24) & 0x3f);
1037 *buf++ = 0x80 | ((val >> 18) & 0x3f);
1038 *buf++ = 0x80 | ((val >> 12) & 0x3f);
1039 *buf++ = 0x80 | ((val >> 6) & 0x3f);
1040 *buf++ = 0x80 | ((val & 0x3f));
1041 }
1042 } else {
1043 /*
1044 * Ugly, limited parsing of &amp; &gt; &lt;
1045 */
1046 char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len);
1047 if(!sc) goto want_more;
1048 if((sc - p) == 4
1049 && p[1] == 0x61 /* 'a' */
1050 && p[2] == 0x6d /* 'm' */
1051 && p[3] == 0x70 /* 'p' */) {
1052 *buf++ = 0x26;
1053 p = sc;
1054 continue;
1055 }
1056 if((sc - p) == 3) {
1057 if(p[1] == 0x6c) {
1058 *buf = 0x3c; /* '<' */
1059 } else if(p[1] == 0x67) {
1060 *buf = 0x3e; /* '>' */
1061 } else {
1062 /* Unsupported entity reference */
1063 *buf++ = ch;
1064 continue;
1065 }
1066 if(p[2] != 0x74) {
1067 /* Unsupported entity reference */
1068 *buf++ = ch;
1069 continue;
1070 }
1071 buf++;
1072 p = sc;
1073 continue;
1074 }
1075 /* Unsupported entity reference */
1076 *buf++ = ch;
1077 }
1078
1079 continue;
1080 want_more:
1081 if(have_more) {
1082 /*
1083 * We know that no more data (of the same type)
1084 * is coming. Copy the rest verbatim.
1085 */
1086 *buf++ = ch;
1087 continue;
1088 }
1089 chunk_size = (p - (const char *)chunk_buf);
1090 /* Processing stalled: need more data */
1091 break;
1092 }
1093
1094 st->size = buf - st->buf;
1095 assert(st->size <= _ns);
1096 st->buf[st->size] = 0; /* Courtesy termination */
1097
1098 return chunk_size; /* Converted in full */
1099}
1100
1101/*
1102 * Decode OCTET STRING from the XML element's body.
1103 */
1104static asn_dec_rval_t
1105OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx,
1106 asn_TYPE_descriptor_t *td, void **sptr,
1107 const char *opt_mname, const void *buf_ptr, size_t size,
1108 int (*opt_unexpected_tag_decoder)
1109 (void *struct_ptr, const void *chunk_buf, size_t chunk_size),
1110 ssize_t (*body_receiver)
1111 (void *struct_ptr, const void *chunk_buf, size_t chunk_size,
1112 int have_more)
1113) {
1114 OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
1115 asn_OCTET_STRING_specifics_t *specs = td->specifics
1116 ? (asn_OCTET_STRING_specifics_t *)td->specifics
1117 : &asn_DEF_OCTET_STRING_specs;
1118 const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
1119 asn_struct_ctx_t *ctx; /* Per-structure parser context */
1120 asn_dec_rval_t rval; /* Return value from the decoder */
1121 int st_allocated;
1122
1123 /*
1124 * Create the string if does not exist.
1125 */
1126 if(!st) {
1127 st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
1128 *sptr = (void *)st;
1129 if(!st) goto sta_failed;
1130 st_allocated = 1;
1131 } else {
1132 st_allocated = 0;
1133 }
1134 if(!st->buf) {
1135 /* This is separate from above section */
1136 st->buf = (uint8_t *)CALLOC(1, 1);
1137 if(!st->buf) {
1138 if(st_allocated) {
1139 *sptr = 0;
1140 goto stb_failed;
1141 } else {
1142 goto sta_failed;
1143 }
1144 }
1145 }
1146
1147 /* Restore parsing context */
1148 ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset);
1149
1150 return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
1151 buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
1152
1153stb_failed:
1154 FREEMEM(st);
1155sta_failed:
1156 rval.code = RC_FAIL;
1157 rval.consumed = 0;
1158 return rval;
1159}
1160
1161/*
1162 * Decode OCTET STRING from the hexadecimal data.
1163 */
1164asn_dec_rval_t
1165OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx,
1166 asn_TYPE_descriptor_t *td, void **sptr,
1167 const char *opt_mname, const void *buf_ptr, size_t size) {
1168 return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
1169 buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal);
1170}
1171
1172/*
1173 * Decode OCTET STRING from the binary (0/1) data.
1174 */
1175asn_dec_rval_t
1176OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx,
1177 asn_TYPE_descriptor_t *td, void **sptr,
1178 const char *opt_mname, const void *buf_ptr, size_t size) {
1179 return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
1180 buf_ptr, size, 0, OCTET_STRING__convert_binary);
1181}
1182
1183/*
1184 * Decode OCTET STRING from the string (ASCII/UTF-8) data.
1185 */
1186asn_dec_rval_t
1187OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx,
1188 asn_TYPE_descriptor_t *td, void **sptr,
1189 const char *opt_mname, const void *buf_ptr, size_t size) {
1190 return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname,
1191 buf_ptr, size,
1192 OCTET_STRING__handle_control_chars,
1193 OCTET_STRING__convert_entrefs);
1194}
1195
Harald Welteec0e2172010-07-20 00:03:44 +02001196static int
1197OCTET_STRING_per_get_characters(asn_per_data_t *po, uint8_t *buf,
1198 size_t units, unsigned int bpc, unsigned int unit_bits,
Harald Welte41b85d52015-08-31 08:56:53 +02001199 int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
Harald Welteec0e2172010-07-20 00:03:44 +02001200 uint8_t *end = buf + units * bpc;
1201
Harald Welte41b85d52015-08-31 08:56:53 +02001202 ASN_DEBUG("Expanding %d characters into (%lld..%lld):%d",
Harald Welteec0e2172010-07-20 00:03:44 +02001203 (int)units, lb, ub, unit_bits);
1204
1205 /* X.691: 27.5.4 */
Harald Welte41b85d52015-08-31 08:56:53 +02001206 if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
Harald Welteec0e2172010-07-20 00:03:44 +02001207 /* Decode without translation */
1208 lb = 0;
1209 } else if(pc && pc->code2value) {
1210 if(unit_bits > 16)
1211 return 1; /* FATAL: can't have constrained
1212 * UniversalString with more than
1213 * 16 million code points */
1214 for(; buf < end; buf += bpc) {
1215 int value;
1216 int code = per_get_few_bits(po, unit_bits);
1217 if(code < 0) return -1; /* WMORE */
1218 value = pc->code2value(code);
1219 if(value < 0) {
1220 ASN_DEBUG("Code %d (0x%02x) is"
Harald Welte41b85d52015-08-31 08:56:53 +02001221 " not in map (%lld..%lld)",
Harald Welteec0e2172010-07-20 00:03:44 +02001222 code, code, lb, ub);
1223 return 1; /* FATAL */
1224 }
1225 switch(bpc) {
1226 case 1: *buf = value; break;
1227 case 2: buf[0] = value >> 8; buf[1] = value; break;
1228 case 4: buf[0] = value >> 24; buf[1] = value >> 16;
1229 buf[2] = value >> 8; buf[3] = value; break;
1230 }
1231 }
1232 return 0;
1233 }
1234
1235 /* Shortcut the no-op copying to the aligned structure */
1236 if(lb == 0 && (unit_bits == 8 * bpc)) {
1237 return per_get_many_bits(po, buf, 0, unit_bits * units);
1238 }
1239
1240 for(; buf < end; buf += bpc) {
1241 int code = per_get_few_bits(po, unit_bits);
1242 int ch = code + lb;
1243 if(code < 0) return -1; /* WMORE */
1244 if(ch > ub) {
Harald Welte41b85d52015-08-31 08:56:53 +02001245 ASN_DEBUG("Code %d is out of range (%lld..%lld)",
Harald Welteec0e2172010-07-20 00:03:44 +02001246 ch, lb, ub);
1247 return 1; /* FATAL */
1248 }
1249 switch(bpc) {
1250 case 1: *buf = ch; break;
1251 case 2: buf[0] = ch >> 8; buf[1] = ch; break;
1252 case 4: buf[0] = ch >> 24; buf[1] = ch >> 16;
1253 buf[2] = ch >> 8; buf[3] = ch; break;
1254 }
1255 }
1256
1257 return 0;
1258}
1259
1260static int
1261OCTET_STRING_per_put_characters(asn_per_outp_t *po, const uint8_t *buf,
1262 size_t units, unsigned int bpc, unsigned int unit_bits,
Harald Welte41b85d52015-08-31 08:56:53 +02001263 int64_t lb, int64_t ub, asn_per_constraints_t *pc) {
Harald Welteec0e2172010-07-20 00:03:44 +02001264 const uint8_t *end = buf + units * bpc;
1265
Harald Welte41b85d52015-08-31 08:56:53 +02001266 ASN_DEBUG("Squeezing %d characters into (%lld..%lld):%d (%d bpc)",
Harald Welteec0e2172010-07-20 00:03:44 +02001267 (int)units, lb, ub, unit_bits, bpc);
1268
1269 /* X.691: 27.5.4 */
Harald Welte41b85d52015-08-31 08:56:53 +02001270 if((uint64_t)ub <= ((uint64_t)2 << (unit_bits - 1))) {
Harald Welteec0e2172010-07-20 00:03:44 +02001271 /* Encode as is */
1272 lb = 0;
1273 } else if(pc && pc->value2code) {
1274 for(; buf < end; buf += bpc) {
1275 int code;
1276 uint32_t value;
1277 switch(bpc) {
1278 case 1: value = *(const uint8_t *)buf; break;
1279 case 2: value = (buf[0] << 8) | buf[1]; break;
1280 case 4: value = (buf[0] << 24) | (buf[1] << 16)
1281 | (buf[2] << 8) | buf[3]; break;
1282 default: return -1;
1283 }
1284 code = pc->value2code(value);
1285 if(code < 0) {
1286 ASN_DEBUG("Character %d (0x%02x) is"
Harald Welte41b85d52015-08-31 08:56:53 +02001287 " not in map (%lld..%lld)",
Harald Welteec0e2172010-07-20 00:03:44 +02001288 *buf, *buf, lb, ub);
1289 return -1;
1290 }
1291 if(per_put_few_bits(po, code, unit_bits))
1292 return -1;
1293 }
1294 }
1295
1296 /* Shortcut the no-op copying to the aligned structure */
1297 if(lb == 0 && (unit_bits == 8 * bpc)) {
1298 return per_put_many_bits(po, buf, unit_bits * units);
1299 }
1300
1301 for(ub -= lb; buf < end; buf += bpc) {
1302 int ch;
1303 uint32_t value;
1304 switch(bpc) {
1305 case 1: value = *(const uint8_t *)buf; break;
1306 case 2: value = (buf[0] << 8) | buf[1]; break;
1307 case 4: value = (buf[0] << 24) | (buf[1] << 16)
1308 | (buf[2] << 8) | buf[3]; break;
1309 default: return -1;
1310 }
1311 ch = value - lb;
1312 if(ch < 0 || ch > ub) {
1313 ASN_DEBUG("Character %d (0x%02x)"
Harald Welte41b85d52015-08-31 08:56:53 +02001314 " is out of range (%lld..%lld)",
Harald Welteec0e2172010-07-20 00:03:44 +02001315 *buf, *buf, lb, ub + lb);
1316 return -1;
1317 }
1318 if(per_put_few_bits(po, ch, unit_bits))
1319 return -1;
1320 }
1321
1322 return 0;
1323}
1324
Harald Welte92c45f32010-06-12 18:59:38 +02001325asn_dec_rval_t
1326OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx,
1327 asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
1328 void **sptr, asn_per_data_t *pd) {
1329
1330 asn_OCTET_STRING_specifics_t *specs = td->specifics
1331 ? (asn_OCTET_STRING_specifics_t *)td->specifics
1332 : &asn_DEF_OCTET_STRING_specs;
Harald Welteec0e2172010-07-20 00:03:44 +02001333 asn_per_constraints_t *pc = constraints ? constraints
1334 : td->per_constraints;
1335 asn_per_constraint_t *cval;
1336 asn_per_constraint_t *csiz;
Harald Welte92c45f32010-06-12 18:59:38 +02001337 asn_dec_rval_t rval = { RC_OK, 0 };
1338 BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
1339 ssize_t consumed_myself = 0;
1340 int repeat;
Harald Welteec0e2172010-07-20 00:03:44 +02001341 enum {
1342 OS__BPC_BIT = 0,
1343 OS__BPC_CHAR = 1,
1344 OS__BPC_U16 = 2,
1345 OS__BPC_U32 = 4
1346 } bpc; /* Bytes per character */
1347 unsigned int unit_bits;
1348 unsigned int canonical_unit_bits;
Harald Welte92c45f32010-06-12 18:59:38 +02001349
1350 (void)opt_codec_ctx;
1351
Harald Welteec0e2172010-07-20 00:03:44 +02001352 if(pc) {
1353 cval = &pc->value;
1354 csiz = &pc->size;
1355 } else {
1356 cval = &asn_DEF_OCTET_STRING_constraints.value;
1357 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1358 }
1359
1360 switch(specs->subvariant) {
1361 default:
1362 case ASN_OSUBV_ANY:
1363 ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
1364 RETURN(RC_FAIL);
1365 case ASN_OSUBV_BIT:
1366 canonical_unit_bits = unit_bits = 1;
1367 bpc = OS__BPC_BIT;
1368 break;
1369 case ASN_OSUBV_STR:
1370 canonical_unit_bits = unit_bits = 8;
1371 if(cval->flags & APC_CONSTRAINED)
1372 unit_bits = cval->range_bits;
1373 bpc = OS__BPC_CHAR;
1374 break;
1375 case ASN_OSUBV_U16:
1376 canonical_unit_bits = unit_bits = 16;
1377 if(cval->flags & APC_CONSTRAINED)
1378 unit_bits = cval->range_bits;
1379 bpc = OS__BPC_U16;
1380 break;
1381 case ASN_OSUBV_U32:
1382 canonical_unit_bits = unit_bits = 32;
1383 if(cval->flags & APC_CONSTRAINED)
1384 unit_bits = cval->range_bits;
1385 bpc = OS__BPC_U32;
1386 break;
1387 }
1388
Harald Welte92c45f32010-06-12 18:59:38 +02001389 /*
1390 * Allocate the string.
1391 */
1392 if(!st) {
1393 st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
1394 if(!st) RETURN(RC_FAIL);
1395 }
1396
Harald Welte41b85d52015-08-31 08:56:53 +02001397 ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
Harald Welteec0e2172010-07-20 00:03:44 +02001398 csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
1399 csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
Harald Welte92c45f32010-06-12 18:59:38 +02001400
Harald Welteec0e2172010-07-20 00:03:44 +02001401 if(csiz->flags & APC_EXTENSIBLE) {
Harald Welte92c45f32010-06-12 18:59:38 +02001402 int inext = per_get_few_bits(pd, 1);
1403 if(inext < 0) RETURN(RC_WMORE);
Harald Welteec0e2172010-07-20 00:03:44 +02001404 if(inext) {
1405 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1406 cval = &asn_DEF_OCTET_STRING_constraints.value;
1407 unit_bits = canonical_unit_bits;
1408 }
Harald Welte92c45f32010-06-12 18:59:38 +02001409 }
1410
Harald Welteec0e2172010-07-20 00:03:44 +02001411 if(csiz->effective_bits >= 0) {
Harald Welte92c45f32010-06-12 18:59:38 +02001412 FREEMEM(st->buf);
Harald Welteec0e2172010-07-20 00:03:44 +02001413 if(bpc) {
1414 st->size = csiz->upper_bound * bpc;
Harald Welte92c45f32010-06-12 18:59:38 +02001415 } else {
Harald Welteec0e2172010-07-20 00:03:44 +02001416 st->size = (csiz->upper_bound + 7) >> 3;
Harald Welte92c45f32010-06-12 18:59:38 +02001417 }
1418 st->buf = (uint8_t *)MALLOC(st->size + 1);
1419 if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
1420 }
1421
1422 /* X.691, #16.5: zero-length encoding */
1423 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
1424 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
Harald Welteec0e2172010-07-20 00:03:44 +02001425 if(csiz->effective_bits == 0) {
1426 int ret;
1427 if(bpc) {
Harald Welte41b85d52015-08-31 08:56:53 +02001428 ASN_DEBUG("Encoding OCTET STRING size %lld",
Harald Welteec0e2172010-07-20 00:03:44 +02001429 csiz->upper_bound);
1430 ret = OCTET_STRING_per_get_characters(pd, st->buf,
1431 csiz->upper_bound, bpc, unit_bits,
1432 cval->lower_bound, cval->upper_bound, pc);
1433 if(ret > 0) RETURN(RC_FAIL);
1434 } else {
Harald Welte41b85d52015-08-31 08:56:53 +02001435 ASN_DEBUG("Encoding BIT STRING size %lld",
Harald Welteec0e2172010-07-20 00:03:44 +02001436 csiz->upper_bound);
1437 ret = per_get_many_bits(pd, st->buf, 0,
1438 unit_bits * csiz->upper_bound);
1439 }
Harald Welte92c45f32010-06-12 18:59:38 +02001440 if(ret < 0) RETURN(RC_WMORE);
Harald Welteec0e2172010-07-20 00:03:44 +02001441 consumed_myself += unit_bits * csiz->upper_bound;
Harald Welte92c45f32010-06-12 18:59:38 +02001442 st->buf[st->size] = 0;
Harald Welteec0e2172010-07-20 00:03:44 +02001443 if(bpc == 0) {
1444 int ubs = (csiz->upper_bound & 0x7);
1445 st->bits_unused = ubs ? 8 - ubs : 0;
1446 }
Harald Welte92c45f32010-06-12 18:59:38 +02001447 RETURN(RC_OK);
1448 }
1449
1450 st->size = 0;
1451 do {
Harald Welteec0e2172010-07-20 00:03:44 +02001452 ssize_t raw_len;
Harald Welte92c45f32010-06-12 18:59:38 +02001453 ssize_t len_bytes;
1454 ssize_t len_bits;
1455 void *p;
1456 int ret;
1457
1458 /* Get the PER length */
Harald Welteec0e2172010-07-20 00:03:44 +02001459 raw_len = uper_get_length(pd, csiz->effective_bits, &repeat);
1460 if(raw_len < 0) RETURN(RC_WMORE);
1461 raw_len += csiz->lower_bound;
Harald Welte92c45f32010-06-12 18:59:38 +02001462
1463 ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
Harald Welteec0e2172010-07-20 00:03:44 +02001464 (long)csiz->effective_bits, (long)raw_len,
Harald Welte92c45f32010-06-12 18:59:38 +02001465 repeat ? "repeat" : "once", td->name);
Harald Welteec0e2172010-07-20 00:03:44 +02001466 if(bpc) {
1467 len_bytes = raw_len * bpc;
1468 len_bits = len_bytes * unit_bits;
1469 } else {
1470 len_bits = raw_len;
Harald Welte92c45f32010-06-12 18:59:38 +02001471 len_bytes = (len_bits + 7) >> 3;
1472 if(len_bits & 0x7)
1473 st->bits_unused = 8 - (len_bits & 0x7);
1474 /* len_bits be multiple of 16K if repeat is set */
Harald Welte92c45f32010-06-12 18:59:38 +02001475 }
1476 p = REALLOC(st->buf, st->size + len_bytes + 1);
1477 if(!p) RETURN(RC_FAIL);
1478 st->buf = (uint8_t *)p;
1479
Harald Welteec0e2172010-07-20 00:03:44 +02001480 if(bpc) {
1481 ret = OCTET_STRING_per_get_characters(pd,
1482 &st->buf[st->size], raw_len, bpc, unit_bits,
1483 cval->lower_bound, cval->upper_bound, pc);
1484 if(ret > 0) RETURN(RC_FAIL);
1485 } else {
1486 ret = per_get_many_bits(pd, &st->buf[st->size],
1487 0, len_bits);
1488 }
Harald Welte92c45f32010-06-12 18:59:38 +02001489 if(ret < 0) RETURN(RC_WMORE);
1490 st->size += len_bytes;
1491 } while(repeat);
1492 st->buf[st->size] = 0; /* nul-terminate */
1493
1494 return rval;
1495}
1496
Harald Welte41b85d52015-08-31 08:56:53 +02001497asn_dec_rval_t
1498OCTET_STRING_decode_aper(asn_codec_ctx_t *opt_codec_ctx,
1499 asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints,
1500 void **sptr, asn_per_data_t *pd) {
1501
1502 asn_OCTET_STRING_specifics_t *specs = td->specifics
1503 ? (asn_OCTET_STRING_specifics_t *)td->specifics
1504 : &asn_DEF_OCTET_STRING_specs;
1505 asn_per_constraints_t *pc = constraints ? constraints
1506 : td->per_constraints;
1507 asn_per_constraint_t *cval;
1508 asn_per_constraint_t *csiz;
1509 asn_dec_rval_t rval = { RC_OK, 0 };
1510 BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
1511 ssize_t consumed_myself = 0;
1512 int repeat;
1513 enum {
1514 OS__BPC_BIT = 0,
1515 OS__BPC_CHAR = 1,
1516 OS__BPC_U16 = 2,
1517 OS__BPC_U32 = 4
1518 } bpc; /* Bytes per character */
1519 unsigned int unit_bits;
1520 unsigned int canonical_unit_bits;
1521
1522 (void)opt_codec_ctx;
1523
1524 if(pc) {
1525 cval = &pc->value;
1526 csiz = &pc->size;
1527 } else {
1528 cval = &asn_DEF_OCTET_STRING_constraints.value;
1529 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1530 }
1531
1532 switch(specs->subvariant) {
1533 default:
1534// case ASN_OSUBV_ANY:
1535// ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
1536// RETURN(RC_FAIL);
1537 case ASN_OSUBV_BIT:
1538 canonical_unit_bits = unit_bits = 1;
1539 bpc = OS__BPC_BIT;
1540 break;
1541 case ASN_OSUBV_ANY:
1542 case ASN_OSUBV_STR:
1543 canonical_unit_bits = unit_bits = 8;
1544// if(cval->flags & APC_CONSTRAINED)
1545// unit_bits = cval->range_bits;
1546 bpc = OS__BPC_CHAR;
1547 break;
1548 case ASN_OSUBV_U16:
1549 canonical_unit_bits = unit_bits = 16;
1550 if(cval->flags & APC_CONSTRAINED)
1551 unit_bits = cval->range_bits;
1552 bpc = OS__BPC_U16;
1553 break;
1554 case ASN_OSUBV_U32:
1555 canonical_unit_bits = unit_bits = 32;
1556 if(cval->flags & APC_CONSTRAINED)
1557 unit_bits = cval->range_bits;
1558 bpc = OS__BPC_U32;
1559 break;
1560 }
1561
1562 /*
1563 * Allocate the string.
1564 */
1565 if(!st) {
1566 st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
1567 if(!st) RETURN(RC_FAIL);
1568 }
1569
1570 ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
1571 csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
1572 csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
1573
1574 if(csiz->flags & APC_EXTENSIBLE) {
1575 int inext = per_get_few_bits(pd, 1);
1576 if(inext < 0) RETURN(RC_WMORE);
1577 if(inext) {
1578 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1579 cval = &asn_DEF_OCTET_STRING_constraints.value;
1580 unit_bits = canonical_unit_bits;
1581 }
1582 }
1583
1584 if(csiz->effective_bits >= 0) {
1585 FREEMEM(st->buf);
1586 if(bpc) {
1587 st->size = csiz->upper_bound * bpc;
1588 } else {
1589 st->size = (csiz->upper_bound + 7) >> 3;
1590 }
1591 st->buf = (uint8_t *)MALLOC(st->size + 1);
1592 if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
1593 }
1594
1595 /* X.691, #16.5: zero-length encoding */
1596 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
1597 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
1598 if(csiz->effective_bits == 0) {
1599 int ret;
1600 if (st->size > 2) { /* X.691 #16 NOTE 1 */
1601 if (aper_get_align(pd) < 0)
1602 RETURN(RC_FAIL);
1603 }
1604 if(bpc) {
1605 ASN_DEBUG("Decoding OCTET STRING size %lld",
1606 csiz->upper_bound);
1607 ret = OCTET_STRING_per_get_characters(pd, st->buf,
1608 csiz->upper_bound, bpc, unit_bits,
1609 cval->lower_bound, cval->upper_bound, pc);
1610 if(ret > 0) RETURN(RC_FAIL);
1611 } else {
1612 ASN_DEBUG("Decoding BIT STRING size %lld",
1613 csiz->upper_bound);
1614 ret = per_get_many_bits(pd, st->buf, 0,
1615 unit_bits * csiz->upper_bound);
1616 }
1617 if(ret < 0) RETURN(RC_WMORE);
1618 consumed_myself += unit_bits * csiz->upper_bound;
1619 st->buf[st->size] = 0;
1620 if(bpc == 0) {
1621 int ubs = (csiz->upper_bound & 0x7);
1622 st->bits_unused = ubs ? 8 - ubs : 0;
1623 }
1624 RETURN(RC_OK);
1625 }
1626
1627 st->size = 0;
1628 do {
1629 ssize_t raw_len;
1630 ssize_t len_bytes;
1631 ssize_t len_bits;
1632 void *p;
1633 int ret;
1634
1635 /* Get the PER length */
1636 if (csiz->upper_bound - csiz->lower_bound == 0)
1637 // Indefinite length case
1638 raw_len = aper_get_length(pd, -1, csiz->effective_bits, &repeat);
1639 else
1640 raw_len = aper_get_length(pd, csiz->upper_bound - csiz->lower_bound + 1, csiz->effective_bits, &repeat);
1641 repeat = 0;
1642 if(raw_len < 0) RETURN(RC_WMORE);
1643 raw_len += csiz->lower_bound;
1644
1645 ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
1646 (long)csiz->effective_bits, (long)raw_len,
1647 repeat ? "repeat" : "once", td->name);
1648
1649 if (raw_len > 2) { /* X.691 #16 NOTE 1 */
1650 if (aper_get_align(pd) < 0)
1651 RETURN(RC_FAIL);
1652 }
1653
1654 if(bpc) {
1655 len_bytes = raw_len * bpc;
1656 len_bits = len_bytes * unit_bits;
1657 } else {
1658 len_bits = raw_len;
1659 len_bytes = (len_bits + 7) >> 3;
1660 if(len_bits & 0x7)
1661 st->bits_unused = 8 - (len_bits & 0x7);
1662 /* len_bits be multiple of 16K if repeat is set */
1663 }
1664 p = REALLOC(st->buf, st->size + len_bytes + 1);
1665 if(!p) RETURN(RC_FAIL);
1666 st->buf = (uint8_t *)p;
1667
1668 if(bpc) {
1669 ret = OCTET_STRING_per_get_characters(pd,
1670 &st->buf[st->size], raw_len, bpc, unit_bits,
1671 cval->lower_bound, cval->upper_bound, pc);
1672 if(ret > 0) RETURN(RC_FAIL);
1673 } else {
1674 ret = per_get_many_bits(pd, &st->buf[st->size],
1675 0, len_bits);
1676 }
1677 if(ret < 0) RETURN(RC_WMORE);
1678 st->size += len_bytes;
1679 } while(repeat);
1680 st->buf[st->size] = 0; /* nul-terminate */
1681
1682 return rval;
1683}
1684
Harald Welte92c45f32010-06-12 18:59:38 +02001685asn_enc_rval_t
1686OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td,
1687 asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
1688
1689 asn_OCTET_STRING_specifics_t *specs = td->specifics
1690 ? (asn_OCTET_STRING_specifics_t *)td->specifics
1691 : &asn_DEF_OCTET_STRING_specs;
Harald Welteec0e2172010-07-20 00:03:44 +02001692 asn_per_constraints_t *pc = constraints ? constraints
1693 : td->per_constraints;
1694 asn_per_constraint_t *cval;
1695 asn_per_constraint_t *csiz;
Harald Welte92c45f32010-06-12 18:59:38 +02001696 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
Harald Welteec0e2172010-07-20 00:03:44 +02001697 asn_enc_rval_t er = { 0, 0, 0 };
Harald Welte92c45f32010-06-12 18:59:38 +02001698 int inext = 0; /* Lies not within extension root */
Harald Welteec0e2172010-07-20 00:03:44 +02001699 unsigned int unit_bits;
1700 unsigned int canonical_unit_bits;
1701 unsigned int sizeinunits;
Harald Welte92c45f32010-06-12 18:59:38 +02001702 const uint8_t *buf;
1703 int ret;
Harald Welteec0e2172010-07-20 00:03:44 +02001704 enum {
1705 OS__BPC_BIT = 0,
1706 OS__BPC_CHAR = 1,
1707 OS__BPC_U16 = 2,
1708 OS__BPC_U32 = 4
1709 } bpc; /* Bytes per character */
1710 int ct_extensible;
Harald Welte92c45f32010-06-12 18:59:38 +02001711
Harald Welteec0e2172010-07-20 00:03:44 +02001712 if(!st || (!st->buf && st->size))
Harald Welte92c45f32010-06-12 18:59:38 +02001713 _ASN_ENCODE_FAILED;
1714
Harald Welteec0e2172010-07-20 00:03:44 +02001715 if(pc) {
1716 cval = &pc->value;
1717 csiz = &pc->size;
1718 } else {
1719 cval = &asn_DEF_OCTET_STRING_constraints.value;
1720 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1721 }
1722 ct_extensible = csiz->flags & APC_EXTENSIBLE;
1723
1724 switch(specs->subvariant) {
1725 default:
1726 case ASN_OSUBV_ANY:
1727 _ASN_ENCODE_FAILED;
1728 case ASN_OSUBV_BIT:
1729 canonical_unit_bits = unit_bits = 1;
1730 bpc = OS__BPC_BIT;
1731 sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
Harald Welte92c45f32010-06-12 18:59:38 +02001732 ASN_DEBUG("BIT STRING of %d bytes, %d bits unused",
1733 sizeinunits, st->bits_unused);
Harald Welteec0e2172010-07-20 00:03:44 +02001734 break;
1735 case ASN_OSUBV_STR:
1736 canonical_unit_bits = unit_bits = 8;
1737 if(cval->flags & APC_CONSTRAINED)
1738 unit_bits = cval->range_bits;
1739 bpc = OS__BPC_CHAR;
1740 sizeinunits = st->size;
1741 break;
1742 case ASN_OSUBV_U16:
1743 canonical_unit_bits = unit_bits = 16;
1744 if(cval->flags & APC_CONSTRAINED)
1745 unit_bits = cval->range_bits;
1746 bpc = OS__BPC_U16;
1747 sizeinunits = st->size / 2;
1748 break;
1749 case ASN_OSUBV_U32:
1750 canonical_unit_bits = unit_bits = 32;
1751 if(cval->flags & APC_CONSTRAINED)
1752 unit_bits = cval->range_bits;
1753 bpc = OS__BPC_U32;
1754 sizeinunits = st->size / 4;
1755 break;
Harald Welte92c45f32010-06-12 18:59:38 +02001756 }
1757
1758 ASN_DEBUG("Encoding %s into %d units of %d bits"
Harald Welte41b85d52015-08-31 08:56:53 +02001759 " (%lld..%lld, effective %d)%s",
Harald Welte92c45f32010-06-12 18:59:38 +02001760 td->name, sizeinunits, unit_bits,
Harald Welteec0e2172010-07-20 00:03:44 +02001761 csiz->lower_bound, csiz->upper_bound,
1762 csiz->effective_bits, ct_extensible ? " EXT" : "");
Harald Welte92c45f32010-06-12 18:59:38 +02001763
Harald Welte41b85d52015-08-31 08:56:53 +02001764 /* Figure out whether size lies within PER visible constraint */
Harald Welte92c45f32010-06-12 18:59:38 +02001765
Harald Welteec0e2172010-07-20 00:03:44 +02001766 if(csiz->effective_bits >= 0) {
1767 if((int)sizeinunits < csiz->lower_bound
1768 || (int)sizeinunits > csiz->upper_bound) {
Harald Welte92c45f32010-06-12 18:59:38 +02001769 if(ct_extensible) {
Harald Welteec0e2172010-07-20 00:03:44 +02001770 cval = &asn_DEF_OCTET_STRING_constraints.value;
1771 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1772 unit_bits = canonical_unit_bits;
Harald Welte92c45f32010-06-12 18:59:38 +02001773 inext = 1;
1774 } else
1775 _ASN_ENCODE_FAILED;
1776 }
1777 } else {
1778 inext = 0;
1779 }
1780
1781 if(ct_extensible) {
1782 /* Declare whether length is [not] within extension root */
1783 if(per_put_few_bits(po, inext, 1))
1784 _ASN_ENCODE_FAILED;
1785 }
1786
1787 /* X.691, #16.5: zero-length encoding */
1788 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
1789 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
Harald Welteec0e2172010-07-20 00:03:44 +02001790 if(csiz->effective_bits >= 0) {
Harald Welte41b85d52015-08-31 08:56:53 +02001791 ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
Harald Welteec0e2172010-07-20 00:03:44 +02001792 st->size, sizeinunits - csiz->lower_bound,
1793 csiz->effective_bits);
1794 ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
1795 csiz->effective_bits);
Harald Welte92c45f32010-06-12 18:59:38 +02001796 if(ret) _ASN_ENCODE_FAILED;
Harald Welteec0e2172010-07-20 00:03:44 +02001797 if(bpc) {
1798 ret = OCTET_STRING_per_put_characters(po, st->buf,
1799 sizeinunits, bpc, unit_bits,
1800 cval->lower_bound, cval->upper_bound, pc);
1801 } else {
1802 ret = per_put_many_bits(po, st->buf,
1803 sizeinunits * unit_bits);
1804 }
Harald Welte92c45f32010-06-12 18:59:38 +02001805 if(ret) _ASN_ENCODE_FAILED;
1806 _ASN_ENCODED_OK(er);
1807 }
1808
1809 ASN_DEBUG("Encoding %d bytes", st->size);
1810
1811 if(sizeinunits == 0) {
1812 if(uper_put_length(po, 0))
1813 _ASN_ENCODE_FAILED;
1814 _ASN_ENCODED_OK(er);
1815 }
1816
1817 buf = st->buf;
1818 while(sizeinunits) {
1819 ssize_t maySave = uper_put_length(po, sizeinunits);
1820 if(maySave < 0) _ASN_ENCODE_FAILED;
1821
Harald Welteec0e2172010-07-20 00:03:44 +02001822 ASN_DEBUG("Encoding %ld of %ld",
1823 (long)maySave, (long)sizeinunits);
Harald Welte92c45f32010-06-12 18:59:38 +02001824
Harald Welteec0e2172010-07-20 00:03:44 +02001825 if(bpc) {
1826 ret = OCTET_STRING_per_put_characters(po, buf,
1827 maySave, bpc, unit_bits,
1828 cval->lower_bound, cval->upper_bound, pc);
1829 } else {
1830 ret = per_put_many_bits(po, buf, maySave * unit_bits);
1831 }
Harald Welte92c45f32010-06-12 18:59:38 +02001832 if(ret) _ASN_ENCODE_FAILED;
1833
Harald Welteec0e2172010-07-20 00:03:44 +02001834 if(bpc)
1835 buf += maySave * bpc;
Harald Welte92c45f32010-06-12 18:59:38 +02001836 else
Harald Welteec0e2172010-07-20 00:03:44 +02001837 buf += maySave >> 3;
Harald Welte92c45f32010-06-12 18:59:38 +02001838 sizeinunits -= maySave;
1839 assert(!(maySave & 0x07) || !sizeinunits);
1840 }
1841
1842 _ASN_ENCODED_OK(er);
1843}
1844
Harald Welte41b85d52015-08-31 08:56:53 +02001845asn_enc_rval_t
1846OCTET_STRING_encode_aper(asn_TYPE_descriptor_t *td,
1847 asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
1848
1849 asn_OCTET_STRING_specifics_t *specs = td->specifics
1850 ? (asn_OCTET_STRING_specifics_t *)td->specifics
1851 : &asn_DEF_OCTET_STRING_specs;
1852 asn_per_constraints_t *pc = constraints ? constraints
1853 : td->per_constraints;
1854 asn_per_constraint_t *cval;
1855 asn_per_constraint_t *csiz;
1856 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
1857 asn_enc_rval_t er = { 0, 0, 0 };
1858 int inext = 0; /* Lies not within extension root */
1859 unsigned int unit_bits;
1860 unsigned int canonical_unit_bits;
1861 unsigned int sizeinunits;
1862 const uint8_t *buf;
1863 int ret;
1864 enum {
1865 OS__BPC_BIT = 0,
1866 OS__BPC_CHAR = 1,
1867 OS__BPC_U16 = 2,
1868 OS__BPC_U32 = 4
1869 } bpc; /* Bytes per character */
1870 int ct_extensible;
1871
1872 if(!st || (!st->buf && st->size))
1873 _ASN_ENCODE_FAILED;
1874
1875 if(pc) {
1876 cval = &pc->value;
1877 csiz = &pc->size;
1878 } else {
1879 cval = &asn_DEF_OCTET_STRING_constraints.value;
1880 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1881 }
1882 ct_extensible = csiz->flags & APC_EXTENSIBLE;
1883
1884 switch(specs->subvariant) {
1885 default:
1886// case ASN_OSUBV_ANY:
1887// _ASN_ENCODE_FAILED;
1888 case ASN_OSUBV_BIT:
1889 canonical_unit_bits = unit_bits = 1;
1890 bpc = OS__BPC_BIT;
1891 sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
1892 ASN_DEBUG("BIT STRING of %d bytes",
1893 sizeinunits);
1894 break;
1895 case ASN_OSUBV_ANY:
1896 case ASN_OSUBV_STR:
1897 canonical_unit_bits = unit_bits = 8;
1898// if(cval->flags & APC_CONSTRAINED)
1899// unit_bits = 8;
1900 bpc = OS__BPC_CHAR;
1901 sizeinunits = st->size;
1902 break;
1903 case ASN_OSUBV_U16:
1904 canonical_unit_bits = unit_bits = 16;
1905 if(cval->flags & APC_CONSTRAINED)
1906 unit_bits = cval->range_bits;
1907 bpc = OS__BPC_U16;
1908 sizeinunits = st->size / 2;
1909 break;
1910 case ASN_OSUBV_U32:
1911 canonical_unit_bits = unit_bits = 32;
1912 if(cval->flags & APC_CONSTRAINED)
1913 unit_bits = cval->range_bits;
1914 bpc = OS__BPC_U32;
1915 sizeinunits = st->size / 4;
1916 break;
1917 }
1918
1919 ASN_DEBUG("Encoding %s into %d units of %d bits"
1920 " (%lld..%lld, effective %d)%s",
1921 td->name, sizeinunits, unit_bits,
1922 csiz->lower_bound, csiz->upper_bound,
1923 csiz->effective_bits, ct_extensible ? " EXT" : "");
1924
1925 /* Figure out wheter size lies within PER visible constraint */
1926
1927 if(csiz->effective_bits >= 0) {
1928 if((int)sizeinunits < csiz->lower_bound
1929 || (int)sizeinunits > csiz->upper_bound) {
1930 if(ct_extensible) {
1931 cval = &asn_DEF_OCTET_STRING_constraints.value;
1932 csiz = &asn_DEF_OCTET_STRING_constraints.size;
1933 unit_bits = canonical_unit_bits;
1934 inext = 1;
1935 } else
1936 _ASN_ENCODE_FAILED;
1937 }
1938 } else {
1939 inext = 0;
1940 }
1941
1942
1943 if(ct_extensible) {
1944 /* Declare whether length is [not] within extension root */
1945 if(per_put_few_bits(po, inext, 1))
1946 _ASN_ENCODE_FAILED;
1947 }
1948
1949 /* X.691, #16.5: zero-length encoding */
1950 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
1951 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
1952 if(csiz->effective_bits >= 0) {
1953 ASN_DEBUG("Encoding %d bytes (%lld), length in %d bits",
1954 st->size, sizeinunits - csiz->lower_bound,
1955 csiz->effective_bits);
1956 ret = per_put_few_bits(po, sizeinunits - csiz->lower_bound,
1957 csiz->effective_bits);
1958 if(ret) _ASN_ENCODE_FAILED;
1959 if (st->size > 2) { /* X.691 #16 NOTE 1 */
1960 if (aper_put_align(po) < 0)
1961 _ASN_ENCODE_FAILED;
1962 }
1963 if(bpc) {
1964 ret = OCTET_STRING_per_put_characters(po, st->buf,
1965 sizeinunits, bpc, unit_bits,
1966 cval->lower_bound, cval->upper_bound, pc);
1967 } else {
1968 ret = per_put_many_bits(po, st->buf,
1969 sizeinunits * unit_bits);
1970 }
1971 if(ret) _ASN_ENCODE_FAILED;
1972 _ASN_ENCODED_OK(er);
1973 }
1974
1975 ASN_DEBUG("Encoding %d bytes", st->size);
1976
1977 if(sizeinunits == 0) {
1978 if(aper_put_length(po, -1, 0))
1979 _ASN_ENCODE_FAILED;
1980 _ASN_ENCODED_OK(er);
1981 }
1982
1983 buf = st->buf;
1984 while(sizeinunits) {
1985 ssize_t maySave = aper_put_length(po, -1, sizeinunits);
1986
1987 if(maySave < 0) _ASN_ENCODE_FAILED;
1988
1989 ASN_DEBUG("Encoding %ld of %ld",
1990 (long)maySave, (long)sizeinunits);
1991
1992 if(bpc) {
1993 ret = OCTET_STRING_per_put_characters(po, buf,
1994 maySave, bpc, unit_bits,
1995 cval->lower_bound, cval->upper_bound, pc);
1996 } else {
1997 ret = per_put_many_bits(po, buf, maySave * unit_bits);
1998 }
1999 if(ret) _ASN_ENCODE_FAILED;
2000
2001 if(bpc)
2002 buf += maySave * bpc;
2003 else
2004 buf += maySave >> 3;
2005 sizeinunits -= maySave;
2006 assert(!(maySave & 0x07) || !sizeinunits);
2007 }
2008
2009 _ASN_ENCODED_OK(er);
2010}
2011
Harald Welte92c45f32010-06-12 18:59:38 +02002012int
2013OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
2014 asn_app_consume_bytes_f *cb, void *app_key) {
Harald Welte41b85d52015-08-31 08:56:53 +02002015 const char * const h2c = "0123456789ABCDEF";
Harald Welte92c45f32010-06-12 18:59:38 +02002016 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
2017 char scratch[16 * 3 + 4];
2018 char *p = scratch;
2019 uint8_t *buf;
2020 uint8_t *end;
2021 size_t i;
2022
2023 (void)td; /* Unused argument */
2024
Harald Welteec0e2172010-07-20 00:03:44 +02002025 if(!st || (!st->buf && st->size))
2026 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
Harald Welte92c45f32010-06-12 18:59:38 +02002027
2028 /*
2029 * Dump the contents of the buffer in hexadecimal.
2030 */
2031 buf = st->buf;
2032 end = buf + st->size;
2033 for(i = 0; buf < end; buf++, i++) {
2034 if(!(i % 16) && (i || st->size > 16)) {
2035 if(cb(scratch, p - scratch, app_key) < 0)
2036 return -1;
2037 _i_INDENT(1);
2038 p = scratch;
2039 }
2040 *p++ = h2c[(*buf >> 4) & 0x0F];
2041 *p++ = h2c[*buf & 0x0F];
2042 *p++ = 0x20;
2043 }
2044
2045 if(p > scratch) {
2046 p--; /* Remove the tail space */
2047 if(cb(scratch, p - scratch, app_key) < 0)
2048 return -1;
2049 }
2050
2051 return 0;
2052}
2053
2054int
2055OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr,
2056 int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
2057 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
2058
2059 (void)td; /* Unused argument */
2060 (void)ilevel; /* Unused argument */
2061
Harald Welteec0e2172010-07-20 00:03:44 +02002062 if(st && (st->buf || !st->size)) {
Harald Welte92c45f32010-06-12 18:59:38 +02002063 return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
2064 } else {
2065 return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
2066 }
2067}
2068
2069void
2070OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) {
2071 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
2072 asn_OCTET_STRING_specifics_t *specs = td->specifics
2073 ? (asn_OCTET_STRING_specifics_t *)td->specifics
2074 : &asn_DEF_OCTET_STRING_specs;
2075 asn_struct_ctx_t *ctx = (asn_struct_ctx_t *)
2076 ((char *)st + specs->ctx_offset);
2077 struct _stack *stck;
2078
2079 if(!td || !st)
2080 return;
2081
2082 ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
2083
2084 if(st->buf) {
2085 FREEMEM(st->buf);
Harald Welteec0e2172010-07-20 00:03:44 +02002086 st->buf = 0;
Harald Welte92c45f32010-06-12 18:59:38 +02002087 }
2088
2089 /*
2090 * Remove decode-time stack.
2091 */
2092 stck = (struct _stack *)ctx->ptr;
2093 if(stck) {
2094 while(stck->tail) {
2095 struct _stack_el *sel = stck->tail;
2096 stck->tail = sel->prev;
2097 FREEMEM(sel);
2098 }
2099 FREEMEM(stck);
2100 }
2101
2102 if(!contents_only) {
2103 FREEMEM(st);
2104 }
2105}
2106
2107/*
2108 * Conversion routines.
2109 */
2110int
2111OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
2112 void *buf;
2113
2114 if(st == 0 || (str == 0 && len)) {
2115 errno = EINVAL;
2116 return -1;
2117 }
2118
2119 /*
2120 * Clear the OCTET STRING.
2121 */
2122 if(str == NULL) {
2123 FREEMEM(st->buf);
2124 st->buf = 0;
2125 st->size = 0;
2126 return 0;
2127 }
2128
2129 /* Determine the original string size, if not explicitly given */
2130 if(len < 0)
2131 len = strlen(str);
2132
2133 /* Allocate and fill the memory */
2134 buf = MALLOC(len + 1);
2135 if(buf == NULL)
2136 return -1;
2137
2138 memcpy(buf, str, len);
2139 ((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */
2140 FREEMEM(st->buf);
2141 st->buf = (uint8_t *)buf;
2142 st->size = len;
2143
2144 return 0;
2145}
2146
2147OCTET_STRING_t *
2148OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) {
2149 asn_OCTET_STRING_specifics_t *specs = td->specifics
2150 ? (asn_OCTET_STRING_specifics_t *)td->specifics
2151 : &asn_DEF_OCTET_STRING_specs;
2152 OCTET_STRING_t *st;
2153
2154 st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
2155 if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
2156 FREEMEM(st);
2157 st = NULL;
2158 }
2159
2160 return st;
2161}
2162