Coverage Report

Created: 2026-11-12 07:01

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