blob: 4b7bd66ece573e67d8797c4cb5ce5047cbb9463d [file] [log] [blame]
vlmfa67ddc2004-06-03 03:38:44 +00001/*-
vlm72425de2004-09-13 08:31:01 +00002 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
vlmfa67ddc2004-06-03 03:38:44 +00003 * Redistribution and modifications are permitted subject to BSD license.
4 */
vlm39ba4c42004-09-22 16:06:28 +00005#include <asn_internal.h>
vlmfa67ddc2004-06-03 03:38:44 +00006#include <OCTET_STRING.h>
7#include <assert.h>
8#include <errno.h>
9
10/*
11 * OCTET STRING basic type description.
12 */
13static ber_tlv_tag_t asn1_DEF_OCTET_STRING_tags[] = {
14 (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
15};
16asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
17 "OCTET STRING",
vlm39ba4c42004-09-22 16:06:28 +000018 OCTET_STRING_free,
19 OCTET_STRING_print, /* non-ascii stuff, generally */
vlmfa67ddc2004-06-03 03:38:44 +000020 asn_generic_no_constraint,
21 OCTET_STRING_decode_ber,
22 OCTET_STRING_encode_der,
vlm39ba4c42004-09-22 16:06:28 +000023 0, /* Not implemented yet */
24 OCTET_STRING_encode_xer,
vlmfa67ddc2004-06-03 03:38:44 +000025 0, /* Use generic outmost tag fetcher */
26 asn1_DEF_OCTET_STRING_tags,
27 sizeof(asn1_DEF_OCTET_STRING_tags)
28 / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
vlm72425de2004-09-13 08:31:01 +000029 asn1_DEF_OCTET_STRING_tags, /* Same as above */
30 sizeof(asn1_DEF_OCTET_STRING_tags)
31 / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
vlmfa67ddc2004-06-03 03:38:44 +000032 -1, /* Both ways are fine (primitive and constructed) */
vlme413c122004-08-20 13:23:42 +000033 0, 0, /* No members */
vlmb42843a2004-06-05 08:17:50 +000034 0 /* No specifics */
vlmfa67ddc2004-06-03 03:38:44 +000035};
36
37#define _CH_PHASE(ctx, inc) do { \
38 if(ctx->phase == 0) \
39 ctx->step = 0; \
40 ctx->phase += inc; \
41 } while(0)
42#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
43#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
44
vlmd86c9252004-08-25 01:34:11 +000045#define ADVANCE(num_bytes) do { \
46 size_t num = num_bytes; \
47 buf_ptr = ((char *)buf_ptr) + num; \
48 size -= num; \
49 consumed_myself += num; \
vlmfa67ddc2004-06-03 03:38:44 +000050 } while(0)
51
52#define RETURN(_code) do { \
53 rval.code = _code; \
54 rval.consumed = consumed_myself;\
55 return rval; \
56 } while(0)
57
vlmb42843a2004-06-05 08:17:50 +000058#define APPEND(bufptr, bufsize) do { \
vlmcdfdb722004-09-04 04:44:50 +000059 size_t _bs = (bufsize); \
vlmb42843a2004-06-05 08:17:50 +000060 size_t _ns = ctx->step; /* Allocated */ \
vlmcdfdb722004-09-04 04:44:50 +000061 if(_ns <= (size_t)(st->size + _bs)) { \
vlmb42843a2004-06-05 08:17:50 +000062 void *ptr; \
vlm72425de2004-09-13 08:31:01 +000063 /* Be nice and round to the memory allocator */ \
vlmb42843a2004-06-05 08:17:50 +000064 do { _ns = _ns ? _ns<<2 : 16; } \
vlmcdfdb722004-09-04 04:44:50 +000065 while(_ns <= (size_t)(st->size + _bs)); \
vlmb42843a2004-06-05 08:17:50 +000066 ptr = REALLOC(st->buf, _ns); \
67 if(ptr) { \
vlmda674682004-08-11 09:07:36 +000068 st->buf = (uint8_t *)ptr; \
vlmb42843a2004-06-05 08:17:50 +000069 ctx->step = _ns; \
70 } else { \
71 RETURN(RC_FAIL); \
72 } \
73 } \
vlmcdfdb722004-09-04 04:44:50 +000074 memcpy(st->buf + st->size, bufptr, _bs); \
75 st->size += _bs; \
vlmb42843a2004-06-05 08:17:50 +000076 if(st->size < 0) \
77 /* Why even care?.. JIC */ \
78 RETURN(RC_FAIL); \
79 /* Convenient nul-termination */ \
80 st->buf[st->size] = '\0'; \
vlmfa67ddc2004-06-03 03:38:44 +000081 } while(0)
82
83/*
84 * The main reason why ASN.1 is still alive is that too much time and effort
85 * is necessary for learning it more or less adequately, thus creating a gut
86 * necessity to demonstrate that aquired skill everywhere afterwards.
87 * No, I am not going to explain what the following stuff is.
88 */
89struct _stack_el {
90 ber_tlv_len_t left; /* What's left to read */
vlm72425de2004-09-13 08:31:01 +000091 int cont_level; /* Depth of subcontainment */
vlmfa67ddc2004-06-03 03:38:44 +000092 int want_nulls; /* Want null "end of content" octets? */
93 int bits_chopped; /* Flag in BIT STRING mode */
94 struct _stack_el *prev;
95 struct _stack_el *next;
96};
97struct _stack {
98 struct _stack_el *tail;
99 struct _stack_el *cur_ptr;
100};
101
102static struct _stack_el *
103_add_stack_el(struct _stack *st) {
104 struct _stack_el *nel;
105
vlm72425de2004-09-13 08:31:01 +0000106 /*
107 * Reuse the old stack frame or allocate a new one.
108 */
vlmfa67ddc2004-06-03 03:38:44 +0000109 if(st->cur_ptr && st->cur_ptr->next) {
110 nel = st->cur_ptr->next;
111 nel->left = 0;
112 nel->want_nulls = 0;
113 nel->bits_chopped = 0;
vlm72425de2004-09-13 08:31:01 +0000114 /* Retain nel->cont_level, it's correct. */
vlmfa67ddc2004-06-03 03:38:44 +0000115 } else {
vlmda674682004-08-11 09:07:36 +0000116 (void *)nel = CALLOC(1, sizeof(struct _stack_el));
vlmfa67ddc2004-06-03 03:38:44 +0000117 if(nel == NULL)
118 return NULL;
119
120 if(st->tail) {
vlm72425de2004-09-13 08:31:01 +0000121 /* Increase a subcontainment depth */
122 nel->cont_level = st->tail->cont_level + 1;
vlmfa67ddc2004-06-03 03:38:44 +0000123 st->tail->next = nel;
124 }
125 nel->prev = st->tail;
126 st->tail = nel;
127 }
128
129 st->cur_ptr = nel;
130
131 return nel;
132}
133
134static struct _stack *
135_new_stack() {
136 struct _stack *st;
vlmda674682004-08-11 09:07:36 +0000137 (void *)st = CALLOC(1, sizeof(struct _stack));
vlmfa67ddc2004-06-03 03:38:44 +0000138 if(st == NULL)
139 return NULL;
140
vlmfa67ddc2004-06-03 03:38:44 +0000141 return st;
142}
143
144/*
145 * Decode OCTET STRING type.
146 */
147ber_dec_rval_t
148OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
149 void **os_structure, void *buf_ptr, size_t size, int tag_mode) {
vlmda674682004-08-11 09:07:36 +0000150 OCTET_STRING_t *st = (OCTET_STRING_t *)*os_structure;
vlmfa67ddc2004-06-03 03:38:44 +0000151 ber_dec_rval_t rval;
152 ber_dec_ctx_t *ctx;
153 ssize_t consumed_myself = 0;
154 struct _stack *stck; /* A stack structure */
155 struct _stack_el *sel; /* Stack element */
156 int tlv_constr;
vlm72425de2004-09-13 08:31:01 +0000157 enum type_type_e {
158 _TT_GENERIC = 0, /* Just a random OCTET STRING */
159 _TT_BIT_STRING = -1, /* BIT STRING type, a special case */
160 _TT_ANY = 1, /* ANY type, a special case too */
161 } type_type
162 = (enum type_type_e)(int)td->specifics; /* An ugly hack */
vlmfa67ddc2004-06-03 03:38:44 +0000163
164 ASN_DEBUG("Decoding %s as %s (%ld)",
vlmcdfdb722004-09-04 04:44:50 +0000165 td->name, "OCTET STRING", (long)size);
vlmfa67ddc2004-06-03 03:38:44 +0000166
167 /*
168 * Create the string if does not exist.
169 */
170 if(st == NULL) {
vlmda674682004-08-11 09:07:36 +0000171 (void *)st = *os_structure = CALLOC(1, sizeof(*st));
vlmfa67ddc2004-06-03 03:38:44 +0000172 if(st == NULL)
173 RETURN(RC_FAIL);
174 }
175
176 /* Restore parsing context */
177 ctx = &st->_ber_dec_ctx;
178
179 switch(ctx->phase) {
180 case 0:
181 /*
182 * Check tags.
183 */
184 rval = ber_check_tags(td, ctx,
185 buf_ptr, size, tag_mode,
186 &ctx->left, &tlv_constr);
187 if(rval.code != RC_OK) {
188 RETURN(rval.code);
189 }
190
191 ASN_DEBUG("OS length is %d bytes, form %d",
192 (int)ctx->left, tlv_constr);
193
194 if(tlv_constr) {
195 /*
196 * Complex operation, requires stack of expectations.
197 */
198 ctx->ptr = _new_stack();
199 if(ctx->ptr) {
vlmda674682004-08-11 09:07:36 +0000200 (void *)stck = ctx->ptr;
vlmcdfdb722004-09-04 04:44:50 +0000201#if 0
vlmfa67ddc2004-06-03 03:38:44 +0000202 if(ctx->left < 0) {
203 stck->cur_ptr->want_nulls = -ctx->left;
204 stck->cur_ptr->left = -1;
205 } else {
206 stck->cur_ptr->want_nulls = 0;
207 stck->cur_ptr->left = ctx->left;
208 }
vlmcdfdb722004-09-04 04:44:50 +0000209 ASN_DEBUG("+EXPECT1 left=%d wn=%d",
vlmfa67ddc2004-06-03 03:38:44 +0000210 stck->cur_ptr->left,
211 stck->cur_ptr->want_nulls);
vlmcdfdb722004-09-04 04:44:50 +0000212#endif
vlm72425de2004-09-13 08:31:01 +0000213 if(type_type == _TT_BIT_STRING) {
vlmcdfdb722004-09-04 04:44:50 +0000214 /* Number of meaningless tail bits */
vlmfa67ddc2004-06-03 03:38:44 +0000215 APPEND("\0", 1);
216 }
217 } else {
218 RETURN(RC_FAIL);
219 }
220 } else {
221 /*
222 * Jump into stackless primitive decoding.
223 */
224 _CH_PHASE(ctx, 3);
vlm72425de2004-09-13 08:31:01 +0000225 if(type_type == _TT_ANY)
226 APPEND(buf_ptr, rval.consumed);
vlmfa67ddc2004-06-03 03:38:44 +0000227 ADVANCE(rval.consumed);
228 goto phase3;
229 }
230
vlmfa67ddc2004-06-03 03:38:44 +0000231 NEXT_PHASE(ctx);
232 /* Fall through */
233 case 1:
234 phase1:
235 /*
236 * Fill the stack with expectations.
237 */
vlmda674682004-08-11 09:07:36 +0000238 (void *)stck = ctx->ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000239 sel = stck->cur_ptr;
240 do {
241 ber_tlv_tag_t tlv_tag;
242 ber_tlv_len_t tlv_len;
vlm72425de2004-09-13 08:31:01 +0000243 ber_tlv_tag_t expected_tag;
vlmfa67ddc2004-06-03 03:38:44 +0000244 ssize_t tl, ll;
245
vlmcdfdb722004-09-04 04:44:50 +0000246 ASN_DEBUG("fetch tag(size=%d), %sstack, left=%d, want0=%d",
247 (int)size, sel?"":"!",
248 sel?sel->left:0, sel?sel->want_nulls:0);
vlmfa67ddc2004-06-03 03:38:44 +0000249 tl = ber_fetch_tag(buf_ptr, size, &tlv_tag);
250 switch(tl) {
251 case -1: RETURN(RC_FAIL);
252 case 0: RETURN(RC_WMORE);
253 }
254
255 tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
256
257 ll = ber_fetch_length(tlv_constr,
vlm1ff928d2004-08-11 08:10:13 +0000258 (char *)buf_ptr + tl, size - tl, &tlv_len);
vlmcdfdb722004-09-04 04:44:50 +0000259 ASN_DEBUG("Got tag=%s, tc=%d, size=%d, tl=%d, len=%d, ll=%d, {%d, %d}",
260 ber_tlv_tag_string(tlv_tag), tlv_constr,
261 (int)size, tl, tlv_len, ll,
vlmfa67ddc2004-06-03 03:38:44 +0000262 ((uint8_t *)buf_ptr)[0],
263 ((uint8_t *)buf_ptr)[1]);
264 switch(ll) {
265 case -1: RETURN(RC_FAIL);
266 case 0: RETURN(RC_WMORE);
267 }
268
vlmcdfdb722004-09-04 04:44:50 +0000269 if(sel && sel->want_nulls
vlmfa67ddc2004-06-03 03:38:44 +0000270 && ((uint8_t *)buf_ptr)[0] == 0
271 && ((uint8_t *)buf_ptr)[1] == 0)
272 {
vlmcdfdb722004-09-04 04:44:50 +0000273 ADVANCE(2);
vlm72425de2004-09-13 08:31:01 +0000274 if(type_type == _TT_ANY) APPEND("\0\0", 2);
vlmcdfdb722004-09-04 04:44:50 +0000275
276 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
277
vlmfa67ddc2004-06-03 03:38:44 +0000278 sel->want_nulls--;
279 if(sel->want_nulls == 0) {
280 /* Move to the next expectation */
281 sel = stck->cur_ptr = sel->prev;
vlmcdfdb722004-09-04 04:44:50 +0000282 if(sel == NULL)
vlmfa67ddc2004-06-03 03:38:44 +0000283 break;
vlmfa67ddc2004-06-03 03:38:44 +0000284 }
vlmcdfdb722004-09-04 04:44:50 +0000285
vlmfa67ddc2004-06-03 03:38:44 +0000286 if(sel->want_nulls) {
287 /*
288 * Simulate while(TRUE) for this loop.
289 * This is necessary to fetch the next
vlmcdfdb722004-09-04 04:44:50 +0000290 * expectation after current "end of content",
291 * for which tlv_constr is 0.
vlmfa67ddc2004-06-03 03:38:44 +0000292 */
vlmfa67ddc2004-06-03 03:38:44 +0000293 tlv_constr = 1;
vlmfa67ddc2004-06-03 03:38:44 +0000294 }
vlmcdfdb722004-09-04 04:44:50 +0000295
296 continue;
vlm72425de2004-09-13 08:31:01 +0000297 }
298
299 /*
300 * Set up expected tags,
301 * depending on ASN.1 type being decoded.
302 */
303 switch(type_type) {
304 case _TT_BIT_STRING:
305 /* X.690: 8.6.4.1, NOTE 2 */
306 /* Fall through */
307 case _TT_GENERIC:
308 default:
309 if(sel) {
310 int level = sel->cont_level;
311 if(level < td->all_tags_count) {
312 expected_tag = td->all_tags[level];
313 break;
314 } else if(td->all_tags_count) {
315 expected_tag = td->all_tags
316 [td->all_tags_count - 1];
317 break;
318 }
319 /* else, Fall through */
320 }
321 /* Fall through */
322 case _TT_ANY:
323 expected_tag = tlv_tag;
324 break;
325 }
326
327
328 if(tlv_tag != expected_tag) {
vlmfa67ddc2004-06-03 03:38:44 +0000329 char buf[2][32];
330 ber_tlv_tag_snprint(tlv_tag,
331 buf[0], sizeof(buf[0]));
332 ber_tlv_tag_snprint(td->tags[td->tags_count-1],
333 buf[1], sizeof(buf[1]));
334 ASN_DEBUG("Tag does not match expectation: %s != %s",
335 buf[0], buf[1]);
336 RETURN(RC_FAIL);
337 }
338
339 /*
340 * Append a new expectation.
341 */
342 sel = _add_stack_el(stck);
343 if(sel) {
344 sel->want_nulls = (tlv_len==-1);
345 sel->left = tlv_len;
vlm72425de2004-09-13 08:31:01 +0000346 ASN_DEBUG("+EXPECT2 left=%d wn=%d, clvl=%d",
347 sel->left, sel->want_nulls, sel->cont_level);
vlmfa67ddc2004-06-03 03:38:44 +0000348 } else {
349 RETURN(RC_FAIL);
350 }
351
vlm72425de2004-09-13 08:31:01 +0000352 if(type_type == _TT_ANY) APPEND(buf_ptr, tl + ll);
vlmfa67ddc2004-06-03 03:38:44 +0000353 ADVANCE(tl+ll);
354 } while(tlv_constr);
355 if(sel == NULL) {
356 /* Finished operation, "phase out" */
vlm72425de2004-09-13 08:31:01 +0000357 ASN_DEBUG("Phase out");
vlmfa67ddc2004-06-03 03:38:44 +0000358 _CH_PHASE(ctx, +3);
359 break;
360 }
361
362 NEXT_PHASE(ctx);
363 /* Fall through */
364 case 2:
vlmda674682004-08-11 09:07:36 +0000365 (void *)stck = ctx->ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000366 sel = stck->cur_ptr;
367 ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld",
368 (long)sel->left, (long)size);
369 {
370 ber_tlv_len_t len;
371
372 assert(sel->left >= 0);
373
vlmc5190612004-08-18 04:53:32 +0000374 len = ((ber_tlv_len_t)size < sel->left)
375 ? (ber_tlv_len_t)size : sel->left;
vlmfa67ddc2004-06-03 03:38:44 +0000376 if(len > 0) {
vlm72425de2004-09-13 08:31:01 +0000377 if(type_type == _TT_BIT_STRING
378 && sel->bits_chopped == 0) {
vlmfa67ddc2004-06-03 03:38:44 +0000379 /*
380 * Finalize the previous chunk:
381 * strip down unused bits.
382 */
383 st->buf[st->size-1] &= 0xff << st->buf[0];
384
vlm1ff928d2004-08-11 08:10:13 +0000385 APPEND(((char *)buf_ptr+1), (len - 1));
vlmfa67ddc2004-06-03 03:38:44 +0000386 st->buf[0] = *(uint8_t *)buf_ptr;
387 sel->bits_chopped = 1;
388 } else {
389 APPEND(buf_ptr, len);
390 }
391 ADVANCE(len);
392 sel->left -= len;
393 }
394
395 if(sel->left) {
396 RETURN(RC_WMORE);
397 } else {
398 sel->left = 0;
399 if(sel->prev)
400 sel = stck->cur_ptr = sel->prev;
401 PREV_PHASE(ctx);
402 goto phase1;
403 }
404 }
405 break;
406 case 3:
407 phase3:
408 /*
409 * Primitive form, no stack required.
410 */
vlmb42843a2004-06-05 08:17:50 +0000411 if(size < (size_t)ctx->left) {
vlmfa67ddc2004-06-03 03:38:44 +0000412 APPEND(buf_ptr, size);
413 ctx->left -= size;
414 ADVANCE(size);
415 RETURN(RC_WMORE);
416 } else {
417 APPEND(buf_ptr, ctx->left);
418 ADVANCE(ctx->left);
419 ctx->left = 0;
420
421 NEXT_PHASE(ctx);
422 }
423 break;
424 }
425
426 /*
427 * BIT STRING-specific processing.
428 */
vlm72425de2004-09-13 08:31:01 +0000429 if(type_type == _TT_BIT_STRING && st->size >= 2) {
vlmfa67ddc2004-06-03 03:38:44 +0000430 /* Finalize BIT STRING: zero out unused bits. */
431 st->buf[st->size-1] &= 0xff << st->buf[0];
432 }
433
434 ASN_DEBUG("Took %d bytes to encode %s: [%s]:%d",
435 consumed_myself, td->name, st->buf, st->size);
436
437 rval.code = RC_OK;
438 rval.consumed = consumed_myself;
439
440 return rval;
441}
442
443/*
444 * Encode OCTET STRING type using DER.
445 */
vlm39ba4c42004-09-22 16:06:28 +0000446asn_enc_rval_t
vlm3e693022004-09-02 12:57:25 +0000447OCTET_STRING_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
vlmfa67ddc2004-06-03 03:38:44 +0000448 int tag_mode, ber_tlv_tag_t tag,
449 asn_app_consume_bytes_f *cb, void *app_key) {
vlm39ba4c42004-09-22 16:06:28 +0000450 asn_enc_rval_t erval;
vlmda674682004-08-11 09:07:36 +0000451 OCTET_STRING_t *st = (OCTET_STRING_t *)ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000452 int add_byte = 0;
vlm7e66aa82004-09-02 12:11:47 +0000453 int is_bit_str = (td->specifics == (void *)-1);
vlm3e693022004-09-02 12:57:25 +0000454 int is_ANY_type = (td->specifics == (void *)1);
vlmfa67ddc2004-06-03 03:38:44 +0000455
456 ASN_DEBUG("%s %s as OCTET STRING",
vlm3e693022004-09-02 12:57:25 +0000457 cb?"Estimating":"Encoding", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000458
459 /*
460 * Canonicalize BIT STRING.
461 */
vlm7e66aa82004-09-02 12:11:47 +0000462 if(is_bit_str && st->buf) {
vlmfa67ddc2004-06-03 03:38:44 +0000463 switch(st->size) {
464 case 0: add_byte = 1; break;
465 case 1: st->buf[0] = 0; break;
466 default:
467 /* Finalize BIT STRING: zero out unused bits. */
468 st->buf[st->size-1] &= 0xff << st->buf[0];
469 }
470 }
471
vlm7e66aa82004-09-02 12:11:47 +0000472 if(is_ANY_type) {
473 erval.encoded = 0;
474 } else {
vlm3e693022004-09-02 12:57:25 +0000475 erval.encoded = der_write_tags(td, st->size + add_byte,
vlm7e66aa82004-09-02 12:11:47 +0000476 tag_mode, tag, cb, app_key);
477 if(erval.encoded == -1) {
vlm3e693022004-09-02 12:57:25 +0000478 erval.failed_type = td;
vlm7e66aa82004-09-02 12:11:47 +0000479 erval.structure_ptr = ptr;
480 return erval;
481 }
vlmfa67ddc2004-06-03 03:38:44 +0000482 }
483
484 if(cb) {
485 uint8_t zero;
486 uint8_t *buf;
487 int size;
488 ssize_t ret;
489
490 /* BIT STRING-aware handling */
491 if(add_byte) {
492 zero = 0;
493 buf = &zero;
494 size = 1;
495 } else if(st->buf) {
496 buf = st->buf;
497 size = st->size;
498 } else {
499 assert(st->size == 0);
500 buf = 0; /* Not used */
501 size = 0;
502 }
503
504 if(size) {
505 ret = cb(buf, size, app_key);
506 if(ret == -1) {
507 erval.encoded = -1;
vlm3e693022004-09-02 12:57:25 +0000508 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000509 erval.structure_ptr = ptr;
510 return erval;
511 }
512 }
513 }
514
515 erval.encoded += st->size + add_byte;
516
517 return erval;
518}
519
vlm39ba4c42004-09-22 16:06:28 +0000520asn_enc_rval_t
521OCTET_STRING_encode_xer(asn1_TYPE_descriptor_t *td, void *sptr,
522 int ilevel, enum xer_encoder_flags_e flags,
523 asn_app_consume_bytes_f *cb, void *app_key) {
524 static const char *h2c = "0123456789ABCDEF";
525 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
526 asn_enc_rval_t er;
527 char scratch[16 * 3 + 4];
528 char *p = scratch;
529 uint8_t *buf;
530 uint8_t *end;
531 size_t i;
532
533 if(!st || !st->buf) {
534 er.encoded = -1;
535 er.failed_type = td;
536 er.structure_ptr = sptr;
537 return er;
538 }
539
540 er.encoded = 0;
541
542 /*
543 * Dump the contents of the buffer in hexadecimal.
544 */
545 buf = st->buf;
546 end = buf + st->size;
547 if(flags & XER_F_CANONICAL) {
548 char *scend = scratch + (sizeof(scratch) - 2);
549 for(; buf < end; buf++) {
550 if(p >= scend) {
551 _ASN_CALLBACK(scratch, p - scratch);
552 er.encoded += p - scratch;
553 p = scratch;
554 }
555 *p++ = h2c[(*buf >> 4) & 0x0F];
556 *p++ = h2c[*buf & 0x0F];
557 }
558 } else {
559 for(i = 0; buf < end; buf++, i++) {
560 if(!(i % 16) && (i || st->size > 16)) {
561 _ASN_CALLBACK(scratch, p-scratch);
562 er.encoded += (p-scratch);
563 p = scratch;
564 _i_ASN_TEXT_INDENT(1, ilevel);
565 }
566 *p++ = h2c[(*buf >> 4) & 0x0F];
567 *p++ = h2c[*buf & 0x0F];
568 *p++ = 0x20;
569 }
570 if(i) p--; /* Remove the tail space */
571 }
572
573 _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */
574 er.encoded += p - scratch;
575
576 return er;
577}
578
579asn_enc_rval_t
580OCTET_STRING_encode_xer_ascii(asn1_TYPE_descriptor_t *td, void *sptr,
581 int ilevel, enum xer_encoder_flags_e flags,
582 asn_app_consume_bytes_f *cb, void *app_key) {
583 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
584 asn_enc_rval_t er;
585
586 (void)ilevel; /* Unused argument */
587 (void)flags; /* Unused argument */
588
589 if(!st || !st->buf)
590 _ASN_ENCODE_FAILED;
591
592 _ASN_CALLBACK(st->buf, st->size);
593 er.encoded = st->size;
594
595 return er;
596}
597
vlmfa67ddc2004-06-03 03:38:44 +0000598int
599OCTET_STRING_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
600 asn_app_consume_bytes_f *cb, void *app_key) {
vlm1ff928d2004-08-11 08:10:13 +0000601 static const char *h2c = "0123456789ABCDEF";
vlmda674682004-08-11 09:07:36 +0000602 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000603 char scratch[16 * 3 + 4];
604 char *p = scratch;
605 uint8_t *buf;
606 uint8_t *end;
607 size_t i;
vlm39ba4c42004-09-22 16:06:28 +0000608 int lvl;
vlmfa67ddc2004-06-03 03:38:44 +0000609
vlmb42843a2004-06-05 08:17:50 +0000610 (void)td; /* Unused argument */
611
vlmfa67ddc2004-06-03 03:38:44 +0000612 if(!st || !st->buf) return cb("<absent>", 8, app_key);
613
614 /*
615 * Dump the contents of the buffer in hexadecimal.
616 */
617 buf = st->buf;
618 end = buf + st->size;
619 for(i = 0; buf < end; buf++, i++) {
620 if(!(i % 16) && (i || st->size > 16)) {
621 if(cb(scratch, p - scratch, app_key)
622 || cb("\n", 1, app_key))
623 return -1;
vlm39ba4c42004-09-22 16:06:28 +0000624 for(lvl = 0; lvl < ilevel; lvl++)
vlmfa67ddc2004-06-03 03:38:44 +0000625 cb(" ", 1, app_key);
626 p = scratch;
627 }
628 *p++ = h2c[(*buf >> 4) & 0x0F];
629 *p++ = h2c[*buf & 0x0F];
vlm39ba4c42004-09-22 16:06:28 +0000630 *p++ = 0x20;
vlmfa67ddc2004-06-03 03:38:44 +0000631 }
vlm39ba4c42004-09-22 16:06:28 +0000632 if(i) p--; /* Remove the tail space */
vlmfa67ddc2004-06-03 03:38:44 +0000633
634 return cb(scratch, p - scratch, app_key);
635}
636
637int
638OCTET_STRING_print_ascii(asn1_TYPE_descriptor_t *td, const void *sptr,
639 int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
vlmda674682004-08-11 09:07:36 +0000640 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000641
vlmb42843a2004-06-05 08:17:50 +0000642 (void)td; /* Unused argument */
643 (void)ilevel; /* Unused argument */
644
vlmfa67ddc2004-06-03 03:38:44 +0000645 if(st && st->buf) {
646 return cb(st->buf, st->size, app_key);
647 } else {
648 return cb("<absent>", 8, app_key);
649 }
650}
651
652void
653OCTET_STRING_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
vlmda674682004-08-11 09:07:36 +0000654 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
655 struct _stack *stck = (struct _stack *)st->_ber_dec_ctx.ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000656
657 if(!td || !st)
658 return;
659
660 ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
661
662 if(st->buf) {
663 FREEMEM(st->buf);
664 }
665
666 /*
667 * Remove decode-time stack.
668 */
669 if(stck) {
670 while(stck->tail) {
671 struct _stack_el *sel = stck->tail;
672 stck->tail = sel->prev;
673 FREEMEM(sel);
674 }
675 FREEMEM(stck);
676 }
677
678 if(!contents_only) {
679 FREEMEM(st);
680 }
681}
682
683/*
684 * Conversion routines.
685 */
686int
687OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
688 void *buf;
689
690 if(st == 0 || (str == 0 && len)) {
691 errno = EINVAL;
692 return -1;
693 }
694
695 /*
696 * Clear the OCTET STRING.
697 */
698 if(str == NULL) {
699 if(st->buf)
700 FREEMEM(st->buf);
701 st->size = 0;
702 return 0;
703 }
704
705 /* Determine the original string size, if not explicitly given */
706 if(len < 0)
707 len = strlen(str);
708
709 /* Allocate and fill the memory */
710 buf = MALLOC(len + 1);
711 if(buf == NULL) {
712 return -1;
713 } else {
vlmda674682004-08-11 09:07:36 +0000714 st->buf = (uint8_t *)buf;
vlmfa67ddc2004-06-03 03:38:44 +0000715 st->size = len;
716 }
717
718 memcpy(buf, str, len);
719 st->buf[st->size] = '\0'; /* Couldn't use memcpy(len+1)! */
720
721 return 0;
722}
723
724OCTET_STRING_t *
725OCTET_STRING_new_fromBuf(const char *str, int len) {
726 OCTET_STRING_t *st;
727
vlmda674682004-08-11 09:07:36 +0000728 (void *)st = CALLOC(1, sizeof(*st));
vlmfa67ddc2004-06-03 03:38:44 +0000729 if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
730 free(st);
731 st = NULL;
732 }
733
734 return st;
735}
736