Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/asn1.c
Line
Count
Source
1
/* asn1.c
2
 * Common routines for ASN.1
3
 * 2007  Anders Broman
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <glib.h>
15
16
#include <string.h>
17
#include <stdlib.h>
18
#include <math.h>
19
#include <errno.h>
20
#include <fenv.h>
21
22
#include <epan/packet.h>
23
#include <wsutil/pint.h>
24
#include <wsutil/sign_ext.h>
25
26
#include "asn1.h"
27
28
75.1k
void asn1_ctx_init(asn1_ctx_t *actx, asn1_enc_e encoding, bool aligned, packet_info *pinfo) {
29
75.1k
  memset(actx, '\0', sizeof(*actx));
30
75.1k
  actx->signature = ASN1_CTX_SIGNATURE;
31
75.1k
  actx->encoding = encoding;
32
75.1k
  actx->aligned = aligned;
33
75.1k
  actx->pinfo = pinfo;
34
75.1k
}
35
36
1.74k
bool asn1_ctx_check_signature(asn1_ctx_t *actx) {
37
1.74k
  return actx && (actx->signature == ASN1_CTX_SIGNATURE);
38
1.74k
}
39
40
0
void asn1_ctx_clean_external(asn1_ctx_t *actx) {
41
0
  memset(&actx->external, '\0', sizeof(actx->external));
42
0
  actx->external.hf_index = -1;
43
0
  actx->external.encoding = -1;
44
0
}
45
46
0
void asn1_ctx_clean_epdv(asn1_ctx_t *actx) {
47
0
  memset(&actx->embedded_pdv, '\0', sizeof(actx->embedded_pdv));
48
0
  actx->embedded_pdv.hf_index = -1;
49
0
  actx->embedded_pdv.identification = -1;
50
0
}
51
52
53
/*--- stack/parameters ---*/
54
55
40
void asn1_stack_frame_push(asn1_ctx_t *actx, const char *name) {
56
40
  asn1_stack_frame_t *frame;
57
58
40
  frame = wmem_new0(actx->pinfo->pool, asn1_stack_frame_t);
59
40
  frame->name = name;
60
40
  frame->next = actx->stack;
61
40
  actx->stack = frame;
62
40
}
63
64
23
void asn1_stack_frame_pop(asn1_ctx_t *actx, const char *name) {
65
23
  DISSECTOR_ASSERT(actx->stack);
66
23
  DISSECTOR_ASSERT(!strcmp(actx->stack->name, name));
67
23
  actx->stack = actx->stack->next;
68
23
}
69
70
15
void asn1_stack_frame_check(asn1_ctx_t *actx, const char *name, const asn1_par_def_t *par_def) {
71
15
  const asn1_par_def_t *pd = par_def;
72
15
  asn1_par_t *par;
73
74
15
  DISSECTOR_ASSERT(actx->stack);
75
15
  DISSECTOR_ASSERT(!strcmp(actx->stack->name, name));
76
77
15
  par = actx->stack->par;
78
45
  while (pd->name) {
79
30
    DISSECTOR_ASSERT(par);
80
30
    DISSECTOR_ASSERT((pd->ptype == ASN1_PAR_IRR) || (par->ptype == pd->ptype));
81
30
    par->name = pd->name;
82
30
    pd++;
83
30
    par = par->next;
84
30
  }
85
15
  DISSECTOR_ASSERT(!par);
86
15
}
87
88
30
static asn1_par_t *get_par_by_name(asn1_ctx_t *actx, const char *name) {
89
30
  asn1_par_t *par = NULL;
90
91
30
  DISSECTOR_ASSERT(actx->stack);
92
30
  par = actx->stack->par;
93
45
  while (par) {
94
45
    if (!strcmp(par->name, name))
95
30
      return par;
96
15
    par = par->next;
97
15
  }
98
0
  return par;
99
30
}
100
101
105
static asn1_par_t *push_new_par(asn1_ctx_t *actx) {
102
105
  asn1_par_t *par, **pp;
103
104
105
  DISSECTOR_ASSERT(actx->stack);
105
106
105
  par = wmem_new0(actx->pinfo->pool, asn1_par_t);
107
108
105
  pp = &(actx->stack->par);
109
195
  while (*pp)
110
90
    pp = &((*pp)->next);
111
105
  *pp = par;
112
113
105
  return par;
114
105
}
115
116
25
void asn1_param_push_boolean(asn1_ctx_t *actx, bool value) {
117
25
  asn1_par_t *par;
118
119
25
  par = push_new_par(actx);
120
25
  par->ptype = ASN1_PAR_BOOLEAN;
121
25
  par->value.v_boolean = value;
122
25
}
123
124
80
void asn1_param_push_integer(asn1_ctx_t *actx, int32_t value) {
125
80
  asn1_par_t *par;
126
127
80
  par = push_new_par(actx);
128
80
  par->ptype = ASN1_PAR_INTEGER;
129
80
  par->value.v_integer = value;
130
80
}
131
132
0
bool asn1_param_get_boolean(asn1_ctx_t *actx, const char *name) {
133
0
  asn1_par_t *par = NULL;
134
135
0
  par = get_par_by_name(actx, name);
136
0
  DISSECTOR_ASSERT(par);
137
0
  return par->value.v_boolean;
138
0
}
139
140
30
int32_t asn1_param_get_integer(asn1_ctx_t *actx, const char *name) {
141
30
  asn1_par_t *par = NULL;
142
143
30
  par = get_par_by_name(actx, name);
144
30
  DISSECTOR_ASSERT(par);
145
30
  return par->value.v_integer;
146
30
}
147
148
149
/*--- ROSE ---*/
150
151
45
void rose_ctx_init(rose_ctx_t *rctx) {
152
45
  memset(rctx, '\0', sizeof(*rctx));
153
45
  rctx->signature = ROSE_CTX_SIGNATURE;
154
45
}
155
156
9
bool rose_ctx_check_signature(rose_ctx_t *rctx) {
157
9
  return rctx && (rctx->signature == ROSE_CTX_SIGNATURE);
158
9
}
159
160
10
void rose_ctx_clean_data(rose_ctx_t *rctx) {
161
10
  memset(&rctx->d, '\0', sizeof(rctx->d));
162
10
  rctx->d.code = -1;
163
10
}
164
165
15
asn1_ctx_t *get_asn1_ctx(void *ptr) {
166
15
  asn1_ctx_t *actx = (asn1_ctx_t*)ptr;
167
168
15
  if (!asn1_ctx_check_signature(actx))
169
0
    actx = NULL;
170
171
15
  return actx;
172
15
}
173
174
9
rose_ctx_t *get_rose_ctx(void *ptr) {
175
9
  rose_ctx_t *rctx = (rose_ctx_t*)ptr;
176
9
  asn1_ctx_t *actx = (asn1_ctx_t*)ptr;
177
178
9
  if (!asn1_ctx_check_signature(actx))
179
9
    actx = NULL;
180
181
9
  if (actx)
182
0
    rctx = actx->rose_ctx;
183
184
9
  if (!rose_ctx_check_signature(rctx))
185
0
    rctx = NULL;
186
187
9
  return rctx;
188
9
}
189
190
static double
191
0
asn1_get_overflow(uint8_t first_octet, int S) {
192
0
  if (first_octet & 0x80) {
193
    // Negative exponent
194
0
    return S * 0.0;
195
0
  } else {
196
    // Positive exponent
197
0
    return S * HUGE_VAL;
198
0
  }
199
0
}
200
201
#ifdef _MSC_VER
202
/* MSVC way of turning on floating point exceptions. */
203
#pragma float_control(precise, on, push)
204
#pragma float_control(except, on)
205
#pragma fenv_access(on)
206
#endif
207
208
50
double asn1_get_real(const uint8_t *real_ptr, int len, int *err) {
209
50
  uint8_t octet;
210
50
  const uint8_t *p;
211
50
  double val = 0;
212
50
  *err = 0;
213
214
  /* XXX - We don't check the asn1 context, and so allow any encoding which
215
   * is acceptable in BER, instead of setting EINVAL for overlong encodings
216
   * which are not allowed in CER and DER (11.3) nor PER, which uses the
217
   * same encoding as CER & DER for the real type after octet alignement
218
   * (X.691 15.2). Many of those will set ERANGE instead of EINVAL.
219
   */
220
221
  /* 8.5.2    If the real value is the value zero,
222
   *          there shall be no contents octets in the encoding.
223
   */
224
50
  if (len < 1) return val;
225
226
49
  octet = real_ptr[0];
227
49
  p = real_ptr + 1;
228
49
  len -= 1;
229
49
  if (octet & 0x80) {  /* binary encoding */
230
10
    int i;
231
10
    int8_t S; /* Sign */
232
10
    uint8_t B; /* log base 2 of the Base */
233
10
    uint8_t F; /* scaling Factor */
234
10
    int32_t E = 0; /* Exponent (supported max 3 octets/24 bit) */
235
10
    uint64_t N = 0; /* N (supported max 8 octets/64 bit) */
236
10
    int exp = 0;
237
238
10
    uint8_t lenE, lenN;
239
240
10
    if(octet & 0x40) S = -1; else S = 1;
241
10
    switch(octet & 0x30) {
242
3
      case 0x00: B = 1; break;
243
2
      case 0x10: B = 3; break;
244
3
      case 0x20: B = 4; break;
245
2
      case 0x30: /* Reserved */
246
2
      default:
247
2
        *err = EINVAL;
248
2
        return val;
249
10
    }
250
8
    F = (octet & 0x0c) >> 2;
251
252
    /* 8.5.7.4 Exponent length */
253
8
    lenE = (octet & 0x3) + 1;
254
255
    /* 8.5.7.4 d) Next octet defines length of exponent */
256
8
    if (lenE == 4) {
257
2
      lenE = *p;
258
2
      p++;
259
2
      len--;
260
2
      if (lenE == 0 || lenE >= 3) {
261
        /* "the third up to the (X plus 3)th (inclusive) contents octets encode
262
         * the value of the exponent as a two's complement binary number; the
263
         * value of X shall be at least one; the first nine bits of the
264
         * transmitted exponent shall not be all zeros or all ones."
265
         * The last part means that the exponent could not be representable
266
         * as a two's complement number using fewer octets. If there are
267
         * three octets, that means that the exponent must be sufficiently
268
         * large as not to fit in a IEEE 754 double precision floating point
269
         * (exponent offset binary width 11) or even a quadruple precision
270
         * binary128 (exponent offset binary width 15), or for that matter,
271
         * in an IBM double-precision/long hexadecimal floating point.
272
         *
273
         * Note that if lenE is 1 or 2 here this is not the smallest encoding
274
         * as 8.5.7.4 a) or b) could have been used, so it is still invalid
275
         * in CER, DER, or PER.
276
         */
277
2
        if (lenE == 0) {
278
0
          *err = EINVAL;
279
2
        } else if (lenE >= 3) {
280
2
          if (lenE > len) {
281
2
            *err = ERANGE;
282
2
          } else {
283
0
            val = asn1_get_overflow(*p, S);
284
0
          }
285
2
          *err = ERANGE;
286
2
        }
287
2
        return val;
288
2
      }
289
2
    }
290
291
    /* Ensure the buffer len and its content are coherent */
292
6
    if (lenE > len) {
293
0
      *err = EINVAL;
294
0
      return val;
295
0
    }
296
297
6
    switch (lenE) {
298
1
    case 1:
299
1
      E = ws_sign_ext32(pntohu8(p), 8);
300
1
      break;
301
3
    case 2:
302
3
      E = ws_sign_ext32(pntohu16(p), 16);
303
3
      break;
304
2
    case 3:
305
2
      E = ws_sign_ext32(pntohu24(p), 24);
306
2
      break;
307
0
    default:
308
0
      ws_assert_not_reached();
309
6
    }
310
311
6
    p += lenE;
312
313
    /* 8.5.7.5 "The remaining contents octets encode the value of the integer
314
     * N as an unsigned binary number." */
315
6
    lenN = len - lenE;
316
317
    /* we can't handle integers > 64 bits, but that's ok, as no double precision
318
     * floating format can handle that much precision by definition. */
319
    /* Take the fraction from the first 8 octets and then use the length of the
320
     * remaining octets to adjust the exponent, losing the excess precision.
321
     * If the first octet is all zeros, which is allowed in BER, sigh, NOTE 1,
322
     * we should skip past it and any other all zero octets, but we don't.
323
     * We also ideally should set floating point exception FE_EXACT or an
324
     * errno substitute. */
325
6
    if (lenN > 8) {
326
      // Store the excess precision in bits
327
1
      if (ckd_mul(&exp, 8, lenN - 8)) {
328
        // Wow. Really?
329
0
        val = S * HUGE_VAL;
330
0
        *err = ERANGE;
331
0
        return val;
332
0
      }
333
1
      lenN = 8;
334
1
    }
335
336
40
    for (i=0; i<lenN; i++) {
337
34
      N = (N<<8) | *p;
338
34
      p++;
339
34
    }
340
    /* Since E is never larger than 24 bits, B no larger than 4, B*E + F
341
     * doesn't overflow an int. */
342
6
    if (ckd_add(&exp, exp, B*E + F)) {
343
0
      val = S * HUGE_VAL;
344
0
      *err = ERANGE;
345
6
    } else {
346
6
#ifndef _MSC_VER
347
      /* According to the C standard (7.6.1), #pragma STDC FENV_ACCESS ON can
348
       * appear at the start of a compound statement (i.e., here), and then
349
       * it is restored to its previous state. GCC doesn't support the pragma
350
       * and will warn about an unknown pragma. Luckily it doesn't need it
351
       * either, but some compilers might. */
352
6
      DIAG_OFF(unknown-pragmas)
353
6
      #pragma STDC FENV_ACCESS ON
354
6
#endif
355
6
      errno = 0;
356
6
      feclearexcept(FE_ALL_EXCEPT);
357
6
      val = ldexp((double) S * N, exp);
358
6
      if (errno || fetestexcept(FE_OVERFLOW | FE_UNDERFLOW)) {
359
5
        *err = ERANGE;
360
5
      }
361
6
#ifndef _MSC_VER
362
6
      DIAG_ON(unknown-pragmas)
363
6
#endif
364
6
    }
365
39
  } else if (octet & 0x40) {  /* SpecialRealValue */
366
5
    switch (octet & 0x3F) {
367
1
      case 0x00: val = HUGE_VAL; break;
368
0
      case 0x01: val = -HUGE_VAL; break;
369
0
      case 0x02: val = NAN; break;
370
0
      case 0x03: val = -0.0; break; /* Yes, negative 0 is different. */
371
4
      default:
372
4
        *err = EINVAL;
373
4
        break;
374
5
    }
375
34
  } else {  /* decimal encoding */
376
34
    char *buf;
377
378
34
    buf = g_strndup((const char*)p, len);
379
    /* g_ascii_strtod resets errno and returns ERANGE as appropriate */
380
34
    val = g_ascii_strtod(buf, NULL);
381
34
    if (errno == ERANGE) {
382
0
      *err = ERANGE;
383
34
    } else if (val == 0.0) {
384
      /* Since 0.0 "shall" be encoded with no contents octets (8.5.2), (and
385
       * minus 0 per 8.5.9) a return value of 0.0 must be a failed conversion
386
       * or where a zero was encoded with decimal encoding in violation of
387
       * the specification, and thus EINVAL is appropriate. */
388
34
      *err = EINVAL;
389
34
    }
390
34
    g_free(buf);
391
34
  }
392
393
45
  return val;
394
49
}
395
396
#ifdef _MSC_VER
397
#pragma float_control(pop)
398
#endif
399
400
/*
401
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
402
 *
403
 * Local Variables:
404
 * c-basic-offset: 2
405
 * tab-width: 8
406
 * indent-tabs-mode: nil
407
 * End:
408
 *
409
 * ex: set shiftwidth=2 tabstop=8 expandtab:
410
 * :indentSize=2:tabSize=8:noTabs=true:
411
 */