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_aper(const asn_codec_ctx_t *opt_codec_ctx,
26 const asn_TYPE_descriptor_t *td,
27 const asn_per_constraints_t *constraints,
28 void **sptr, asn_per_data_t *pd) {
30 const asn_OCTET_STRING_specifics_t *specs = td->specifics
31 ? (const asn_OCTET_STRING_specifics_t *)td->specifics
32 : &asn_SPC_OCTET_STRING_specs;
33 const asn_per_constraints_t *pc = constraints
35 : td->encoding_constraints.per_constraints;
36 const asn_per_constraint_t *cval;
37 const asn_per_constraint_t *csiz;
38 asn_dec_rval_t rval = { RC_OK, 0 };
39 BIT_STRING_t *st = (BIT_STRING_t *)*sptr;
40 ssize_t consumed_myself = 0;
47 } bpc; /* Bytes per character */
48 unsigned int unit_bits;
49 unsigned int canonical_unit_bits;
57 cval = &asn_DEF_OCTET_STRING_constraints.value;
58 csiz = &asn_DEF_OCTET_STRING_constraints.size;
61 switch(specs->subvariant) {
65 ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant);
69 canonical_unit_bits = unit_bits = 1;
74 canonical_unit_bits = unit_bits = 8;
76 if(cval->flags & APC_CONSTRAINED)
77 unit_bits = cval->range_bits;
82 canonical_unit_bits = unit_bits = 16;
83 if(cval->flags & APC_CONSTRAINED)
84 unit_bits = cval->range_bits;
88 canonical_unit_bits = unit_bits = 32;
89 if(cval->flags & APC_CONSTRAINED)
90 unit_bits = cval->range_bits;
96 * Allocate the string.
99 st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size));
100 if(!st) RETURN(RC_FAIL);
103 ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d",
104 csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible",
105 (long long int)csiz->lower_bound, (long long int)csiz->upper_bound,
106 csiz->effective_bits);
108 if(csiz->flags & APC_EXTENSIBLE) {
109 int inext = per_get_few_bits(pd, 1);
110 if(inext < 0) RETURN(RC_WMORE);
112 csiz = &asn_DEF_OCTET_STRING_constraints.size;
113 cval = &asn_DEF_OCTET_STRING_constraints.value;
114 unit_bits = canonical_unit_bits;
118 if(csiz->effective_bits >= 0) {
121 st->size = csiz->upper_bound * bpc;
123 st->size = (csiz->upper_bound + 7) >> 3;
125 st->buf = (uint8_t *)MALLOC(st->size + 1);
126 if(!st->buf) { st->size = 0; RETURN(RC_FAIL); }
129 /* X.691, #16.5: zero-length encoding */
130 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
131 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
132 if(csiz->effective_bits == 0) {
134 /* X.691 #16 NOTE 1 for fixed length (<= 16 bits) strings */
135 if (st->size > 2 || csiz->range_bits != 0) {
136 if (aper_get_align(pd) < 0)
140 ASN_DEBUG("Decoding OCTET STRING size %lld",
141 (long long int)csiz->upper_bound);
142 ret = OCTET_STRING_per_get_characters(pd, st->buf,
148 if(ret > 0) RETURN(RC_FAIL);
150 ASN_DEBUG("Decoding BIT STRING size %lld",
151 (long long int)csiz->upper_bound);
152 ret = per_get_many_bits(pd, st->buf, 0,
153 unit_bits * csiz->upper_bound);
155 if(ret < 0) RETURN(RC_WMORE);
156 consumed_myself += unit_bits * csiz->upper_bound;
157 st->buf[st->size] = 0;
159 int ubs = (csiz->upper_bound & 0x7);
160 st->bits_unused = ubs ? 8 - ubs : 0;
174 /* Get the PER length */
175 if (csiz->upper_bound - csiz->lower_bound == 0)
176 /* Indefinite length case */
177 raw_len = aper_get_length(pd, -1, -1, csiz->effective_bits, &repeat);
179 raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound,
180 csiz->effective_bits, &repeat);
181 if(raw_len < 0) RETURN(RC_WMORE);
182 raw_len += csiz->lower_bound;
184 ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)",
185 (long)csiz->effective_bits, (long)raw_len,
186 repeat ? "repeat" : "once", td->name);
188 /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings */
189 if ((raw_len > 2) || (csiz->upper_bound > 2) || (csiz->range_bits != 0))
191 if (aper_get_align(pd) < 0)
196 len_bytes = raw_len * bpc;
197 len_bits = len_bytes * unit_bits;
200 len_bytes = (len_bits + 7) >> 3;
202 st->bits_unused = 8 - (len_bits & 0x7);
203 /* len_bits be multiple of 16K if repeat is set */
205 p = REALLOC(st->buf, st->size + len_bytes + 1);
206 if(!p) RETURN(RC_FAIL);
207 st->buf = (uint8_t *)p;
210 ret = OCTET_STRING_per_get_characters(pd,
217 if(ret > 0) RETURN(RC_FAIL);
219 ret = per_get_many_bits(pd, &st->buf[st->size],
222 if(ret < 0) RETURN(RC_WMORE);
223 st->size += len_bytes;
225 st->buf[st->size] = 0; /* nul-terminate */
231 OCTET_STRING_encode_aper(const asn_TYPE_descriptor_t *td,
232 const asn_per_constraints_t *constraints,
233 const void *sptr, asn_per_outp_t *po) {
235 const asn_OCTET_STRING_specifics_t *specs = td->specifics
236 ? (const asn_OCTET_STRING_specifics_t *)td->specifics
237 : &asn_SPC_OCTET_STRING_specs;
238 const asn_per_constraints_t *pc = constraints
240 : td->encoding_constraints.per_constraints;
241 const asn_per_constraint_t *cval;
242 const asn_per_constraint_t *csiz;
243 const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
244 asn_enc_rval_t er = { 0, 0, 0 };
245 int inext = 0; /* Lies not within extension root */
246 unsigned int unit_bits;
247 unsigned int canonical_unit_bits;
248 unsigned int sizeinunits;
256 } bpc; /* Bytes per character */
259 if(!st || (!st->buf && st->size))
266 cval = &asn_DEF_OCTET_STRING_constraints.value;
267 csiz = &asn_DEF_OCTET_STRING_constraints.size;
269 ct_extensible = csiz->flags & APC_EXTENSIBLE;
271 switch(specs->subvariant) {
278 canonical_unit_bits = unit_bits = 1;
280 sizeinunits = st->size * 8 - (st->bits_unused & 0x07);
281 ASN_DEBUG("BIT STRING of %d bytes",
286 canonical_unit_bits = unit_bits = 8;
288 if(cval->flags & APC_CONSTRAINED)
292 sizeinunits = st->size;
295 canonical_unit_bits = unit_bits = 16;
296 if(cval->flags & APC_CONSTRAINED)
297 unit_bits = cval->range_bits;
299 sizeinunits = st->size / 2;
302 canonical_unit_bits = unit_bits = 32;
303 if(cval->flags & APC_CONSTRAINED)
304 unit_bits = cval->range_bits;
306 sizeinunits = st->size / 4;
310 ASN_DEBUG("Encoding %s into %d units of %d bits"
311 " (%lld..%lld, effective %d)%s",
312 td->name, sizeinunits, unit_bits,
313 (long long int)csiz->lower_bound,
314 (long long int)csiz->upper_bound,
315 csiz->effective_bits, ct_extensible ? " EXT" : "");
317 /* Figure out wheter size lies within PER visible constraint */
319 if(csiz->effective_bits >= 0) {
320 if((int)sizeinunits < csiz->lower_bound
321 || (int)sizeinunits > csiz->upper_bound) {
323 cval = &asn_DEF_OCTET_STRING_constraints.value;
324 csiz = &asn_DEF_OCTET_STRING_constraints.size;
325 unit_bits = canonical_unit_bits;
335 /* Declare whether length is [not] within extension root */
336 if(per_put_few_bits(po, inext, 1))
340 /* X.691, #16.5: zero-length encoding */
341 /* X.691, #16.6: short fixed length encoding (up to 2 octets) */
342 /* X.691, #16.7: long fixed length encoding (up to 64K octets) */
343 if(csiz->effective_bits >= 0) {
344 ASN_DEBUG("Encoding %zu bytes (%lld), length in %d bits",
345 st->size, (long long int)(sizeinunits - csiz->lower_bound),
346 csiz->effective_bits);
347 if (csiz->effective_bits > 0) {
348 ret = aper_put_length(po, csiz->lower_bound, csiz->upper_bound,
349 sizeinunits - csiz->lower_bound, NULL);
350 if(ret < 0) ASN__ENCODE_FAILED;
352 if (csiz->effective_bits > 0 || (st->size > 2)
353 || (csiz->upper_bound > (2 * 8 / unit_bits))
354 || (csiz->range_bits != 0))
355 { /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings*/
356 if (aper_put_align(po) < 0)
360 ret = OCTET_STRING_per_put_characters(po, st->buf,
367 ret = per_put_many_bits(po, st->buf,
368 sizeinunits * unit_bits);
370 if(ret) ASN__ENCODE_FAILED;
374 ASN_DEBUG("Encoding %zu bytes", st->size);
376 if(sizeinunits == 0) {
377 if(aper_put_length(po, -1, -1, 0, NULL) < 0)
385 ssize_t maySave = aper_put_length(po, -1, -1, sizeinunits, &need_eom);
387 if(maySave < 0) ASN__ENCODE_FAILED;
389 ASN_DEBUG("Encoding %ld of %ld",
390 (long)maySave, (long)sizeinunits);
393 ret = OCTET_STRING_per_put_characters(po, buf, maySave,
399 ret = per_put_many_bits(po, buf, maySave * unit_bits);
401 if(ret) ASN__ENCODE_FAILED;
404 buf += maySave * bpc;
407 sizeinunits -= maySave;
408 assert(!(maySave & 0x07) || !sizeinunits);
409 if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0))
410 ASN__ENCODE_FAILED; /* End of Message length */