blob: 6bb3613552a6f760ea162777af312bf7dd7de702 [file] [log] [blame]
Lev Walkine7318792004-09-26 13:11:01 +00001/*-
2 * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
3 * Redistribution and modifications are permitted subject to BSD license.
4 */
5#include <asn_internal.h>
6#include <ber_codec_prim.h>
7#include <assert.h>
8#include <errno.h>
9
10/*
11 * Decode an always-primitive type.
12 */
13ber_dec_rval_t
14ber_decode_primitive(asn1_TYPE_descriptor_t *td,
15 void **sptr, void *buf_ptr, size_t size, int tag_mode) {
16 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr;
17 ber_dec_rval_t rval;
18 ber_tlv_len_t length;
19
20 /*
21 * If the structure is not there, allocate it.
22 */
23 if(st == NULL) {
24 (void *)st = *sptr = CALLOC(1, sizeof(*st));
25 if(st == NULL) {
26 rval.code = RC_FAIL;
27 rval.consumed = 0;
28 return rval;
29 }
30 }
31
32 ASN_DEBUG("Decoding %s as plain primitive (tm=%d)",
33 td->name, tag_mode);
34
35 /*
36 * Check tags and extract value length.
37 */
38 rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0);
39 if(rval.code != RC_OK)
40 return rval;
41
42 ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
43
44 /*
45 * Make sure we have this length.
46 */
47 buf_ptr = ((char *)buf_ptr) + rval.consumed;
48 size -= rval.consumed;
49 if(length > (ber_tlv_len_t)size) {
50 rval.code = RC_WMORE;
51 rval.consumed = 0;
52 return rval;
53 }
54
55 st->buf = (uint8_t *)MALLOC(length + 1);
56 if(st->buf) {
57 st->size = length;
58 } else {
59 rval.code = RC_FAIL;
60 rval.consumed = 0;
61 return rval;
62 }
63
64 memcpy(st->buf, buf_ptr, length);
65 st->buf[length] = '\0'; /* Just in case */
66
67 rval.code = RC_OK;
68 rval.consumed += length;
69
70 ASN_DEBUG("Took %ld/%ld bytes to encode %s",
71 (long)rval.consumed,
72 (long)length, td->name);
73
74 return rval;
75}
76
77/*
78 * Encode an always-primitive type using DER.
79 */
80asn_enc_rval_t
81der_encode_primitive(asn1_TYPE_descriptor_t *td, void *sptr,
82 int tag_mode, ber_tlv_tag_t tag,
83 asn_app_consume_bytes_f *cb, void *app_key) {
84 asn_enc_rval_t erval;
85 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
86
87 ASN_DEBUG("%s %s as a primitive type (tm=%d)",
88 cb?"Encoding":"Estimating", td->name, tag_mode);
89
90 erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag,
91 cb, app_key);
92 ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded);
93 if(erval.encoded == -1) {
94 erval.failed_type = td;
95 erval.structure_ptr = sptr;
96 return erval;
97 }
98
99 if(cb && st->buf) {
100 if(cb(st->buf, st->size, app_key) < 0) {
101 erval.encoded = -1;
102 erval.failed_type = td;
103 erval.structure_ptr = sptr;
104 return erval;
105 }
106 } else {
107 assert(st->buf || st->size == 0);
108 }
109
110 erval.encoded += st->size;
111
112 return erval;
113}
114
115void
116ASN__PRIMITIVE_TYPE_free(asn1_TYPE_descriptor_t *td, void *sptr,
117 int contents_only) {
118 ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr;
119
120 if(!td || !sptr)
121 return;
122
123 ASN_DEBUG("Freeing %s as a primitive type", td->name);
124
125 if(st->buf)
126 FREEMEM(st->buf);
127
128 if(!contents_only)
129 FREEMEM(st);
130}
131