blob: 65893347a7771964a7ecf4f55bd63c344ce91854 [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001/*-
2 * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <OCTET_STRING.h>
6#include <assert.h>
7#include <errno.h>
8
9/*
10 * OCTET STRING basic type description.
11 */
12static ber_tlv_tag_t asn1_DEF_OCTET_STRING_tags[] = {
13 (ASN_TAG_CLASS_UNIVERSAL | (4 << 2))
14};
15asn1_TYPE_descriptor_t asn1_DEF_OCTET_STRING = {
16 "OCTET STRING",
17 asn_generic_no_constraint,
18 OCTET_STRING_decode_ber,
19 OCTET_STRING_encode_der,
20 OCTET_STRING_print, /* non-ascii stuff, generally */
21 OCTET_STRING_free,
22 0, /* Use generic outmost tag fetcher */
23 asn1_DEF_OCTET_STRING_tags,
24 sizeof(asn1_DEF_OCTET_STRING_tags)
25 / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
Lev Walkinf15320b2004-06-03 03:38:44 +000026 -1, /* Both ways are fine (primitive and constructed) */
Lev Walkin449f8322004-08-20 13:23:42 +000027 0, 0, /* No members */
Lev Walkind9bd7752004-06-05 08:17:50 +000028 0 /* No specifics */
Lev Walkinf15320b2004-06-03 03:38:44 +000029};
30
31#define _CH_PHASE(ctx, inc) do { \
32 if(ctx->phase == 0) \
33 ctx->step = 0; \
34 ctx->phase += inc; \
35 } while(0)
36#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
37#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
38
Lev Walkin4ce78ca2004-08-25 01:34:11 +000039#define ADVANCE(num_bytes) do { \
40 size_t num = num_bytes; \
41 buf_ptr = ((char *)buf_ptr) + num; \
42 size -= num; \
43 consumed_myself += num; \
Lev Walkinf15320b2004-06-03 03:38:44 +000044 } while(0)
45
46#define RETURN(_code) do { \
47 rval.code = _code; \
48 rval.consumed = consumed_myself;\
49 return rval; \
50 } while(0)
51
Lev Walkind9bd7752004-06-05 08:17:50 +000052#define APPEND(bufptr, bufsize) do { \
Lev Walkin8d127872004-09-04 04:44:50 +000053 size_t _bs = (bufsize); \
Lev Walkind9bd7752004-06-05 08:17:50 +000054 size_t _ns = ctx->step; /* Allocated */ \
Lev Walkin8d127872004-09-04 04:44:50 +000055 if(_ns <= (size_t)(st->size + _bs)) { \
Lev Walkind9bd7752004-06-05 08:17:50 +000056 void *ptr; \
57 do { _ns = _ns ? _ns<<2 : 16; } \
Lev Walkin8d127872004-09-04 04:44:50 +000058 while(_ns <= (size_t)(st->size + _bs)); \
Lev Walkind9bd7752004-06-05 08:17:50 +000059 ptr = REALLOC(st->buf, _ns); \
60 if(ptr) { \
Lev Walkinc2346572004-08-11 09:07:36 +000061 st->buf = (uint8_t *)ptr; \
Lev Walkind9bd7752004-06-05 08:17:50 +000062 ctx->step = _ns; \
63 } else { \
64 RETURN(RC_FAIL); \
65 } \
66 } \
Lev Walkin8d127872004-09-04 04:44:50 +000067 memcpy(st->buf + st->size, bufptr, _bs); \
68 st->size += _bs; \
Lev Walkind9bd7752004-06-05 08:17:50 +000069 if(st->size < 0) \
70 /* Why even care?.. JIC */ \
71 RETURN(RC_FAIL); \
72 /* Convenient nul-termination */ \
73 st->buf[st->size] = '\0'; \
Lev Walkinf15320b2004-06-03 03:38:44 +000074 } while(0)
75
76/*
77 * The main reason why ASN.1 is still alive is that too much time and effort
78 * is necessary for learning it more or less adequately, thus creating a gut
79 * necessity to demonstrate that aquired skill everywhere afterwards.
80 * No, I am not going to explain what the following stuff is.
81 */
82struct _stack_el {
83 ber_tlv_len_t left; /* What's left to read */
84 int want_nulls; /* Want null "end of content" octets? */
85 int bits_chopped; /* Flag in BIT STRING mode */
86 struct _stack_el *prev;
87 struct _stack_el *next;
88};
89struct _stack {
90 struct _stack_el *tail;
91 struct _stack_el *cur_ptr;
92};
93
94static struct _stack_el *
95_add_stack_el(struct _stack *st) {
96 struct _stack_el *nel;
97
98 if(st->cur_ptr && st->cur_ptr->next) {
99 nel = st->cur_ptr->next;
100 nel->left = 0;
101 nel->want_nulls = 0;
102 nel->bits_chopped = 0;
103 } else {
Lev Walkinc2346572004-08-11 09:07:36 +0000104 (void *)nel = CALLOC(1, sizeof(struct _stack_el));
Lev Walkinf15320b2004-06-03 03:38:44 +0000105 if(nel == NULL)
106 return NULL;
107
108 if(st->tail) {
109 st->tail->next = nel;
110 }
111 nel->prev = st->tail;
112 st->tail = nel;
113 }
114
115 st->cur_ptr = nel;
116
117 return nel;
118}
119
120static struct _stack *
121_new_stack() {
122 struct _stack *st;
Lev Walkinc2346572004-08-11 09:07:36 +0000123 (void *)st = CALLOC(1, sizeof(struct _stack));
Lev Walkinf15320b2004-06-03 03:38:44 +0000124 if(st == NULL)
125 return NULL;
126
Lev Walkinf15320b2004-06-03 03:38:44 +0000127 return st;
128}
129
130/*
131 * Decode OCTET STRING type.
132 */
133ber_dec_rval_t
134OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
135 void **os_structure, void *buf_ptr, size_t size, int tag_mode) {
Lev Walkinc2346572004-08-11 09:07:36 +0000136 OCTET_STRING_t *st = (OCTET_STRING_t *)*os_structure;
Lev Walkinf15320b2004-06-03 03:38:44 +0000137 ber_dec_rval_t rval;
138 ber_dec_ctx_t *ctx;
Lev Walkin8d127872004-09-04 04:44:50 +0000139 ber_tlv_tag_t terminal_tag; /* Inner tag for constructed types */
Lev Walkinf15320b2004-06-03 03:38:44 +0000140 ssize_t consumed_myself = 0;
141 struct _stack *stck; /* A stack structure */
142 struct _stack_el *sel; /* Stack element */
143 int tlv_constr;
Lev Walkin8d127872004-09-04 04:44:50 +0000144 int is_bit_str = 0; /* See below under switch(td->specifics) */
145 int is_ANY_type = 0; /* See below under switch(td->specifics) */
Lev Walkinf15320b2004-06-03 03:38:44 +0000146
147 ASN_DEBUG("Decoding %s as %s (%ld)",
Lev Walkin8d127872004-09-04 04:44:50 +0000148 td->name, "OCTET STRING", (long)size);
Lev Walkinf15320b2004-06-03 03:38:44 +0000149
150 /*
151 * Create the string if does not exist.
152 */
153 if(st == NULL) {
Lev Walkinc2346572004-08-11 09:07:36 +0000154 (void *)st = *os_structure = CALLOC(1, sizeof(*st));
Lev Walkinf15320b2004-06-03 03:38:44 +0000155 if(st == NULL)
156 RETURN(RC_FAIL);
157 }
158
159 /* Restore parsing context */
160 ctx = &st->_ber_dec_ctx;
161
Lev Walkin8d127872004-09-04 04:44:50 +0000162 switch((int)td->specifics) {
163 case 0:
164 terminal_tag = asn1_DEF_OCTET_STRING_tags[0]; /* [U4] */
165 break;
166 case -1: /* BIT STRING */
167 /*
168 * This is some sort of a hack.
169 * The OCTET STRING decoder is being used in BIT STRING mode.
170 */
171 is_bit_str = 1;
172 terminal_tag = ASN_TAG_CLASS_UNIVERSAL | (3 << 2);
173 break;
174 default: /* Just in case; fall through */
175 case 1: /* ANY type */
176 is_ANY_type = 1;
177 terminal_tag = -1;
178 break;
179 }
180
Lev Walkinf15320b2004-06-03 03:38:44 +0000181 switch(ctx->phase) {
182 case 0:
183 /*
184 * Check tags.
185 */
186 rval = ber_check_tags(td, ctx,
187 buf_ptr, size, tag_mode,
188 &ctx->left, &tlv_constr);
189 if(rval.code != RC_OK) {
190 RETURN(rval.code);
191 }
192
193 ASN_DEBUG("OS length is %d bytes, form %d",
194 (int)ctx->left, tlv_constr);
195
196 if(tlv_constr) {
197 /*
198 * Complex operation, requires stack of expectations.
199 */
200 ctx->ptr = _new_stack();
201 if(ctx->ptr) {
Lev Walkinc2346572004-08-11 09:07:36 +0000202 (void *)stck = ctx->ptr;
Lev Walkin8d127872004-09-04 04:44:50 +0000203#if 0
Lev Walkinf15320b2004-06-03 03:38:44 +0000204 if(ctx->left < 0) {
205 stck->cur_ptr->want_nulls = -ctx->left;
206 stck->cur_ptr->left = -1;
207 } else {
208 stck->cur_ptr->want_nulls = 0;
209 stck->cur_ptr->left = ctx->left;
210 }
Lev Walkin8d127872004-09-04 04:44:50 +0000211 ASN_DEBUG("+EXPECT1 left=%d wn=%d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000212 stck->cur_ptr->left,
213 stck->cur_ptr->want_nulls);
Lev Walkin8d127872004-09-04 04:44:50 +0000214#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000215 if(is_bit_str) {
Lev Walkin8d127872004-09-04 04:44:50 +0000216 /* Number of meaningless tail bits */
Lev Walkinf15320b2004-06-03 03:38:44 +0000217 APPEND("\0", 1);
218 }
219 } else {
220 RETURN(RC_FAIL);
221 }
222 } else {
223 /*
224 * Jump into stackless primitive decoding.
225 */
226 _CH_PHASE(ctx, 3);
Lev Walkin8d127872004-09-04 04:44:50 +0000227 if(is_ANY_type) APPEND(buf_ptr, rval.consumed);
Lev Walkinf15320b2004-06-03 03:38:44 +0000228 ADVANCE(rval.consumed);
229 goto phase3;
230 }
231
Lev Walkinf15320b2004-06-03 03:38:44 +0000232 NEXT_PHASE(ctx);
233 /* Fall through */
234 case 1:
235 phase1:
236 /*
237 * Fill the stack with expectations.
238 */
Lev Walkinc2346572004-08-11 09:07:36 +0000239 (void *)stck = ctx->ptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000240 sel = stck->cur_ptr;
241 do {
242 ber_tlv_tag_t tlv_tag;
243 ber_tlv_len_t tlv_len;
244 ssize_t tl, ll;
245
Lev Walkin8d127872004-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);
Lev Walkinf15320b2004-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,
Lev Walkin4d9528c2004-08-11 08:10:13 +0000258 (char *)buf_ptr + tl, size - tl, &tlv_len);
Lev Walkin8d127872004-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,
Lev Walkinf15320b2004-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
Lev Walkin8d127872004-09-04 04:44:50 +0000269 if(sel && sel->want_nulls
Lev Walkinf15320b2004-06-03 03:38:44 +0000270 && ((uint8_t *)buf_ptr)[0] == 0
271 && ((uint8_t *)buf_ptr)[1] == 0)
272 {
Lev Walkin8d127872004-09-04 04:44:50 +0000273 ADVANCE(2);
274 if(is_ANY_type) APPEND("\0\0", 2);
275
276 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
277
Lev Walkinf15320b2004-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;
Lev Walkin8d127872004-09-04 04:44:50 +0000282 if(sel == NULL)
Lev Walkinf15320b2004-06-03 03:38:44 +0000283 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000284 }
Lev Walkin8d127872004-09-04 04:44:50 +0000285
Lev Walkinf15320b2004-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
Lev Walkin8d127872004-09-04 04:44:50 +0000290 * expectation after current "end of content",
291 * for which tlv_constr is 0.
Lev Walkinf15320b2004-06-03 03:38:44 +0000292 */
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 tlv_constr = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000294 }
Lev Walkin8d127872004-09-04 04:44:50 +0000295
296 continue;
297 } else if(tlv_tag != terminal_tag
298 && terminal_tag != (ber_tlv_tag_t)-1) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000299 char buf[2][32];
300 ber_tlv_tag_snprint(tlv_tag,
301 buf[0], sizeof(buf[0]));
302 ber_tlv_tag_snprint(td->tags[td->tags_count-1],
303 buf[1], sizeof(buf[1]));
304 ASN_DEBUG("Tag does not match expectation: %s != %s",
305 buf[0], buf[1]);
306 RETURN(RC_FAIL);
307 }
308
309 /*
310 * Append a new expectation.
311 */
312 sel = _add_stack_el(stck);
313 if(sel) {
314 sel->want_nulls = (tlv_len==-1);
315 sel->left = tlv_len;
Lev Walkin8d127872004-09-04 04:44:50 +0000316 ASN_DEBUG("+EXPECT2 left=%d wn=%d",
Lev Walkinf15320b2004-06-03 03:38:44 +0000317 sel->left, sel->want_nulls);
318 } else {
319 RETURN(RC_FAIL);
320 }
321
Lev Walkin8d127872004-09-04 04:44:50 +0000322 if(is_ANY_type) APPEND(buf_ptr, tl + ll);
Lev Walkinf15320b2004-06-03 03:38:44 +0000323 ADVANCE(tl+ll);
324 } while(tlv_constr);
325 if(sel == NULL) {
326 /* Finished operation, "phase out" */
327 _CH_PHASE(ctx, +3);
328 break;
329 }
330
331 NEXT_PHASE(ctx);
332 /* Fall through */
333 case 2:
Lev Walkinc2346572004-08-11 09:07:36 +0000334 (void *)stck = ctx->ptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000335 sel = stck->cur_ptr;
336 ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld",
337 (long)sel->left, (long)size);
338 {
339 ber_tlv_len_t len;
340
341 assert(sel->left >= 0);
342
Lev Walkinec1ffd42004-08-18 04:53:32 +0000343 len = ((ber_tlv_len_t)size < sel->left)
344 ? (ber_tlv_len_t)size : sel->left;
Lev Walkinf15320b2004-06-03 03:38:44 +0000345 if(len > 0) {
346 if(is_bit_str && sel->bits_chopped == 0) {
347 /*
348 * Finalize the previous chunk:
349 * strip down unused bits.
350 */
351 st->buf[st->size-1] &= 0xff << st->buf[0];
352
Lev Walkin4d9528c2004-08-11 08:10:13 +0000353 APPEND(((char *)buf_ptr+1), (len - 1));
Lev Walkinf15320b2004-06-03 03:38:44 +0000354 st->buf[0] = *(uint8_t *)buf_ptr;
355 sel->bits_chopped = 1;
356 } else {
357 APPEND(buf_ptr, len);
358 }
359 ADVANCE(len);
360 sel->left -= len;
361 }
362
363 if(sel->left) {
364 RETURN(RC_WMORE);
365 } else {
366 sel->left = 0;
367 if(sel->prev)
368 sel = stck->cur_ptr = sel->prev;
369 PREV_PHASE(ctx);
370 goto phase1;
371 }
372 }
373 break;
374 case 3:
375 phase3:
376 /*
377 * Primitive form, no stack required.
378 */
Lev Walkind9bd7752004-06-05 08:17:50 +0000379 if(size < (size_t)ctx->left) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000380 APPEND(buf_ptr, size);
381 ctx->left -= size;
382 ADVANCE(size);
383 RETURN(RC_WMORE);
384 } else {
385 APPEND(buf_ptr, ctx->left);
386 ADVANCE(ctx->left);
387 ctx->left = 0;
388
389 NEXT_PHASE(ctx);
390 }
391 break;
392 }
393
394 /*
395 * BIT STRING-specific processing.
396 */
397 if(is_bit_str && st->size >= 2) {
398 /* Finalize BIT STRING: zero out unused bits. */
399 st->buf[st->size-1] &= 0xff << st->buf[0];
400 }
401
402 ASN_DEBUG("Took %d bytes to encode %s: [%s]:%d",
403 consumed_myself, td->name, st->buf, st->size);
404
405 rval.code = RC_OK;
406 rval.consumed = consumed_myself;
407
408 return rval;
409}
410
411/*
412 * Encode OCTET STRING type using DER.
413 */
414der_enc_rval_t
Lev Walkin1f670c12004-09-02 12:57:25 +0000415OCTET_STRING_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
Lev Walkinf15320b2004-06-03 03:38:44 +0000416 int tag_mode, ber_tlv_tag_t tag,
417 asn_app_consume_bytes_f *cb, void *app_key) {
418 der_enc_rval_t erval;
Lev Walkinc2346572004-08-11 09:07:36 +0000419 OCTET_STRING_t *st = (OCTET_STRING_t *)ptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000420 int add_byte = 0;
Lev Walkina737f3b2004-09-02 12:11:47 +0000421 int is_bit_str = (td->specifics == (void *)-1);
Lev Walkin1f670c12004-09-02 12:57:25 +0000422 int is_ANY_type = (td->specifics == (void *)1);
Lev Walkinf15320b2004-06-03 03:38:44 +0000423
424 ASN_DEBUG("%s %s as OCTET STRING",
Lev Walkin1f670c12004-09-02 12:57:25 +0000425 cb?"Estimating":"Encoding", td->name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000426
427 /*
428 * Canonicalize BIT STRING.
429 */
Lev Walkina737f3b2004-09-02 12:11:47 +0000430 if(is_bit_str && st->buf) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000431 switch(st->size) {
432 case 0: add_byte = 1; break;
433 case 1: st->buf[0] = 0; break;
434 default:
435 /* Finalize BIT STRING: zero out unused bits. */
436 st->buf[st->size-1] &= 0xff << st->buf[0];
437 }
438 }
439
Lev Walkina737f3b2004-09-02 12:11:47 +0000440 if(is_ANY_type) {
441 erval.encoded = 0;
442 } else {
Lev Walkin1f670c12004-09-02 12:57:25 +0000443 erval.encoded = der_write_tags(td, st->size + add_byte,
Lev Walkina737f3b2004-09-02 12:11:47 +0000444 tag_mode, tag, cb, app_key);
445 if(erval.encoded == -1) {
Lev Walkin1f670c12004-09-02 12:57:25 +0000446 erval.failed_type = td;
Lev Walkina737f3b2004-09-02 12:11:47 +0000447 erval.structure_ptr = ptr;
448 return erval;
449 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000450 }
451
452 if(cb) {
453 uint8_t zero;
454 uint8_t *buf;
455 int size;
456 ssize_t ret;
457
458 /* BIT STRING-aware handling */
459 if(add_byte) {
460 zero = 0;
461 buf = &zero;
462 size = 1;
463 } else if(st->buf) {
464 buf = st->buf;
465 size = st->size;
466 } else {
467 assert(st->size == 0);
468 buf = 0; /* Not used */
469 size = 0;
470 }
471
472 if(size) {
473 ret = cb(buf, size, app_key);
474 if(ret == -1) {
475 erval.encoded = -1;
Lev Walkin1f670c12004-09-02 12:57:25 +0000476 erval.failed_type = td;
Lev Walkinf15320b2004-06-03 03:38:44 +0000477 erval.structure_ptr = ptr;
478 return erval;
479 }
480 }
481 }
482
483 erval.encoded += st->size + add_byte;
484
485 return erval;
486}
487
488int
489OCTET_STRING_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
490 asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkin4d9528c2004-08-11 08:10:13 +0000491 static const char *h2c = "0123456789ABCDEF";
Lev Walkinc2346572004-08-11 09:07:36 +0000492 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000493 char scratch[16 * 3 + 4];
494 char *p = scratch;
495 uint8_t *buf;
496 uint8_t *end;
497 size_t i;
498 int ret;
499
Lev Walkind9bd7752004-06-05 08:17:50 +0000500 (void)td; /* Unused argument */
501
Lev Walkinf15320b2004-06-03 03:38:44 +0000502 if(!st || !st->buf) return cb("<absent>", 8, app_key);
503
504 /*
505 * Dump the contents of the buffer in hexadecimal.
506 */
507 buf = st->buf;
508 end = buf + st->size;
509 for(i = 0; buf < end; buf++, i++) {
510 if(!(i % 16) && (i || st->size > 16)) {
511 if(cb(scratch, p - scratch, app_key)
512 || cb("\n", 1, app_key))
513 return -1;
514 for(ret = 0; ret < ilevel; ret++)
515 cb(" ", 1, app_key);
516 p = scratch;
517 }
518 *p++ = h2c[(*buf >> 4) & 0x0F];
519 *p++ = h2c[*buf & 0x0F];
520 *p++ = ' ';
521 }
522
523 return cb(scratch, p - scratch, app_key);
524}
525
526int
527OCTET_STRING_print_ascii(asn1_TYPE_descriptor_t *td, const void *sptr,
528 int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
Lev Walkinc2346572004-08-11 09:07:36 +0000529 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000530
Lev Walkind9bd7752004-06-05 08:17:50 +0000531 (void)td; /* Unused argument */
532 (void)ilevel; /* Unused argument */
533
Lev Walkinf15320b2004-06-03 03:38:44 +0000534 if(st && st->buf) {
535 return cb(st->buf, st->size, app_key);
536 } else {
537 return cb("<absent>", 8, app_key);
538 }
539}
540
541void
542OCTET_STRING_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
Lev Walkinc2346572004-08-11 09:07:36 +0000543 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
544 struct _stack *stck = (struct _stack *)st->_ber_dec_ctx.ptr;
Lev Walkinf15320b2004-06-03 03:38:44 +0000545
546 if(!td || !st)
547 return;
548
549 ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
550
551 if(st->buf) {
552 FREEMEM(st->buf);
553 }
554
555 /*
556 * Remove decode-time stack.
557 */
558 if(stck) {
559 while(stck->tail) {
560 struct _stack_el *sel = stck->tail;
561 stck->tail = sel->prev;
562 FREEMEM(sel);
563 }
564 FREEMEM(stck);
565 }
566
567 if(!contents_only) {
568 FREEMEM(st);
569 }
570}
571
572/*
573 * Conversion routines.
574 */
575int
576OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
577 void *buf;
578
579 if(st == 0 || (str == 0 && len)) {
580 errno = EINVAL;
581 return -1;
582 }
583
584 /*
585 * Clear the OCTET STRING.
586 */
587 if(str == NULL) {
588 if(st->buf)
589 FREEMEM(st->buf);
590 st->size = 0;
591 return 0;
592 }
593
594 /* Determine the original string size, if not explicitly given */
595 if(len < 0)
596 len = strlen(str);
597
598 /* Allocate and fill the memory */
599 buf = MALLOC(len + 1);
600 if(buf == NULL) {
601 return -1;
602 } else {
Lev Walkinc2346572004-08-11 09:07:36 +0000603 st->buf = (uint8_t *)buf;
Lev Walkinf15320b2004-06-03 03:38:44 +0000604 st->size = len;
605 }
606
607 memcpy(buf, str, len);
608 st->buf[st->size] = '\0'; /* Couldn't use memcpy(len+1)! */
609
610 return 0;
611}
612
613OCTET_STRING_t *
614OCTET_STRING_new_fromBuf(const char *str, int len) {
615 OCTET_STRING_t *st;
616
Lev Walkinc2346572004-08-11 09:07:36 +0000617 (void *)st = CALLOC(1, sizeof(*st));
Lev Walkinf15320b2004-06-03 03:38:44 +0000618 if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
619 free(st);
620 st = NULL;
621 }
622
623 return st;
624}
625