blob: 71d59d3d52f23b832e455885adaafcb1391658d2 [file] [log] [blame]
vlmfa67ddc2004-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]),
26 1, /* Single UNIVERSAL tag may be implicitly overriden */
27 -1, /* Both ways are fine (primitive and constructed) */
vlme413c122004-08-20 13:23:42 +000028 0, 0, /* No members */
vlmb42843a2004-06-05 08:17:50 +000029 0 /* No specifics */
vlmfa67ddc2004-06-03 03:38:44 +000030};
31
32#define _CH_PHASE(ctx, inc) do { \
33 if(ctx->phase == 0) \
34 ctx->step = 0; \
35 ctx->phase += inc; \
36 } while(0)
37#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1)
38#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1)
39
vlmd86c9252004-08-25 01:34:11 +000040#define ADVANCE(num_bytes) do { \
41 size_t num = num_bytes; \
42 buf_ptr = ((char *)buf_ptr) + num; \
43 size -= num; \
44 consumed_myself += num; \
vlmfa67ddc2004-06-03 03:38:44 +000045 } while(0)
46
47#define RETURN(_code) do { \
48 rval.code = _code; \
49 rval.consumed = consumed_myself;\
50 return rval; \
51 } while(0)
52
vlmb42843a2004-06-05 08:17:50 +000053#define APPEND(bufptr, bufsize) do { \
vlmcdfdb722004-09-04 04:44:50 +000054 size_t _bs = (bufsize); \
vlmb42843a2004-06-05 08:17:50 +000055 size_t _ns = ctx->step; /* Allocated */ \
vlmcdfdb722004-09-04 04:44:50 +000056 if(_ns <= (size_t)(st->size + _bs)) { \
vlmb42843a2004-06-05 08:17:50 +000057 void *ptr; \
58 do { _ns = _ns ? _ns<<2 : 16; } \
vlmcdfdb722004-09-04 04:44:50 +000059 while(_ns <= (size_t)(st->size + _bs)); \
vlmb42843a2004-06-05 08:17:50 +000060 ptr = REALLOC(st->buf, _ns); \
61 if(ptr) { \
vlmda674682004-08-11 09:07:36 +000062 st->buf = (uint8_t *)ptr; \
vlmb42843a2004-06-05 08:17:50 +000063 ctx->step = _ns; \
64 } else { \
65 RETURN(RC_FAIL); \
66 } \
67 } \
vlmcdfdb722004-09-04 04:44:50 +000068 memcpy(st->buf + st->size, bufptr, _bs); \
69 st->size += _bs; \
vlmb42843a2004-06-05 08:17:50 +000070 if(st->size < 0) \
71 /* Why even care?.. JIC */ \
72 RETURN(RC_FAIL); \
73 /* Convenient nul-termination */ \
74 st->buf[st->size] = '\0'; \
vlmfa67ddc2004-06-03 03:38:44 +000075 } while(0)
76
77/*
78 * The main reason why ASN.1 is still alive is that too much time and effort
79 * is necessary for learning it more or less adequately, thus creating a gut
80 * necessity to demonstrate that aquired skill everywhere afterwards.
81 * No, I am not going to explain what the following stuff is.
82 */
83struct _stack_el {
84 ber_tlv_len_t left; /* What's left to read */
85 int want_nulls; /* Want null "end of content" octets? */
86 int bits_chopped; /* Flag in BIT STRING mode */
87 struct _stack_el *prev;
88 struct _stack_el *next;
89};
90struct _stack {
91 struct _stack_el *tail;
92 struct _stack_el *cur_ptr;
93};
94
95static struct _stack_el *
96_add_stack_el(struct _stack *st) {
97 struct _stack_el *nel;
98
99 if(st->cur_ptr && st->cur_ptr->next) {
100 nel = st->cur_ptr->next;
101 nel->left = 0;
102 nel->want_nulls = 0;
103 nel->bits_chopped = 0;
104 } else {
vlmda674682004-08-11 09:07:36 +0000105 (void *)nel = CALLOC(1, sizeof(struct _stack_el));
vlmfa67ddc2004-06-03 03:38:44 +0000106 if(nel == NULL)
107 return NULL;
108
109 if(st->tail) {
110 st->tail->next = nel;
111 }
112 nel->prev = st->tail;
113 st->tail = nel;
114 }
115
116 st->cur_ptr = nel;
117
118 return nel;
119}
120
121static struct _stack *
122_new_stack() {
123 struct _stack *st;
vlmda674682004-08-11 09:07:36 +0000124 (void *)st = CALLOC(1, sizeof(struct _stack));
vlmfa67ddc2004-06-03 03:38:44 +0000125 if(st == NULL)
126 return NULL;
127
vlmfa67ddc2004-06-03 03:38:44 +0000128 return st;
129}
130
131/*
132 * Decode OCTET STRING type.
133 */
134ber_dec_rval_t
135OCTET_STRING_decode_ber(asn1_TYPE_descriptor_t *td,
136 void **os_structure, void *buf_ptr, size_t size, int tag_mode) {
vlmda674682004-08-11 09:07:36 +0000137 OCTET_STRING_t *st = (OCTET_STRING_t *)*os_structure;
vlmfa67ddc2004-06-03 03:38:44 +0000138 ber_dec_rval_t rval;
139 ber_dec_ctx_t *ctx;
vlmcdfdb722004-09-04 04:44:50 +0000140 ber_tlv_tag_t terminal_tag; /* Inner tag for constructed types */
vlmfa67ddc2004-06-03 03:38:44 +0000141 ssize_t consumed_myself = 0;
142 struct _stack *stck; /* A stack structure */
143 struct _stack_el *sel; /* Stack element */
144 int tlv_constr;
vlmcdfdb722004-09-04 04:44:50 +0000145 int is_bit_str = 0; /* See below under switch(td->specifics) */
146 int is_ANY_type = 0; /* See below under switch(td->specifics) */
vlmfa67ddc2004-06-03 03:38:44 +0000147
148 ASN_DEBUG("Decoding %s as %s (%ld)",
vlmcdfdb722004-09-04 04:44:50 +0000149 td->name, "OCTET STRING", (long)size);
vlmfa67ddc2004-06-03 03:38:44 +0000150
151 /*
152 * Create the string if does not exist.
153 */
154 if(st == NULL) {
vlmda674682004-08-11 09:07:36 +0000155 (void *)st = *os_structure = CALLOC(1, sizeof(*st));
vlmfa67ddc2004-06-03 03:38:44 +0000156 if(st == NULL)
157 RETURN(RC_FAIL);
158 }
159
160 /* Restore parsing context */
161 ctx = &st->_ber_dec_ctx;
162
vlmcdfdb722004-09-04 04:44:50 +0000163 switch((int)td->specifics) {
164 case 0:
165 terminal_tag = asn1_DEF_OCTET_STRING_tags[0]; /* [U4] */
166 break;
167 case -1: /* BIT STRING */
168 /*
169 * This is some sort of a hack.
170 * The OCTET STRING decoder is being used in BIT STRING mode.
171 */
172 is_bit_str = 1;
173 terminal_tag = ASN_TAG_CLASS_UNIVERSAL | (3 << 2);
174 break;
175 default: /* Just in case; fall through */
176 case 1: /* ANY type */
177 is_ANY_type = 1;
178 terminal_tag = -1;
179 break;
180 }
181
vlmfa67ddc2004-06-03 03:38:44 +0000182 switch(ctx->phase) {
183 case 0:
184 /*
185 * Check tags.
186 */
187 rval = ber_check_tags(td, ctx,
188 buf_ptr, size, tag_mode,
189 &ctx->left, &tlv_constr);
190 if(rval.code != RC_OK) {
191 RETURN(rval.code);
192 }
193
194 ASN_DEBUG("OS length is %d bytes, form %d",
195 (int)ctx->left, tlv_constr);
196
197 if(tlv_constr) {
198 /*
199 * Complex operation, requires stack of expectations.
200 */
201 ctx->ptr = _new_stack();
202 if(ctx->ptr) {
vlmda674682004-08-11 09:07:36 +0000203 (void *)stck = ctx->ptr;
vlmcdfdb722004-09-04 04:44:50 +0000204#if 0
vlmfa67ddc2004-06-03 03:38:44 +0000205 if(ctx->left < 0) {
206 stck->cur_ptr->want_nulls = -ctx->left;
207 stck->cur_ptr->left = -1;
208 } else {
209 stck->cur_ptr->want_nulls = 0;
210 stck->cur_ptr->left = ctx->left;
211 }
vlmcdfdb722004-09-04 04:44:50 +0000212 ASN_DEBUG("+EXPECT1 left=%d wn=%d",
vlmfa67ddc2004-06-03 03:38:44 +0000213 stck->cur_ptr->left,
214 stck->cur_ptr->want_nulls);
vlmcdfdb722004-09-04 04:44:50 +0000215#endif
vlmfa67ddc2004-06-03 03:38:44 +0000216 if(is_bit_str) {
vlmcdfdb722004-09-04 04:44:50 +0000217 /* Number of meaningless tail bits */
vlmfa67ddc2004-06-03 03:38:44 +0000218 APPEND("\0", 1);
219 }
220 } else {
221 RETURN(RC_FAIL);
222 }
223 } else {
224 /*
225 * Jump into stackless primitive decoding.
226 */
227 _CH_PHASE(ctx, 3);
vlmcdfdb722004-09-04 04:44:50 +0000228 if(is_ANY_type) APPEND(buf_ptr, rval.consumed);
vlmfa67ddc2004-06-03 03:38:44 +0000229 ADVANCE(rval.consumed);
230 goto phase3;
231 }
232
vlmfa67ddc2004-06-03 03:38:44 +0000233 NEXT_PHASE(ctx);
234 /* Fall through */
235 case 1:
236 phase1:
237 /*
238 * Fill the stack with expectations.
239 */
vlmda674682004-08-11 09:07:36 +0000240 (void *)stck = ctx->ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000241 sel = stck->cur_ptr;
242 do {
243 ber_tlv_tag_t tlv_tag;
244 ber_tlv_len_t tlv_len;
245 ssize_t tl, ll;
246
vlmcdfdb722004-09-04 04:44:50 +0000247 ASN_DEBUG("fetch tag(size=%d), %sstack, left=%d, want0=%d",
248 (int)size, sel?"":"!",
249 sel?sel->left:0, sel?sel->want_nulls:0);
vlmfa67ddc2004-06-03 03:38:44 +0000250 tl = ber_fetch_tag(buf_ptr, size, &tlv_tag);
251 switch(tl) {
252 case -1: RETURN(RC_FAIL);
253 case 0: RETURN(RC_WMORE);
254 }
255
256 tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr);
257
258 ll = ber_fetch_length(tlv_constr,
vlm1ff928d2004-08-11 08:10:13 +0000259 (char *)buf_ptr + tl, size - tl, &tlv_len);
vlmcdfdb722004-09-04 04:44:50 +0000260 ASN_DEBUG("Got tag=%s, tc=%d, size=%d, tl=%d, len=%d, ll=%d, {%d, %d}",
261 ber_tlv_tag_string(tlv_tag), tlv_constr,
262 (int)size, tl, tlv_len, ll,
vlmfa67ddc2004-06-03 03:38:44 +0000263 ((uint8_t *)buf_ptr)[0],
264 ((uint8_t *)buf_ptr)[1]);
265 switch(ll) {
266 case -1: RETURN(RC_FAIL);
267 case 0: RETURN(RC_WMORE);
268 }
269
vlmcdfdb722004-09-04 04:44:50 +0000270 if(sel && sel->want_nulls
vlmfa67ddc2004-06-03 03:38:44 +0000271 && ((uint8_t *)buf_ptr)[0] == 0
272 && ((uint8_t *)buf_ptr)[1] == 0)
273 {
vlmcdfdb722004-09-04 04:44:50 +0000274 ADVANCE(2);
275 if(is_ANY_type) APPEND("\0\0", 2);
276
277 ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
278
vlmfa67ddc2004-06-03 03:38:44 +0000279 sel->want_nulls--;
280 if(sel->want_nulls == 0) {
281 /* Move to the next expectation */
282 sel = stck->cur_ptr = sel->prev;
vlmcdfdb722004-09-04 04:44:50 +0000283 if(sel == NULL)
vlmfa67ddc2004-06-03 03:38:44 +0000284 break;
vlmfa67ddc2004-06-03 03:38:44 +0000285 }
vlmcdfdb722004-09-04 04:44:50 +0000286
vlmfa67ddc2004-06-03 03:38:44 +0000287 if(sel->want_nulls) {
288 /*
289 * Simulate while(TRUE) for this loop.
290 * This is necessary to fetch the next
vlmcdfdb722004-09-04 04:44:50 +0000291 * expectation after current "end of content",
292 * for which tlv_constr is 0.
vlmfa67ddc2004-06-03 03:38:44 +0000293 */
vlmfa67ddc2004-06-03 03:38:44 +0000294 tlv_constr = 1;
vlmfa67ddc2004-06-03 03:38:44 +0000295 }
vlmcdfdb722004-09-04 04:44:50 +0000296
297 continue;
298 } else if(tlv_tag != terminal_tag
299 && terminal_tag != (ber_tlv_tag_t)-1) {
vlmfa67ddc2004-06-03 03:38:44 +0000300 char buf[2][32];
301 ber_tlv_tag_snprint(tlv_tag,
302 buf[0], sizeof(buf[0]));
303 ber_tlv_tag_snprint(td->tags[td->tags_count-1],
304 buf[1], sizeof(buf[1]));
305 ASN_DEBUG("Tag does not match expectation: %s != %s",
306 buf[0], buf[1]);
307 RETURN(RC_FAIL);
308 }
309
310 /*
311 * Append a new expectation.
312 */
313 sel = _add_stack_el(stck);
314 if(sel) {
315 sel->want_nulls = (tlv_len==-1);
316 sel->left = tlv_len;
vlmcdfdb722004-09-04 04:44:50 +0000317 ASN_DEBUG("+EXPECT2 left=%d wn=%d",
vlmfa67ddc2004-06-03 03:38:44 +0000318 sel->left, sel->want_nulls);
319 } else {
320 RETURN(RC_FAIL);
321 }
322
vlmcdfdb722004-09-04 04:44:50 +0000323 if(is_ANY_type) APPEND(buf_ptr, tl + ll);
vlmfa67ddc2004-06-03 03:38:44 +0000324 ADVANCE(tl+ll);
325 } while(tlv_constr);
326 if(sel == NULL) {
327 /* Finished operation, "phase out" */
328 _CH_PHASE(ctx, +3);
329 break;
330 }
331
332 NEXT_PHASE(ctx);
333 /* Fall through */
334 case 2:
vlmda674682004-08-11 09:07:36 +0000335 (void *)stck = ctx->ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000336 sel = stck->cur_ptr;
337 ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld",
338 (long)sel->left, (long)size);
339 {
340 ber_tlv_len_t len;
341
342 assert(sel->left >= 0);
343
vlmc5190612004-08-18 04:53:32 +0000344 len = ((ber_tlv_len_t)size < sel->left)
345 ? (ber_tlv_len_t)size : sel->left;
vlmfa67ddc2004-06-03 03:38:44 +0000346 if(len > 0) {
347 if(is_bit_str && sel->bits_chopped == 0) {
348 /*
349 * Finalize the previous chunk:
350 * strip down unused bits.
351 */
352 st->buf[st->size-1] &= 0xff << st->buf[0];
353
vlm1ff928d2004-08-11 08:10:13 +0000354 APPEND(((char *)buf_ptr+1), (len - 1));
vlmfa67ddc2004-06-03 03:38:44 +0000355 st->buf[0] = *(uint8_t *)buf_ptr;
356 sel->bits_chopped = 1;
357 } else {
358 APPEND(buf_ptr, len);
359 }
360 ADVANCE(len);
361 sel->left -= len;
362 }
363
364 if(sel->left) {
365 RETURN(RC_WMORE);
366 } else {
367 sel->left = 0;
368 if(sel->prev)
369 sel = stck->cur_ptr = sel->prev;
370 PREV_PHASE(ctx);
371 goto phase1;
372 }
373 }
374 break;
375 case 3:
376 phase3:
377 /*
378 * Primitive form, no stack required.
379 */
vlmb42843a2004-06-05 08:17:50 +0000380 if(size < (size_t)ctx->left) {
vlmfa67ddc2004-06-03 03:38:44 +0000381 APPEND(buf_ptr, size);
382 ctx->left -= size;
383 ADVANCE(size);
384 RETURN(RC_WMORE);
385 } else {
386 APPEND(buf_ptr, ctx->left);
387 ADVANCE(ctx->left);
388 ctx->left = 0;
389
390 NEXT_PHASE(ctx);
391 }
392 break;
393 }
394
395 /*
396 * BIT STRING-specific processing.
397 */
398 if(is_bit_str && st->size >= 2) {
399 /* Finalize BIT STRING: zero out unused bits. */
400 st->buf[st->size-1] &= 0xff << st->buf[0];
401 }
402
403 ASN_DEBUG("Took %d bytes to encode %s: [%s]:%d",
404 consumed_myself, td->name, st->buf, st->size);
405
406 rval.code = RC_OK;
407 rval.consumed = consumed_myself;
408
409 return rval;
410}
411
412/*
413 * Encode OCTET STRING type using DER.
414 */
415der_enc_rval_t
vlm3e693022004-09-02 12:57:25 +0000416OCTET_STRING_encode_der(asn1_TYPE_descriptor_t *td, void *ptr,
vlmfa67ddc2004-06-03 03:38:44 +0000417 int tag_mode, ber_tlv_tag_t tag,
418 asn_app_consume_bytes_f *cb, void *app_key) {
419 der_enc_rval_t erval;
vlmda674682004-08-11 09:07:36 +0000420 OCTET_STRING_t *st = (OCTET_STRING_t *)ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000421 int add_byte = 0;
vlm7e66aa82004-09-02 12:11:47 +0000422 int is_bit_str = (td->specifics == (void *)-1);
vlm3e693022004-09-02 12:57:25 +0000423 int is_ANY_type = (td->specifics == (void *)1);
vlmfa67ddc2004-06-03 03:38:44 +0000424
425 ASN_DEBUG("%s %s as OCTET STRING",
vlm3e693022004-09-02 12:57:25 +0000426 cb?"Estimating":"Encoding", td->name);
vlmfa67ddc2004-06-03 03:38:44 +0000427
428 /*
429 * Canonicalize BIT STRING.
430 */
vlm7e66aa82004-09-02 12:11:47 +0000431 if(is_bit_str && st->buf) {
vlmfa67ddc2004-06-03 03:38:44 +0000432 switch(st->size) {
433 case 0: add_byte = 1; break;
434 case 1: st->buf[0] = 0; break;
435 default:
436 /* Finalize BIT STRING: zero out unused bits. */
437 st->buf[st->size-1] &= 0xff << st->buf[0];
438 }
439 }
440
vlm7e66aa82004-09-02 12:11:47 +0000441 if(is_ANY_type) {
442 erval.encoded = 0;
443 } else {
vlm3e693022004-09-02 12:57:25 +0000444 erval.encoded = der_write_tags(td, st->size + add_byte,
vlm7e66aa82004-09-02 12:11:47 +0000445 tag_mode, tag, cb, app_key);
446 if(erval.encoded == -1) {
vlm3e693022004-09-02 12:57:25 +0000447 erval.failed_type = td;
vlm7e66aa82004-09-02 12:11:47 +0000448 erval.structure_ptr = ptr;
449 return erval;
450 }
vlmfa67ddc2004-06-03 03:38:44 +0000451 }
452
453 if(cb) {
454 uint8_t zero;
455 uint8_t *buf;
456 int size;
457 ssize_t ret;
458
459 /* BIT STRING-aware handling */
460 if(add_byte) {
461 zero = 0;
462 buf = &zero;
463 size = 1;
464 } else if(st->buf) {
465 buf = st->buf;
466 size = st->size;
467 } else {
468 assert(st->size == 0);
469 buf = 0; /* Not used */
470 size = 0;
471 }
472
473 if(size) {
474 ret = cb(buf, size, app_key);
475 if(ret == -1) {
476 erval.encoded = -1;
vlm3e693022004-09-02 12:57:25 +0000477 erval.failed_type = td;
vlmfa67ddc2004-06-03 03:38:44 +0000478 erval.structure_ptr = ptr;
479 return erval;
480 }
481 }
482 }
483
484 erval.encoded += st->size + add_byte;
485
486 return erval;
487}
488
489int
490OCTET_STRING_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
491 asn_app_consume_bytes_f *cb, void *app_key) {
vlm1ff928d2004-08-11 08:10:13 +0000492 static const char *h2c = "0123456789ABCDEF";
vlmda674682004-08-11 09:07:36 +0000493 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000494 char scratch[16 * 3 + 4];
495 char *p = scratch;
496 uint8_t *buf;
497 uint8_t *end;
498 size_t i;
499 int ret;
500
vlmb42843a2004-06-05 08:17:50 +0000501 (void)td; /* Unused argument */
502
vlmfa67ddc2004-06-03 03:38:44 +0000503 if(!st || !st->buf) return cb("<absent>", 8, app_key);
504
505 /*
506 * Dump the contents of the buffer in hexadecimal.
507 */
508 buf = st->buf;
509 end = buf + st->size;
510 for(i = 0; buf < end; buf++, i++) {
511 if(!(i % 16) && (i || st->size > 16)) {
512 if(cb(scratch, p - scratch, app_key)
513 || cb("\n", 1, app_key))
514 return -1;
515 for(ret = 0; ret < ilevel; ret++)
516 cb(" ", 1, app_key);
517 p = scratch;
518 }
519 *p++ = h2c[(*buf >> 4) & 0x0F];
520 *p++ = h2c[*buf & 0x0F];
521 *p++ = ' ';
522 }
523
524 return cb(scratch, p - scratch, app_key);
525}
526
527int
528OCTET_STRING_print_ascii(asn1_TYPE_descriptor_t *td, const void *sptr,
529 int ilevel, asn_app_consume_bytes_f *cb, void *app_key) {
vlmda674682004-08-11 09:07:36 +0000530 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
vlmfa67ddc2004-06-03 03:38:44 +0000531
vlmb42843a2004-06-05 08:17:50 +0000532 (void)td; /* Unused argument */
533 (void)ilevel; /* Unused argument */
534
vlmfa67ddc2004-06-03 03:38:44 +0000535 if(st && st->buf) {
536 return cb(st->buf, st->size, app_key);
537 } else {
538 return cb("<absent>", 8, app_key);
539 }
540}
541
542void
543OCTET_STRING_free(asn1_TYPE_descriptor_t *td, void *sptr, int contents_only) {
vlmda674682004-08-11 09:07:36 +0000544 OCTET_STRING_t *st = (OCTET_STRING_t *)sptr;
545 struct _stack *stck = (struct _stack *)st->_ber_dec_ctx.ptr;
vlmfa67ddc2004-06-03 03:38:44 +0000546
547 if(!td || !st)
548 return;
549
550 ASN_DEBUG("Freeing %s as OCTET STRING", td->name);
551
552 if(st->buf) {
553 FREEMEM(st->buf);
554 }
555
556 /*
557 * Remove decode-time stack.
558 */
559 if(stck) {
560 while(stck->tail) {
561 struct _stack_el *sel = stck->tail;
562 stck->tail = sel->prev;
563 FREEMEM(sel);
564 }
565 FREEMEM(stck);
566 }
567
568 if(!contents_only) {
569 FREEMEM(st);
570 }
571}
572
573/*
574 * Conversion routines.
575 */
576int
577OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) {
578 void *buf;
579
580 if(st == 0 || (str == 0 && len)) {
581 errno = EINVAL;
582 return -1;
583 }
584
585 /*
586 * Clear the OCTET STRING.
587 */
588 if(str == NULL) {
589 if(st->buf)
590 FREEMEM(st->buf);
591 st->size = 0;
592 return 0;
593 }
594
595 /* Determine the original string size, if not explicitly given */
596 if(len < 0)
597 len = strlen(str);
598
599 /* Allocate and fill the memory */
600 buf = MALLOC(len + 1);
601 if(buf == NULL) {
602 return -1;
603 } else {
vlmda674682004-08-11 09:07:36 +0000604 st->buf = (uint8_t *)buf;
vlmfa67ddc2004-06-03 03:38:44 +0000605 st->size = len;
606 }
607
608 memcpy(buf, str, len);
609 st->buf[st->size] = '\0'; /* Couldn't use memcpy(len+1)! */
610
611 return 0;
612}
613
614OCTET_STRING_t *
615OCTET_STRING_new_fromBuf(const char *str, int len) {
616 OCTET_STRING_t *st;
617
vlmda674682004-08-11 09:07:36 +0000618 (void *)st = CALLOC(1, sizeof(*st));
vlmfa67ddc2004-06-03 03:38:44 +0000619 if(st && str && OCTET_STRING_fromBuf(st, str, len)) {
620 free(st);
621 st = NULL;
622 }
623
624 return st;
625}
626