/src/open5gs/lib/asn1c/common/OCTET_STRING_aper.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2017 Lev Walkin <vlm@lionet.info>. |
3 | | * All rights reserved. |
4 | | * Redistribution and modifications are permitted subject to BSD license. |
5 | | */ |
6 | | #include <asn_internal.h> |
7 | | #include <OCTET_STRING.h> |
8 | | #include <BIT_STRING.h> /* for .bits_unused member */ |
9 | | |
10 | | #undef RETURN |
11 | 10.4k | #define RETURN(_code) do {\ |
12 | 10.4k | asn_dec_rval_t tmprval;\ |
13 | 10.4k | tmprval.code = _code;\ |
14 | 10.4k | tmprval.consumed = consumed_myself;\ |
15 | 10.4k | return tmprval;\ |
16 | 10.4k | } while(0) |
17 | | |
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 }, |
21 | | 0, 0 |
22 | | }; |
23 | | |
24 | | asn_dec_rval_t |
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 | 14.0k | void **sptr, asn_per_data_t *pd) { |
29 | | |
30 | 14.0k | const asn_OCTET_STRING_specifics_t *specs = td->specifics |
31 | 14.0k | ? (const asn_OCTET_STRING_specifics_t *)td->specifics |
32 | 14.0k | : &asn_SPC_OCTET_STRING_specs; |
33 | 14.0k | const asn_per_constraints_t *pc = constraints |
34 | 14.0k | ? constraints |
35 | 14.0k | : td->encoding_constraints.per_constraints; |
36 | 14.0k | const asn_per_constraint_t *cval; |
37 | 14.0k | const asn_per_constraint_t *csiz; |
38 | 14.0k | asn_dec_rval_t rval = { RC_OK, 0 }; |
39 | 14.0k | BIT_STRING_t *st = (BIT_STRING_t *)*sptr; |
40 | 14.0k | ssize_t consumed_myself = 0; |
41 | 14.0k | int repeat; |
42 | 14.0k | enum { |
43 | 14.0k | OS__BPC_BIT = 0, |
44 | 14.0k | OS__BPC_CHAR = 1, |
45 | 14.0k | OS__BPC_U16 = 2, |
46 | 14.0k | OS__BPC_U32 = 4 |
47 | 14.0k | } bpc; /* Bytes per character */ |
48 | 14.0k | unsigned int unit_bits; |
49 | 14.0k | unsigned int canonical_unit_bits; |
50 | | |
51 | 14.0k | (void)opt_codec_ctx; |
52 | | |
53 | 14.0k | if(pc) { |
54 | 12.2k | cval = &pc->value; |
55 | 12.2k | csiz = &pc->size; |
56 | 12.2k | } else { |
57 | 1.76k | cval = &asn_DEF_OCTET_STRING_constraints.value; |
58 | 1.76k | csiz = &asn_DEF_OCTET_STRING_constraints.size; |
59 | 1.76k | } |
60 | | |
61 | 14.0k | switch(specs->subvariant) { |
62 | 0 | case ASN_OSUBV_ANY: |
63 | 9.43k | case ASN_OSUBV_STR: |
64 | 9.43k | canonical_unit_bits = unit_bits = 8; |
65 | 9.43k | if(cval->flags & APC_CONSTRAINED) { |
66 | | /* follow power of 2 rule */ |
67 | 1.83k | if (cval->range_bits <= 2) { |
68 | 0 | unit_bits = 2; |
69 | 1.83k | } else { |
70 | 1.83k | if (cval->range_bits <= 4) { |
71 | 0 | unit_bits = 4; |
72 | | /* otherwise, unit_bits = 8; */ |
73 | 0 | } |
74 | 1.83k | } |
75 | | /* unit_bits = cval->range_bits; */ |
76 | 1.83k | ASN_DEBUG("APER decoding ASN_OSUBV_STR range_bits = %d unit_bits = %d\n", |
77 | 1.83k | cval->range_bits, unit_bits); |
78 | 1.83k | } |
79 | 9.43k | bpc = OS__BPC_CHAR; |
80 | 9.43k | break; |
81 | 0 | case ASN_OSUBV_U16: |
82 | 0 | canonical_unit_bits = unit_bits = 16; |
83 | 0 | if(cval->flags & APC_CONSTRAINED) { |
84 | 0 | unit_bits = cval->range_bits; |
85 | 0 | ASN_DEBUG("APER decoding ASN_OSUBV_U16 range_bits = %d\n", cval->range_bits); |
86 | 0 | } |
87 | 0 | bpc = OS__BPC_U16; |
88 | 0 | break; |
89 | 0 | case ASN_OSUBV_U32: |
90 | 0 | canonical_unit_bits = unit_bits = 32; |
91 | 0 | if(cval->flags & APC_CONSTRAINED) { |
92 | 0 | unit_bits = cval->range_bits; |
93 | 0 | ASN_DEBUG("APER decoding ASN_OSUBV_U32 range_bits = %d\n", cval->range_bits); |
94 | 0 | } |
95 | 0 | bpc = OS__BPC_U32; |
96 | 0 | break; |
97 | | /* |
98 | | case ASN_OSUBV_ANY: |
99 | | ASN_DEBUG("Unrecognized subvariant %d", specs->subvariant); |
100 | | RETURN(RC_FAIL); |
101 | | */ |
102 | 4.62k | case ASN_OSUBV_BIT: |
103 | 4.62k | default: |
104 | 4.62k | canonical_unit_bits = unit_bits = 1; |
105 | 4.62k | bpc = OS__BPC_BIT; |
106 | 4.62k | break; |
107 | 14.0k | } |
108 | | |
109 | | /* |
110 | | * Allocate the string. |
111 | | */ |
112 | 14.0k | if(!st) { |
113 | 4.95k | st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); |
114 | 4.95k | if(!st) RETURN(RC_FAIL); |
115 | 4.95k | } |
116 | | |
117 | 14.0k | ASN_DEBUG("PER Decoding %s size %lld .. %lld bits %d", |
118 | 14.0k | csiz->flags & APC_EXTENSIBLE ? "extensible" : "non-extensible", |
119 | 14.0k | (long long int)csiz->lower_bound, (long long int)csiz->upper_bound, |
120 | 14.0k | csiz->effective_bits); |
121 | | |
122 | 14.0k | if(csiz->flags & APC_EXTENSIBLE) { |
123 | 1.46k | int inext = per_get_few_bits(pd, 1); |
124 | 1.46k | if(inext < 0) RETURN(RC_WMORE); |
125 | 1.45k | if(inext) { |
126 | 360 | csiz = &asn_DEF_OCTET_STRING_constraints.size; |
127 | 360 | cval = &asn_DEF_OCTET_STRING_constraints.value; |
128 | 360 | unit_bits = canonical_unit_bits; |
129 | 360 | } |
130 | 1.45k | } |
131 | | |
132 | 14.0k | if(csiz->effective_bits >= 0) { |
133 | 11.4k | FREEMEM(st->buf); |
134 | 11.4k | if(bpc) { |
135 | 7.23k | st->size = csiz->upper_bound * bpc; |
136 | 7.23k | } else { |
137 | 4.23k | st->size = (csiz->upper_bound + 7) >> 3; |
138 | 4.23k | } |
139 | 11.4k | st->buf = (uint8_t *)MALLOC(st->size + 1); |
140 | 11.4k | if(!st->buf) { st->size = 0; RETURN(RC_FAIL); } |
141 | 11.4k | } |
142 | | |
143 | | /* X.691, #16.5: zero-length encoding */ |
144 | | /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ |
145 | | /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ |
146 | 14.0k | if(csiz->effective_bits == 0) { |
147 | 10.2k | int ret; |
148 | | /* X.691 #16 NOTE 1 for fixed length (<= 16 bits) strings */ |
149 | 10.2k | if (st->size > 2 || csiz->range_bits != 0) { |
150 | 5.02k | if (aper_get_align(pd) < 0) |
151 | 0 | RETURN(RC_FAIL); |
152 | 5.02k | } |
153 | 10.2k | if(bpc) { |
154 | 7.14k | ASN_DEBUG("Decoding OCTET STRING size %lld", |
155 | 7.14k | (long long int)csiz->upper_bound); |
156 | 7.14k | ret = OCTET_STRING_per_get_characters(pd, st->buf, |
157 | 7.14k | csiz->upper_bound, |
158 | 7.14k | bpc, unit_bits, |
159 | 7.14k | cval->lower_bound, |
160 | 7.14k | cval->upper_bound, |
161 | 7.14k | pc); |
162 | 7.14k | if(ret > 0) RETURN(RC_FAIL); |
163 | 7.14k | } else { |
164 | 3.07k | ASN_DEBUG("Decoding BIT STRING size %lld", |
165 | 3.07k | (long long int)csiz->upper_bound); |
166 | 3.07k | ret = per_get_many_bits(pd, st->buf, 0, |
167 | 3.07k | unit_bits * csiz->upper_bound); |
168 | 3.07k | } |
169 | 10.2k | if(ret < 0) RETURN(RC_WMORE); |
170 | 10.0k | consumed_myself += unit_bits * csiz->upper_bound; |
171 | 10.0k | st->buf[st->size] = 0; |
172 | 10.0k | if(bpc == 0) { |
173 | 3.03k | int ubs = (csiz->upper_bound & 0x7); |
174 | 3.03k | st->bits_unused = ubs ? 8 - ubs : 0; |
175 | 3.03k | } |
176 | 10.0k | RETURN(RC_OK); |
177 | 10.0k | } |
178 | | |
179 | 3.82k | st->size = 0; |
180 | 3.82k | do { |
181 | 3.82k | ssize_t raw_len; |
182 | 3.82k | ssize_t len_bytes; |
183 | 3.82k | ssize_t len_bits; |
184 | 3.82k | void *p; |
185 | 3.82k | int ret; |
186 | | |
187 | 3.82k | repeat = 0; |
188 | | /* Get the PER length */ |
189 | 3.82k | if (csiz->upper_bound - csiz->lower_bound == 0) |
190 | | /* Indefinite length case */ |
191 | 2.55k | raw_len = aper_get_length(pd, -1, -1, csiz->effective_bits, &repeat); |
192 | 1.26k | else |
193 | 1.26k | raw_len = aper_get_length(pd, csiz->lower_bound, csiz->upper_bound, |
194 | 1.26k | csiz->effective_bits, &repeat); |
195 | 3.82k | if(raw_len < 0) RETURN(RC_WMORE); |
196 | | |
197 | 3.71k | ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", |
198 | 3.71k | (long)csiz->effective_bits, (long)raw_len, |
199 | 3.71k | repeat ? "repeat" : "once", td->name); |
200 | | |
201 | | /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings */ |
202 | 3.71k | if ((raw_len > 2) || (csiz->upper_bound > 2) || (csiz->range_bits != 0)) |
203 | 3.71k | { |
204 | 3.71k | if (aper_get_align(pd) < 0) |
205 | 0 | RETURN(RC_FAIL); |
206 | 3.71k | } |
207 | | |
208 | 3.71k | if(bpc) { |
209 | 2.20k | len_bytes = raw_len * bpc; |
210 | 2.20k | len_bits = len_bytes * unit_bits; |
211 | 2.20k | } else { |
212 | 1.51k | len_bits = raw_len; |
213 | 1.51k | len_bytes = (len_bits + 7) >> 3; |
214 | 1.51k | if(len_bits & 0x7) |
215 | 1.27k | st->bits_unused = 8 - (len_bits & 0x7); |
216 | | /* len_bits be multiple of 16K if repeat is set */ |
217 | 1.51k | } |
218 | 3.71k | p = REALLOC(st->buf, st->size + len_bytes + 1); |
219 | 3.71k | if(!p) RETURN(RC_FAIL); |
220 | 3.71k | st->buf = (uint8_t *)p; |
221 | | |
222 | 3.71k | if(bpc) { |
223 | 2.20k | ret = OCTET_STRING_per_get_characters(pd, |
224 | 2.20k | &st->buf[st->size], |
225 | 2.20k | raw_len, bpc, |
226 | 2.20k | unit_bits, |
227 | 2.20k | cval->lower_bound, |
228 | 2.20k | cval->upper_bound, |
229 | 2.20k | pc); |
230 | 2.20k | if(ret > 0) RETURN(RC_FAIL); |
231 | 2.20k | } else { |
232 | 1.51k | ret = per_get_many_bits(pd, &st->buf[st->size], |
233 | 1.51k | 0, len_bits); |
234 | 1.51k | } |
235 | 3.71k | if(ret < 0) RETURN(RC_WMORE); |
236 | 3.60k | st->size += len_bytes; |
237 | 3.60k | } while(repeat); |
238 | 3.60k | st->buf[st->size] = 0; /* nul-terminate */ |
239 | | |
240 | 3.60k | return rval; |
241 | 3.82k | } |
242 | | |
243 | | asn_enc_rval_t |
244 | | OCTET_STRING_encode_aper(const asn_TYPE_descriptor_t *td, |
245 | | const asn_per_constraints_t *constraints, |
246 | 0 | const void *sptr, asn_per_outp_t *po) { |
247 | |
|
248 | 0 | const asn_OCTET_STRING_specifics_t *specs = td->specifics |
249 | 0 | ? (const asn_OCTET_STRING_specifics_t *)td->specifics |
250 | 0 | : &asn_SPC_OCTET_STRING_specs; |
251 | 0 | const asn_per_constraints_t *pc = constraints |
252 | 0 | ? constraints |
253 | 0 | : td->encoding_constraints.per_constraints; |
254 | 0 | const asn_per_constraint_t *cval; |
255 | 0 | const asn_per_constraint_t *csiz; |
256 | 0 | const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; |
257 | 0 | asn_enc_rval_t er = { 0, 0, 0 }; |
258 | 0 | int inext = 0; /* Lies not within extension root */ |
259 | 0 | unsigned int unit_bits; |
260 | 0 | unsigned int canonical_unit_bits; |
261 | 0 | unsigned int sizeinunits; |
262 | 0 | const uint8_t *buf; |
263 | 0 | int ret; |
264 | 0 | enum { |
265 | 0 | OS__BPC_BIT = 0, |
266 | 0 | OS__BPC_CHAR = 1, |
267 | 0 | OS__BPC_U16 = 2, |
268 | 0 | OS__BPC_U32 = 4 |
269 | 0 | } bpc; /* Bytes per character */ |
270 | 0 | int ct_extensible; |
271 | |
|
272 | 0 | if(!st || (!st->buf && st->size)) |
273 | 0 | ASN__ENCODE_FAILED; |
274 | | |
275 | 0 | if(pc) { |
276 | 0 | cval = &pc->value; |
277 | 0 | csiz = &pc->size; |
278 | 0 | } else { |
279 | 0 | cval = &asn_DEF_OCTET_STRING_constraints.value; |
280 | 0 | csiz = &asn_DEF_OCTET_STRING_constraints.size; |
281 | 0 | } |
282 | 0 | ct_extensible = csiz->flags & APC_EXTENSIBLE; |
283 | |
|
284 | 0 | switch(specs->subvariant) { |
285 | 0 | case ASN_OSUBV_ANY: |
286 | 0 | case ASN_OSUBV_STR: |
287 | 0 | canonical_unit_bits = unit_bits = 8; |
288 | 0 | if(cval->flags & APC_CONSTRAINED) { |
289 | | /* follow power of 2 rule */ |
290 | 0 | if (cval->range_bits <= 2) { |
291 | 0 | unit_bits = 2; |
292 | 0 | } else { |
293 | 0 | if (cval->range_bits <= 4) |
294 | 0 | unit_bits = 4; |
295 | | /* otherwise, unit_bits = 8; */ |
296 | 0 | } |
297 | | /* unit_bits = cval->range_bits; */ |
298 | 0 | ASN_DEBUG("APER encoding ASN_OSUBV_STR range_bits = %d unit_bits = %d\n", |
299 | 0 | cval->range_bits, unit_bits); |
300 | 0 | } |
301 | 0 | bpc = OS__BPC_CHAR; |
302 | 0 | sizeinunits = st->size; |
303 | 0 | break; |
304 | 0 | case ASN_OSUBV_U16: |
305 | 0 | canonical_unit_bits = unit_bits = 16; |
306 | 0 | if(cval->flags & APC_CONSTRAINED) { |
307 | 0 | unit_bits = cval->range_bits; |
308 | 0 | ASN_DEBUG("APER encoding ASN_OSUBV_U16 range_bits = %d\n", cval->range_bits); |
309 | 0 | } |
310 | 0 | bpc = OS__BPC_U16; |
311 | 0 | sizeinunits = st->size / 2; |
312 | 0 | break; |
313 | 0 | case ASN_OSUBV_U32: |
314 | 0 | canonical_unit_bits = unit_bits = 32; |
315 | 0 | if(cval->flags & APC_CONSTRAINED) { |
316 | 0 | unit_bits = cval->range_bits; |
317 | 0 | ASN_DEBUG("APER encoding ASN_OSUBV_U32 range_bits = %d\n", cval->range_bits); |
318 | 0 | } |
319 | 0 | bpc = OS__BPC_U32; |
320 | 0 | sizeinunits = st->size / 4; |
321 | 0 | break; |
322 | | /* |
323 | | case ASN_OSUBV_ANY: |
324 | | ASN__ENCODE_FAILED; |
325 | | */ |
326 | 0 | case ASN_OSUBV_BIT: |
327 | 0 | default: |
328 | 0 | canonical_unit_bits = unit_bits = 1; |
329 | 0 | bpc = OS__BPC_BIT; |
330 | 0 | sizeinunits = st->size * 8 - (st->bits_unused & 0x07); |
331 | 0 | ASN_DEBUG("BIT STRING of %d bytes", sizeinunits); |
332 | 0 | break; |
333 | 0 | } |
334 | | |
335 | 0 | ASN_DEBUG("Encoding %s into %d units of %d bits" |
336 | 0 | " (%lld..%lld, effective %d)%s", |
337 | 0 | td->name, sizeinunits, unit_bits, |
338 | 0 | (long long int)csiz->lower_bound, |
339 | 0 | (long long int)csiz->upper_bound, |
340 | 0 | csiz->effective_bits, ct_extensible ? " EXT" : ""); |
341 | | |
342 | | /* Figure out wheter size lies within PER visible constraint */ |
343 | |
|
344 | 0 | if(csiz->effective_bits >= 0) { |
345 | 0 | if((int)sizeinunits < csiz->lower_bound |
346 | 0 | || (int)sizeinunits > csiz->upper_bound) { |
347 | 0 | if(ct_extensible) { |
348 | 0 | cval = &asn_DEF_OCTET_STRING_constraints.value; |
349 | 0 | csiz = &asn_DEF_OCTET_STRING_constraints.size; |
350 | 0 | unit_bits = canonical_unit_bits; |
351 | 0 | inext = 1; |
352 | 0 | } else |
353 | 0 | ASN__ENCODE_FAILED; |
354 | 0 | } |
355 | 0 | } else { |
356 | 0 | inext = 0; |
357 | 0 | } |
358 | | |
359 | 0 | if(ct_extensible) { |
360 | | /* Declare whether length is [not] within extension root */ |
361 | 0 | if(per_put_few_bits(po, inext, 1)) |
362 | 0 | ASN__ENCODE_FAILED; |
363 | 0 | } |
364 | | |
365 | | /* X.691, #16.5: zero-length encoding */ |
366 | | /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ |
367 | | /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ |
368 | 0 | if(csiz->effective_bits >= 0) { |
369 | 0 | ASN_DEBUG("Encoding %zu bytes (%lld), length in %d bits", |
370 | 0 | st->size, (long long int)(sizeinunits - csiz->lower_bound), |
371 | 0 | csiz->effective_bits); |
372 | 0 | if (csiz->effective_bits > 0) { |
373 | 0 | ret = aper_put_length(po, csiz->lower_bound, csiz->upper_bound, |
374 | 0 | sizeinunits - csiz->lower_bound, NULL); |
375 | 0 | if(ret < 0) ASN__ENCODE_FAILED; |
376 | 0 | } |
377 | 0 | if (csiz->effective_bits > 0 || (st->size > 2) |
378 | 0 | || (csiz->upper_bound > (2 * 8 / unit_bits)) |
379 | 0 | || (csiz->range_bits != 0)) |
380 | 0 | { /* X.691 #16 NOTE 1 for fixed length (<=16 bits) strings*/ |
381 | 0 | if (aper_put_align(po) < 0) |
382 | 0 | ASN__ENCODE_FAILED; |
383 | 0 | } |
384 | 0 | if(bpc) { |
385 | 0 | ret = OCTET_STRING_per_put_characters(po, st->buf, |
386 | 0 | sizeinunits, |
387 | 0 | bpc, unit_bits, |
388 | 0 | cval->lower_bound, |
389 | 0 | cval->upper_bound, |
390 | 0 | pc); |
391 | 0 | } else { |
392 | 0 | ret = per_put_many_bits(po, st->buf, |
393 | 0 | sizeinunits * unit_bits); |
394 | 0 | } |
395 | 0 | if(ret) ASN__ENCODE_FAILED; |
396 | 0 | ASN__ENCODED_OK(er); |
397 | 0 | } |
398 | | |
399 | 0 | ASN_DEBUG("Encoding %zu bytes", st->size); |
400 | |
|
401 | 0 | if(sizeinunits == 0) { |
402 | 0 | if(aper_put_length(po, -1, -1, 0, NULL) < 0) |
403 | 0 | ASN__ENCODE_FAILED; |
404 | 0 | ASN__ENCODED_OK(er); |
405 | 0 | } |
406 | | |
407 | 0 | buf = st->buf; |
408 | 0 | while(sizeinunits) { |
409 | 0 | int need_eom = 0; |
410 | 0 | ssize_t maySave = aper_put_length(po, -1, -1, sizeinunits, &need_eom); |
411 | |
|
412 | 0 | if(maySave < 0) ASN__ENCODE_FAILED; |
413 | | |
414 | 0 | ASN_DEBUG("Encoding %ld of %ld", |
415 | 0 | (long)maySave, (long)sizeinunits); |
416 | |
|
417 | 0 | if(bpc) { |
418 | 0 | ret = OCTET_STRING_per_put_characters(po, buf, maySave, |
419 | 0 | bpc, unit_bits, |
420 | 0 | cval->lower_bound, |
421 | 0 | cval->upper_bound, |
422 | 0 | pc); |
423 | 0 | } else { |
424 | 0 | ret = per_put_many_bits(po, buf, maySave * unit_bits); |
425 | 0 | } |
426 | 0 | if(ret) ASN__ENCODE_FAILED; |
427 | | |
428 | 0 | if(bpc) |
429 | 0 | buf += maySave * bpc; |
430 | 0 | else |
431 | 0 | buf += maySave >> 3; |
432 | 0 | sizeinunits -= maySave; |
433 | 0 | assert(!(maySave & 0x07) || !sizeinunits); |
434 | 0 | if(need_eom && (aper_put_length(po, -1, -1, 0, NULL) < 0)) |
435 | 0 | ASN__ENCODE_FAILED; /* End of Message length */ |
436 | 0 | } |
437 | | |
438 | 0 | ASN__ENCODED_OK(er); |
439 | 0 | } |