uper_support.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2005-2017 Lev Walkin <vlm@lionet.info>. All rights reserved.
3  * Redistribution and modifications are permitted subject to BSD license.
4  */
8 
9 /*
10  * X.691-201508 #10.9 General rules for encoding a length determinant.
11  * Get the optionally constrained length "n" from the stream.
12  */
13 ssize_t
14 uper_get_length(asn_per_data_t *pd, int ebits, size_t lower_bound,
15  int *repeat) {
16  ssize_t value;
17 
18  *repeat = 0;
19 
20  /* #11.9.4.1 Encoding if constrained (according to effective bits) */
21  if(ebits >= 0 && ebits <= 16) {
22  value = per_get_few_bits(pd, ebits);
23  if(value >= 0) value += lower_bound;
24  return value;
25  }
26 
27  value = per_get_few_bits(pd, 8);
28  if((value & 0x80) == 0) { /* #11.9.3.6 */
29  return (value & 0x7F);
30  } else if((value & 0x40) == 0) { /* #11.9.3.7 */
31  /* bit 8 ... set to 1 and bit 7 ... set to zero */
32  value = ((value & 0x3f) << 8) | per_get_few_bits(pd, 8);
33  return value; /* potential -1 from per_get_few_bits passes through. */
34  } else if(value < 0) {
35  ASN_DEBUG("END of stream reached for PER");
36  return -1;
37  }
38  value &= 0x3f; /* this is "m" from X.691, #11.9.3.8 */
39  if(value < 1 || value > 4) {
40  return -1; /* Prohibited by #11.9.3.8 */
41  }
42  *repeat = 1;
43  return (16384 * value);
44 }
45 
46 /*
47  * Get the normally small length "n".
48  * This procedure used to decode length of extensions bit-maps
49  * for SET and SEQUENCE types.
50  */
51 ssize_t
53  ssize_t length;
54 
55  ASN_DEBUG("Getting normally small length");
56 
57  if(per_get_few_bits(pd, 1) == 0) {
58  length = per_get_few_bits(pd, 6) + 1;
59  if(length <= 0) return -1;
60  ASN_DEBUG("l=%d", (int)length);
61  return length;
62  } else {
63  int repeat;
64  length = uper_get_length(pd, -1, 0, &repeat);
65  if(length >= 0 && !repeat) return length;
66  return -1; /* Error, or do not support >16K extensions */
67  }
68 }
69 
70 /*
71  * Get the normally small non-negative whole number.
72  * X.691, #10.6
73  */
74 ssize_t
76  ssize_t value;
77 
78  value = per_get_few_bits(pd, 7);
79  if(value & 64) { /* implicit (value < 0) */
80  value &= 63;
81  value <<= 2;
82  value |= per_get_few_bits(pd, 2);
83  if(value & 128) /* implicit (value < 0) */
84  return -1;
85  if(value == 0)
86  return 0;
87  if(value >= 3)
88  return -1;
89  value = per_get_few_bits(pd, 8 * value);
90  return value;
91  }
92 
93  return value;
94 }
95 
96 /*
97  * X.691-11/2008, #11.6
98  * Encoding of a normally small non-negative whole number
99  */
100 int
102  int bytes;
103 
104  if(n <= 63) {
105  if(n < 0) return -1;
106  return per_put_few_bits(po, n, 7);
107  }
108  if(n < 256)
109  bytes = 1;
110  else if(n < 65536)
111  bytes = 2;
112  else if(n < 256 * 65536)
113  bytes = 3;
114  else
115  return -1; /* This is not a "normally small" value */
116  if(per_put_few_bits(po, bytes, 8))
117  return -1;
118 
119  return per_put_few_bits(po, n, 8 * bytes);
120 }
121 
122 
123 /* X.691-2008/11, #11.5.6 -> #11.3 */
124 int uper_get_constrained_whole_number(asn_per_data_t *pd, uintmax_t *out_value, int nbits) {
125  uintmax_t lhalf; /* Lower half of the number*/
126  intmax_t half;
127 
128  if(nbits <= 31) {
129  half = per_get_few_bits(pd, nbits);
130  if(half < 0) return -1;
131  *out_value = half;
132  return 0;
133  }
134 
135  if((size_t)nbits > 8 * sizeof(*out_value))
136  return -1; /* RANGE */
137 
138  half = per_get_few_bits(pd, 31);
139  if(half < 0) return -1;
140 
141  if(uper_get_constrained_whole_number(pd, &lhalf, nbits - 31))
142  return -1;
143 
144  *out_value = ((uintmax_t)half << (nbits - 31)) | lhalf;
145  return 0;
146 }
147 
148 
149 /* X.691-2008/11, #11.5.6 -> #11.3 */
150 int
152  int nbits) {
153  if(nbits <= 31) {
154  return per_put_few_bits(po, v, nbits);
155  } else {
156  /* Put higher portion first, followed by lower 31-bit */
157  if(uper_put_constrained_whole_number_u(po, v >> 31, nbits - 31))
158  return -1;
159  return per_put_few_bits(po, v, 31);
160  }
161 }
162 
163 /*
164  * X.691 (08/2015) #11.9 "General rules for encoding a length determinant"
165  * Put the length "n" (or part of it) into the stream.
166  */
167 ssize_t
168 uper_put_length(asn_per_outp_t *po, size_t length, int *need_eom) {
169  int dummy = 0;
170  if(!need_eom) need_eom = &dummy;
171 
172  if(length <= 127) { /* #11.9.3.6 */
173  *need_eom = 0;
174  return per_put_few_bits(po, length, 8)
175  ? -1 : (ssize_t)length;
176  } else if(length < 16384) { /* #10.9.3.7 */
177  *need_eom = 0;
178  return per_put_few_bits(po, length|0x8000, 16)
179  ? -1 : (ssize_t)length;
180  }
181 
182  *need_eom = 0 == (length & 16383);
183  length >>= 14;
184  if(length > 4) {
185  *need_eom = 0;
186  length = 4;
187  }
188 
189  return per_put_few_bits(po, 0xC0 | length, 8)
190  ? -1 : (ssize_t)(length << 14);
191 
192 }
193 
194 
195 /*
196  * Put the normally small length "n" into the stream.
197  * This procedure used to encode length of extensions bit-maps
198  * for SET and SEQUENCE types.
199  */
200 int
201 uper_put_nslength(asn_per_outp_t *po, size_t length) {
202  if(length <= 64) {
203  /* #11.9.3.4 */
204  if(length == 0) return -1;
205  return per_put_few_bits(po, length - 1, 7) ? -1 : 0;
206  } else {
207  int need_eom = 0;
208  if(uper_put_length(po, length, &need_eom) != (ssize_t)length
209  || need_eom) {
210  /* This might happen in case of >16K extensions */
211  return -1;
212  }
213  }
214 
215  return 0;
216 }
217 
218 static int
219 per__imax_range(intmax_t lb, intmax_t ub, uintmax_t *range_r) {
220  uintmax_t bounds_range;
221  if((ub < 0) == (lb < 0)) {
222  bounds_range = ub - lb;
223  } else if(lb < 0) {
224  assert(ub >= 0);
225  bounds_range = 1 + ((uintmax_t)ub + (uintmax_t)-(lb + 1));
226  } else {
227  assert(!"Unreachable");
228  return -1;
229  }
230  *range_r = bounds_range;
231  return 0;
232 }
233 
234 int
235 per_imax_range_rebase(intmax_t v, intmax_t lb, intmax_t ub, uintmax_t *output) {
236  uintmax_t range;
237 
238  assert(lb <= ub);
239 
240  if(v < lb || v > ub || per__imax_range(lb, ub, &range) < 0) {
241  /* Range error. */
242  return -1;
243  }
244 
245  /*
246  * Fundamentally what we're doing is returning (v-lb).
247  * However, this triggers undefined behavior when the word width
248  * of signed (v) is the same as the size of unsigned (*output).
249  * In practice, it triggers the UndefinedSanitizer. Therefore we shall
250  * compute the ranges accurately to avoid C's undefined behavior.
251  */
252  if((v < 0) == (lb < 0)) {
253  *output = v-lb;
254  return 0;
255  } else if(v < 0) {
256  uintmax_t rebased = 1 + (uintmax_t)-(v+1) + (uintmax_t)lb;
257  assert(rebased <= range); /* By construction */
258  *output = rebased;
259  return 0;
260  } else if(lb < 0) {
261  uintmax_t rebased = 1 + (uintmax_t)-(lb+1) + (uintmax_t)v;
262  assert(rebased <= range); /* By construction */
263  *output = rebased;
264  return 0;
265  } else {
266  assert(!"Unreachable");
267  return -1;
268  }
269 }
270 
271 int
272 per_long_range_rebase(long v, intmax_t lb, intmax_t ub, unsigned long *output) {
273  uintmax_t tmp = *output;
274  int rc = per_imax_range_rebase((intmax_t)v, lb, ub, &tmp);
275  *output = tmp;
276  return rc;
277 }
278 
279 int
280 per_imax_range_unrebase(uintmax_t inp, intmax_t lb, intmax_t ub, intmax_t *outp) {
281  uintmax_t range;
282 
283  if(per__imax_range(lb, ub, &range) != 0) {
284  return -1;
285  }
286 
287  if(inp > range) {
288  /*
289  * We can encode something in the given number of bits that technically
290  * exceeds the range. This is an avenue for security errors,
291  * so we don't allow that.
292  */
293  return -1;
294  }
295 
296  if(inp <= INTMAX_MAX) {
297  *outp = (intmax_t)inp + lb;
298  } else {
299  *outp = (lb + INTMAX_MAX + 1) + (intmax_t)((inp - INTMAX_MAX) - 1);
300  }
301 
302  return 0;
303 }
304 
305 int
306 per_long_range_unrebase(unsigned long inp, intmax_t lb, intmax_t ub, long *outp) {
307  intmax_t tmp = *outp;
308  int rc = per_imax_range_unrebase((uintmax_t)inp, lb, ub, &tmp);
309  *outp = tmp;
310  return rc;
311 }
asn_bit_outp_s
Definition: asn_bit_data.h:56
uper_put_nsnnwn
int uper_put_nsnnwn(asn_per_outp_t *po, int n)
Definition: uper_support.c:101
uper_put_length
ssize_t uper_put_length(asn_per_outp_t *po, size_t length, int *need_eom)
Definition: uper_support.c:168
per_long_range_unrebase
int per_long_range_unrebase(unsigned long inp, intmax_t lb, intmax_t ub, long *outp)
Definition: uper_support.c:306
per_imax_range_rebase
int per_imax_range_rebase(intmax_t v, intmax_t lb, intmax_t ub, uintmax_t *output)
Definition: uper_support.c:235
per_get_few_bits
#define per_get_few_bits(data, bits)
Definition: per_support.h:39
uper_support.h
uper_get_nslength
ssize_t uper_get_nslength(asn_per_data_t *pd)
Definition: uper_support.c:52
uper_put_nslength
int uper_put_nslength(asn_per_outp_t *po, size_t length)
Definition: uper_support.c:201
uper_put_constrained_whole_number_u
int uper_put_constrained_whole_number_u(asn_per_outp_t *po, uintmax_t v, int nbits)
Definition: uper_support.c:151
per_long_range_rebase
int per_long_range_rebase(long v, intmax_t lb, intmax_t ub, unsigned long *output)
Definition: uper_support.c:272
asn_bit_data_s
Definition: asn_bit_data.h:17
per__imax_range
static int per__imax_range(intmax_t lb, intmax_t ub, uintmax_t *range_r)
Definition: uper_support.c:219
asn_system.h
uper_get_constrained_whole_number
int uper_get_constrained_whole_number(asn_per_data_t *pd, uintmax_t *out_value, int nbits)
Definition: uper_support.c:124
asn_internal.h
uper_get_nsnnwn
ssize_t uper_get_nsnnwn(asn_per_data_t *pd)
Definition: uper_support.c:75
per_imax_range_unrebase
int per_imax_range_unrebase(uintmax_t inp, intmax_t lb, intmax_t ub, intmax_t *outp)
Definition: uper_support.c:280
uper_get_length
ssize_t uper_get_length(asn_per_data_t *pd, int ebits, size_t lower_bound, int *repeat)
Definition: uper_support.c:14
per_put_few_bits
#define per_put_few_bits(out, bits, obits)
Definition: per_support.h:46


etsi_its_cpm_ts_coding
Author(s): Jean-Pierre Busch , Guido Küppers , Lennart Reiher
autogenerated on Sun May 18 2025 02:22:38