2 * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>.
4 * Redistribution and modifications are permitted subject to BSD license.
6 #include <asn_internal.h>
7 #include <OCTET_STRING.h>
8 #include <BIT_STRING.h> /* for .bits_unused member */
11 #define RETURN(_code) do {\
12 asn_dec_rval_t tmprval;\
13 tmprval.code = _code;\
14 tmprval.consumed = consumed_myself;\
18 static asn_per_constraints_t asn_DEF_OCTET_STRING_constraints = {
19 { APC_CONSTRAINED, 8, 8, 0, 255 },
20 { APC_SEMI_CONSTRAINED, -1, -1, 0, 0 },
25 OCTET_STRING_decode_uper(const asn_codec_ctx_t *opt_codec_ctx,
26 const asn_TYPE_descriptor_t *td,
27 const asn_per_constraints_t *constraints, void **sptr,
29 const asn_OCTET_STRING_specifics_t *specs = td->specifics
30 ? (const asn_OCTET_STRING_specifics_t *)td->specifics
31 : &asn_SPC_OCTET_STRING_specs;
32 const asn_per_constraints_t *pc =
33 constraints ? constraints : td->encoding_constraints.per_constraints;
34 const asn_per_constraint_t *cval;
35 const asn_per_constraint_t *csiz;
36 asn_dec_rval_t rval = { RC_OK, 0 };
37 OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr;
38 ssize_t consumed_myself = 0;
44 } bpc; /* Bytes per character */
45 unsigned int unit_bits;
46 unsigned int canonical_unit_bits;
54 cval = &asn_DEF_OCTET_STRING_constraints.value;
55 csiz = &asn_DEF_OCTET_STRING_constraints.size;
58 switch(specs->subvariant) {
62 ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
66 canonical_unit_bits = unit_bits = 8;
67 if(cval->flags & APC_CONSTRAINED)
68 unit_bits = cval->range_bits;
72 canonical_unit_bits = unit_bits = 16;
73 if(cval->flags & APC_CONSTRAINED)
74 unit_bits = cval->range_bits;
78 canonical_unit_bits = unit_bits = 32;
79 if(cval->flags & APC_CONSTRAINED)
80 unit_bits = cval->range_bits;
86 * Allocate the string.
89 st = (OCTET_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
90 if(!st) RETURN(RC_FAIL);
93 ASN_DEBUG("PER Decoding %s size %ld .. %ld bits %d",
94 csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
95 csiz->lower_bound, csiz->upper_bound, csiz->effective_bits);
97 if(csiz->flags & APC_EXTENSIBLE) {
98 int inext = per_get_few_bits(pd, 1);
99 if(inext < 0) RETURN(RC_WMORE);
101 csiz = &asn_DEF_OCTET_STRING_constraints.size;
102 unit_bits = canonical_unit_bits;
106 if(csiz->effective_bits >= 0) {
109 st->size = csiz->upper_bound * bpc;
111 st->size = (csiz->upper_bound + 7) >> 3;
113 st->buf = (uint8_t *)MALLOC(st->size + 1);
114 if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
117 /* X.691, #16.5: zero-length encoding */
118 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
119 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
120 if(csiz->effective_bits == 0) {
123 ASN_DEBUG("Encoding OCTET STRING size %ld",
125 ret = OCTET_STRING_per_get_characters(pd, st->buf,
131 if(ret > 0) RETURN(RC_FAIL);
133 ASN_DEBUG("Encoding BIT STRING size %ld",
135 ret = per_get_many_bits(pd, st->buf, 0,
136 unit_bits * csiz->upper_bound);
138 if(ret < 0) RETURN(RC_WMORE);
139 consumed_myself += unit_bits * csiz->upper_bound;
140 st->buf[st->size] = 0;
151 /* Get the PER length */
152 raw_len = uper_get_length(pd, csiz->effective_bits, csiz->lower_bound,
154 if(raw_len < 0) RETURN(RC_WMORE);
155 if(raw_len == 0 && st->buf) break;
157 ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
158 (long)csiz->effective_bits, (long)raw_len,
159 repeat ? "repeat" : "once", td->name);
160 len_bytes = raw_len * bpc;
161 p = REALLOC(st->buf, st->size + len_bytes + 1);
162 if(!p) RETURN(RC_FAIL);
163 st->buf = (uint8_t *)p;
165 ret = OCTET_STRING_per_get_characters(pd, &st->buf[st->size], raw_len,
166 bpc, unit_bits, cval->lower_bound,
167 cval->upper_bound, pc);
168 if(ret > 0) RETURN(RC_FAIL);
169 if(ret < 0) RETURN(RC_WMORE);
170 st->size += len_bytes;
172 st->buf[st->size] = 0; /* nul-terminate */
178 OCTET_STRING_encode_uper(const asn_TYPE_descriptor_t *td,
179 const asn_per_constraints_t *constraints,
180 const void *sptr, asn_per_outp_t *po) {
181 const asn_OCTET_STRING_specifics_t *specs = td->specifics
182 ? (const asn_OCTET_STRING_specifics_t *)td->specifics
183 : &asn_SPC_OCTET_STRING_specs;
184 const asn_per_constraints_t *pc = constraints
186 : td->encoding_constraints.per_constraints;
187 const asn_per_constraint_t *cval;
188 const asn_per_constraint_t *csiz;
189 const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr;
190 asn_enc_rval_t er = { 0, 0, 0 };
191 int inext = 0; /* Lies not within extension root */
192 unsigned int unit_bits;
193 unsigned int canonical_unit_bits;
194 size_t size_in_units;
201 } bpc; /* Bytes per character */
204 if(!st || (!st->buf && st->size))
211 cval = &asn_DEF_OCTET_STRING_constraints.value;
212 csiz = &asn_DEF_OCTET_STRING_constraints.size;
214 ct_extensible = csiz->flags & APC_EXTENSIBLE;
216 switch(specs->subvariant) {
222 canonical_unit_bits = unit_bits = 8;
223 if(cval->flags & APC_CONSTRAINED)
224 unit_bits = cval->range_bits;
226 size_in_units = st->size;
229 canonical_unit_bits = unit_bits = 16;
230 if(cval->flags & APC_CONSTRAINED)
231 unit_bits = cval->range_bits;
233 size_in_units = st->size >> 1;
235 ASN_DEBUG("%s string size is not modulo 2", td->name);
240 canonical_unit_bits = unit_bits = 32;
241 if(cval->flags & APC_CONSTRAINED)
242 unit_bits = cval->range_bits;
244 size_in_units = st->size >> 2;
246 ASN_DEBUG("%s string size is not modulo 4", td->name);
252 ASN_DEBUG("Encoding %s into %" ASN_PRI_SIZE " units of %d bits"
253 " (%ld..%ld, effective %d)%s",
254 td->name, size_in_units, unit_bits,
255 csiz->lower_bound, csiz->upper_bound,
256 csiz->effective_bits, ct_extensible ? " EXT" : "");
258 /* Figure out whether size lies within PER visible constraint */
260 if(csiz->effective_bits >= 0) {
261 if((ssize_t)size_in_units < csiz->lower_bound
262 || (ssize_t)size_in_units > csiz->upper_bound) {
264 csiz = &asn_DEF_OCTET_STRING_constraints.size;
265 unit_bits = canonical_unit_bits;
276 /* Declare whether length is [not] within extension root */
277 if(per_put_few_bits(po, inext, 1))
281 if(csiz->effective_bits >= 0 && !inext) {
282 ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes (%ld), length in %d bits", st->size,
283 size_in_units - csiz->lower_bound, csiz->effective_bits);
284 ret = per_put_few_bits(po, size_in_units - csiz->lower_bound,
285 csiz->effective_bits);
286 if(ret) ASN__ENCODE_FAILED;
287 ret = OCTET_STRING_per_put_characters(po, st->buf, size_in_units, bpc,
288 unit_bits, cval->lower_bound,
289 cval->upper_bound, pc);
290 if(ret) ASN__ENCODE_FAILED;
294 ASN_DEBUG("Encoding %" ASN_PRI_SIZE " bytes", st->size);
297 ASN_DEBUG("Encoding %" ASN_PRI_SIZE " in units", size_in_units);
300 ssize_t may_save = uper_put_length(po, size_in_units, &need_eom);
301 if(may_save < 0) ASN__ENCODE_FAILED;
303 ASN_DEBUG("Encoding %" ASN_PRI_SSIZE " of %" ASN_PRI_SIZE "%s", may_save, size_in_units,
304 need_eom ? ",+EOM" : "");
306 ret = OCTET_STRING_per_put_characters(po, buf, may_save, bpc, unit_bits,
308 cval->upper_bound, pc);
309 if(ret) ASN__ENCODE_FAILED;
311 buf += may_save * bpc;
312 size_in_units -= may_save;
313 assert(!(may_save & 0x07) || !size_in_units);
314 if(need_eom && uper_put_length(po, 0, 0))
315 ASN__ENCODE_FAILED; /* End of Message length */
316 } while(size_in_units);