Revert "In get_unicode_or_ascii_string(), check if the length is odd/even, not the...
[wireshark-wip.git] / plugins / asn1 / asn1.c
blob7390990bdf025bc50ee3941ab8d1de887f1864ff
1 /* asn1.c
2 * Routines for ASN.1 BER dissection
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
9 * Based on "g_asn1.c" from:
11 * GXSNMP -- An snmp mangament application
12 * Copyright (C) 1998 Gregory McLean & Jochen Friedrich
13 * Beholder RMON ethernet network monitor, Copyright (C) 1993 DNPAP group
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 * MODULE INFORMATION
32 * ------------------
33 * FILE NAME: g_asn1.c
34 * SYSTEM NAME: ASN1 Basic Encoding
35 * ORIGINAL AUTHOR(S): Dirk Wisse
36 * VERSION NUMBER: 1
37 * CREATION DATE: 1990/11/22
39 * DESCRIPTION: ASN1 Basic Encoding Rules.
41 * To decode this we must do:
43 * asn1_open (asn1, tvb, offset);
44 * asn1_header_decode (asn1, &end_of_seq, cls, con, tag, def, len);
45 * asn1_header_decode (asn1, &end_of_octs, cls, con, tag, def, len);
46 * asn1_octets_decode (asn1, end_of_octs, str, len);
47 * asn1_header_decode (asn1, &end_of_int, cls, con, tag);
48 * asn1_int_decode (asn1, end_of_int, &integer);
49 * asn1_eoc_decode (asn1, end_of_seq);
50 * asn1_close (asn1, &offset);
52 * For indefinite encoding end_of_seq and &end_of_seq in the
53 * example above should be replaced by NULL.
54 * For indefinite decoding nothing has to be changed.
55 * This can be very useful if you want to decode both
56 * definite and indefinite encodings.
59 #include "config.h"
61 #include <glib.h>
63 #define subid_t guint32 /* ugly hack to get it to compile this symbol should be suppressed! */
65 #include <epan/tvbuff.h>
66 #include <plugins/asn1/asn1.h>
67 #include <epan/emem.h>
71 * NAME: asn1_open [API]
72 * SYNOPSIS: void asn1_open
73 * (
74 * ASN1_SCK *asn1,
75 * tvbuff_t *tvb,
76 * int offset
77 * )
78 * DESCRIPTION: Opens an ASN1 socket.
79 * Parameters:
80 * asn1: pointer to ASN1 socket.
81 * tvb: Tvbuff for encoding.
82 * offset: Current offset in tvbuff.
83 * Encoding starts at the end of the buffer, and
84 * proceeds to the beginning.
85 * RETURNS: void
88 void
89 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
91 asn1->tvb = tvb;
92 asn1->offset = offset;
96 * NAME: asn1_close [API]
97 * SYNOPSIS: void asn1_close
98 * (
99 * ASN1_SCK *asn1,
100 * int *offset
102 * DESCRIPTION: Closes an ASN1 socket.
103 * Parameters:
104 * asn1: pointer to ASN1 socket.
105 * offset: pointer to variable into which current offset is
106 * to be put.
107 * RETURNS: void
110 void
111 asn1_close(ASN1_SCK *asn1, int *offset)
113 *offset = asn1->offset;
117 * NAME: asn1_octet_decode
118 * SYNOPSIS: int asn1_octet_decode
120 * ASN1_SCK *asn1,
121 * guchar *ch
123 * DESCRIPTION: Decodes an octet.
124 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
127 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
129 *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
130 asn1->offset++;
131 return ASN1_ERR_NOERROR;
135 * NAME: asn1_tag_get
136 * SYNOPSIS: int asn1_tag_get
138 * ASN1_SCK *asn1,
139 * guint *tag
141 * DESCRIPTION: Decodes a tag number, combining it with existing tag bits.
142 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
144 static int
145 asn1_tag_get(ASN1_SCK *asn1, guint *tag)
147 int ret;
148 guchar ch;
150 do {
151 ret = asn1_octet_decode (asn1, &ch);
152 if (ret != ASN1_ERR_NOERROR)
153 return ret;
154 *tag <<= 7;
155 *tag |= ch & 0x7F;
156 } while ((ch & 0x80) == 0x80);
157 return ASN1_ERR_NOERROR;
161 * NAME: asn1_tag_decode
162 * SYNOPSIS: int asn1_tag_decode
164 * ASN1_SCK *asn1,
165 * guint *tag
167 * DESCRIPTION: Decodes a tag number.
168 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
171 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
173 *tag = 0;
174 return asn1_tag_get(asn1, tag);
178 * NAME: asn1_id_decode
179 * SYNOPSIS: int asn1_id_decode
181 * ASN1_SCK *asn1,
182 * guint *cls,
183 * guint *con,
184 * guint *tag
186 * DESCRIPTION: Decodes an identifier.
187 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
190 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
192 int ret;
193 guchar ch;
195 *tag = 0;
196 ret = asn1_octet_decode (asn1, &ch);
197 if (ret != ASN1_ERR_NOERROR)
198 return ret;
199 *cls = (ch & 0xC0) >> 6;
200 *con = (ch & 0x20) >> 5;
201 *tag = (ch & 0x1F);
202 if (*tag == 0x1F) {
203 ret = asn1_tag_decode (asn1, tag);
204 if (ret != ASN1_ERR_NOERROR)
205 return ret;
207 return ASN1_ERR_NOERROR;
211 * NAME: asn1_id_decode1
212 * SYNOPSIS: int asn1_id_decode1
214 * ASN1_SCK *asn1,
215 * guint *tag
217 * DESCRIPTION: Decodes an identifier.
218 * Like asn1_id_decode() except that the Class and Constructor
219 * bits are returned in the tag.
220 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
223 asn1_id_decode1(ASN1_SCK *asn1, guint *tag)
225 int ret;
226 guchar ch;
228 *tag = 0;
229 ret = asn1_octet_decode (asn1, &ch);
230 if (ret != ASN1_ERR_NOERROR)
231 return ret;
233 *tag = ch;
234 if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */
235 *tag = ch >> 5; /* leave just the Class and Constructor bits */
236 ret = asn1_tag_get (asn1, tag);
237 if (ret != ASN1_ERR_NOERROR)
238 return ret;
240 return ASN1_ERR_NOERROR;
244 * NAME: asn1_length_decode
245 * SYNOPSIS: int asn1_length_decode
247 * ASN1_SCK *asn1,
248 * gboolean *def,
249 * guint *len
251 * DESCRIPTION: Decodes an ASN1 length.
252 * Parameters:
253 * asn1: pointer to ASN1 socket.
254 * def: Boolean - TRUE if length definite, FALSE if not
255 * len: length, if length is definite
256 * DESCRIPTION: Decodes a definite or indefinite length.
257 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
260 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
262 int ret;
263 guchar ch, cnt;
265 ret = asn1_octet_decode (asn1, &ch);
266 if (ret != ASN1_ERR_NOERROR)
267 return ret;
268 if (ch == 0x80)
269 *def = FALSE; /* indefinite length */
270 else {
271 *def = TRUE; /* definite length */
272 if (ch < 0x80)
273 *len = ch;
274 else {
275 cnt = (guchar) (ch & 0x7F);
276 *len = 0;
277 while (cnt > 0) {
278 ret = asn1_octet_decode (asn1, &ch);
279 if (ret != ASN1_ERR_NOERROR)
280 return ret;
281 *len <<= 8;
282 *len |= ch;
283 cnt--;
287 return ASN1_ERR_NOERROR;
291 * NAME: asn1_header_decode [API]
292 * SYNOPSIS: int asn1_header_decode
294 * ASN1_SCK *asn1,
295 * guint *cls,
296 * guint *con,
297 * guint *tag
298 * gboolean *defp,
299 * guint *lenp
301 * DESCRIPTION: Decodes an ASN1 header.
302 * Parameters:
303 * asn1: pointer to ASN1 socket.
304 * cls: Class (see asn1.h)
305 * con: Primitive, Constructed (ASN1_PRI, ASN1_CON)
306 * tag: Tag (see asn1.h)
307 * defp: Boolean - TRUE if length definite, FALSE if not
308 * lenp: length, if length is definite
309 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
312 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
313 gboolean *defp, guint *lenp)
315 int ret;
316 guint len = 0;
317 gboolean def;
319 ret = asn1_id_decode (asn1, cls, con, tag);
320 if (ret != ASN1_ERR_NOERROR)
321 return ret;
322 ret = asn1_length_decode (asn1, &def, &len);
323 if (ret != ASN1_ERR_NOERROR)
324 return ret;
325 *defp = def;
326 *lenp = len;
327 return ASN1_ERR_NOERROR;
332 * NAME: asn1_eoc [API]
333 * SYNOPSIS: gboolean asn1_eoc
335 * ASN1_SCK *asn1,
336 * int eoc
338 * DESCRIPTION: Checks if decoding is at End Of Contents.
339 * Parameters:
340 * asn1: pointer to ASN1 socket.
341 * eoc: offset of end of encoding, or -1 if indefinite.
342 * RETURNS: gboolean success
344 gboolean
345 asn1_eoc ( ASN1_SCK *asn1, int eoc)
347 if (eoc == -1)
348 return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
349 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
350 else
351 return (asn1->offset >= eoc);
355 * NAME: asn1_eoc_decode [API]
356 * SYNOPSIS: int asn1_eoc_decode
358 * ASN1_SCK *asn1,
359 * int eoc
361 * DESCRIPTION: Decodes End Of Contents.
362 * Parameters:
363 * asn1: pointer to ASN1 socket.
364 * eoc: offset of end of encoding, or -1 if indefinite.
365 * If eoc is -1 it decodes an ASN1 End Of
366 * Contents (0x00 0x00), so it has to be an
367 * indefinite length encoding. If eoc is a non-negative
368 * integer, it probably was filled by asn1_header_decode,
369 * and should refer to the octet after the last of the encoding.
370 * It is checked if this offset refers to the octet to be
371 * decoded. This only takes place in decoding a
372 * definite length encoding.
373 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
376 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
378 int ret;
379 guchar ch;
381 if (eoc == -1) {
382 ret = asn1_octet_decode (asn1, &ch);
383 if (ret != ASN1_ERR_NOERROR)
384 return ret;
385 if (ch != 0x00)
386 return ASN1_ERR_EOC_MISMATCH;
387 ret = asn1_octet_decode (asn1, &ch);
388 if (ret != ASN1_ERR_NOERROR)
389 return ret;
390 if (ch != 0x00)
391 return ASN1_ERR_EOC_MISMATCH;
392 return ASN1_ERR_NOERROR;
393 } else {
394 if (asn1->offset != eoc)
395 return ASN1_ERR_LENGTH_MISMATCH;
396 return ASN1_ERR_NOERROR;
401 * NAME: asn1_null_decode [API]
402 * SYNOPSIS: int asn1_null_decode
404 * ASN1_SCK *asn1,
405 * int enc_len
407 * DESCRIPTION: Decodes Null.
408 * Parameters:
409 * asn1: pointer to ASN1 socket.
410 * enc_len: length of encoding of value.
411 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
414 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
416 int start_off = asn1->offset;
418 asn1->offset += enc_len;
420 * Check for integer overflows.
421 * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
422 * error from the ones available. Should we make a new one?
424 if (asn1->offset < 0 || asn1->offset < start_off)
425 return ASN1_ERR_LENGTH_MISMATCH;
427 return ASN1_ERR_NOERROR;
431 * NAME: asn1_bool_decode [API]
432 * SYNOPSIS: int asn1_bool_decode
434 * ASN1_SCK *asn1,
435 * int enc_len,
436 * gboolean *boolean
438 * DESCRIPTION: Decodes Boolean.
439 * Parameters:
440 * asn1: pointer to ASN1 socket.
441 * enc_len: length of encoding of value.
442 * bool: False, True (0, !0).
443 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
446 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *boolean)
448 int ret;
449 guchar ch;
451 if (enc_len != 1)
452 return ASN1_ERR_LENGTH_MISMATCH;
453 ret = asn1_octet_decode (asn1, &ch);
454 if (ret != ASN1_ERR_NOERROR)
455 return ret;
456 *boolean = ch ? TRUE : FALSE;
457 return ASN1_ERR_NOERROR;
461 * NAME: asn1_int32_value_decode [API]
462 * SYNOPSIS: int asn1_int32_value_decode
464 * ASN1_SCK *asn1,
465 * int enc_len,
466 * gint32 *integer
468 * DESCRIPTION: Decodes value portion of Integer (which must be no more
469 * than 32 bits).
470 * Parameters:
471 * asn1: pointer to ASN1 socket.
472 * enc_len: length of encoding of value.
473 * integer: Integer.
474 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
477 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
479 int ret;
480 int eoc;
481 guchar ch;
482 guint len;
484 eoc = asn1->offset + enc_len;
485 ret = asn1_octet_decode (asn1, &ch);
486 if (ret != ASN1_ERR_NOERROR)
487 return ret;
488 *integer = (gint) ch;
489 len = 1;
490 while (asn1->offset < eoc) {
491 if (++len > sizeof (gint32))
492 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
493 ret = asn1_octet_decode (asn1, &ch);
494 if (ret != ASN1_ERR_NOERROR)
495 return ret;
496 *integer <<= 8;
497 *integer |= ch;
499 return ASN1_ERR_NOERROR;
503 * NAME: asn1_int32_decode [API]
504 * SYNOPSIS: int asn1_int32_decode
506 * ASN1_SCK *asn1,
507 * gint32 *integer,
508 * guint *nbytes,
510 * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
511 * Parameters:
512 * asn1: pointer to ASN1 socket.
513 * integer: Integer.
514 * nbytes: number of bytes used to encode it.
515 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
518 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
520 int ret;
521 int start;
522 guint cls;
523 guint con;
524 guint tag;
525 gboolean def;
526 guint enc_len;
528 start = asn1->offset;
529 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
530 if (ret != ASN1_ERR_NOERROR)
531 goto done;
532 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
533 ret = ASN1_ERR_WRONG_TYPE;
534 goto done;
536 if (!def) {
537 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
538 goto done;
540 ret = asn1_int32_value_decode (asn1, enc_len, integer);
542 done:
543 *nbytes = asn1->offset - start;
544 return ret;
548 * NAME: asn1_uint32_value_decode [API]
549 * SYNOPSIS: int asn1_uint32_value_decode
551 * ASN1_SCK *asn1,
552 * int enc_len,
553 * guint32 *integer
555 * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
556 * more than 32 bits).
557 * Parameters:
558 * asn1: pointer to ASN1 socket.
559 * enc_len: length of encoding of value.
560 * integer: Integer.
561 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
564 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer)
566 int ret;
567 int eoc;
568 guchar ch;
569 guint len;
571 eoc = asn1->offset + enc_len;
572 ret = asn1_octet_decode (asn1, &ch);
573 if (ret != ASN1_ERR_NOERROR)
574 return ret;
575 *integer = ch;
576 if (ch == 0)
577 len = 0;
578 else
579 len = 1;
580 while (asn1->offset < eoc) {
581 if (++len > sizeof (guint32))
582 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
583 ret = asn1_octet_decode (asn1, &ch);
584 if (ret != ASN1_ERR_NOERROR)
585 return ret;
586 *integer <<= 8;
587 *integer |= ch;
589 return ASN1_ERR_NOERROR;
593 * NAME: asn1_uint32_decode [API]
594 * SYNOPSIS: int asn1_uint32_decode
596 * ASN1_SCK *asn1,
597 * guint32 *integer,
598 * guint *nbytes,
600 * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
601 * Parameters:
602 * asn1: pointer to ASN1 socket.
603 * integer: Integer.
604 * nbytes: number of bytes used to encode it.
605 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
608 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
610 int ret;
611 int start;
612 guint cls;
613 guint con;
614 guint tag;
615 gboolean def;
616 guint enc_len;
618 start = asn1->offset;
619 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
620 if (ret != ASN1_ERR_NOERROR)
621 goto done;
622 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
623 ret = ASN1_ERR_WRONG_TYPE;
624 goto done;
626 if (!def) {
627 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
628 goto done;
630 ret = asn1_uint32_value_decode (asn1, enc_len, integer);
632 done:
633 *nbytes = asn1->offset - start;
634 return ret;
638 * NAME: asn1_bits_decode [API]
639 * SYNOPSIS: int asn1_bits_decode
641 * ASN1_SCK *asn1,
642 * int eoc,
643 * guchar *bits,
644 * guint size,
645 * guint len,
646 * guchar unused
648 * DESCRIPTION: Decodes Bit String.
649 * Parameters:
650 * asn1: pointer to ASN1 socket.
651 * enc_len: length of value.
652 * bits: pointer to variable we set to point to strring
653 * len: Size of Bit String in characters.
654 * unused: Number of unused bits in last character.
655 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
658 asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits,
659 guint *len, guchar *unused)
661 int ret;
662 int eoc;
663 guchar *ptr;
665 eoc = asn1->offset + enc_len;
666 *bits = NULL;
667 ret = asn1_octet_decode (asn1, unused);
668 if (ret != ASN1_ERR_NOERROR)
669 return ret;
670 *len = 0;
673 * First, make sure the entire string is in the tvbuff, and throw
674 * an exception if it isn't. If the length is bogus, this should
675 * keep us from trying to allocate an immensely large buffer.
676 * (It won't help if the length is *valid* but immensely large,
677 * but that's another matter; in any case, that would happen only
678 * if we had an immensely large tvbuff....)
680 if (enc_len != 0) {
681 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
682 *bits = (guchar *)g_malloc (enc_len);
683 } else {
685 * If the length is 0, we allocate a 1-byte buffer, as
686 * "g_malloc()" returns NULL if passed 0 as an argument,
687 * and our caller expects us to return a pointer to a
688 * buffer.
690 *bits = (guchar *)g_malloc (1);
693 ptr = *bits;
694 while (asn1->offset < eoc) {
695 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
696 if (ret != ASN1_ERR_NOERROR) {
697 g_free(*bits);
698 *bits = NULL;
699 return ret;
702 *len = (guint) (ptr - *bits);
703 return ASN1_ERR_NOERROR;
707 * NAME: asn1_string_value_decode [API]
708 * SYNOPSIS: int asn1_string_value_decode
710 * ASN1_SCK *asn1,
711 * int enc_len,
712 * guchar **octets
714 * DESCRIPTION: Decodes value portion of string (Octet String, various
715 * character string types)
716 * Parameters:
717 * asn1: pointer to ASN1 socket.
718 * enc_len: length of encoding of value.
719 * octets: pointer to variable we set to point to string,
720 * which is '\0' terminated for ease of use as C-string
721 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
724 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
726 int ret;
727 int eoc;
728 guchar *ptr;
731 * First, make sure the entire string is in the tvbuff, and throw
732 * an exception if it isn't. If the length is bogus, this should
733 * keep us from trying to allocate an immensely large buffer.
734 * (It won't help if the length is *valid* but immensely large,
735 * but that's another matter; in any case, that would happen only
736 * if we had an immensely large tvbuff....)
738 if (enc_len != 0)
739 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
740 *octets = (guchar *)g_malloc (enc_len+1);
742 eoc = asn1->offset + enc_len;
743 ptr = *octets;
744 while (asn1->offset < eoc) {
745 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
746 if (ret != ASN1_ERR_NOERROR) {
747 g_free(*octets);
748 *octets = NULL;
749 return ret;
752 *(guchar *)ptr = '\0';
753 return ASN1_ERR_NOERROR;
757 * NAME: asn1_string_decode [API]
758 * SYNOPSIS: int asn1_string_decode
760 * ASN1_SCK *asn1,
761 * guchar **octets,
762 * guint *str_len,
763 * guint *nbytes,
764 * guint expected_tag
766 * DESCRIPTION: Decodes string (Octet String, various character string
767 * types)
768 * Parameters:
769 * asn1: pointer to ASN1 socket.
770 * octets: pointer to variable we set to point to string.
771 * str_len: length of octet_string.
772 * nbytes: number of bytes used to encode.
773 * expected_tag: tag expected for this type of string.
774 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
777 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
778 guint *nbytes, guint expected_tag)
780 int ret;
781 int start;
782 guint enc_len;
783 guint cls;
784 guint con;
785 guint tag;
786 gboolean def;
788 start = asn1->offset;
789 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
790 if (ret != ASN1_ERR_NOERROR)
791 goto done;
792 if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
793 /* XXX - handle the constructed encoding? */
794 ret = ASN1_ERR_WRONG_TYPE;
795 goto done;
797 if (!def) {
798 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
799 goto done;
802 ret = asn1_string_value_decode (asn1, enc_len, octets);
803 *str_len = enc_len;
805 done:
806 *nbytes = asn1->offset - start;
807 return ret;
811 * NAME: asn1_octet_string_decode [API]
812 * SYNOPSIS: int asn1_octet_string_decode
814 * ASN1_SCK *asn1,
815 * guchar **octets,
816 * guint *str_len,
817 * guint *nbytes,
819 * DESCRIPTION: Decodes Octet String.
820 * Parameters:
821 * asn1: pointer to ASN1 socket.
822 * octets: pointer to variable we set to point to string.
823 * str_len: length of octet_string.
824 * nbytes: number of bytes used to encode.
825 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
828 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
829 guint *nbytes)
831 return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
835 * NAME: asn1_subid_decode
836 * SYNOPSIS: int asn1_subid_decode
838 * ASN1_SCK *asn1,
839 * subid_t *subid
841 * DESCRIPTION: Decodes Sub Identifier.
842 * Parameters:
843 * asn1: pointer to ASN1 socket.
844 * subid: Sub Identifier.
845 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
848 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
850 int ret;
851 guchar ch;
853 *subid = 0;
854 do {
855 ret = asn1_octet_decode(asn1, &ch);
856 if (ret != ASN1_ERR_NOERROR)
857 return ret;
858 *subid <<= 7;
859 *subid |= ch & 0x7F;
860 } while ((ch & 0x80) == 0x80);
861 return ASN1_ERR_NOERROR;
865 * NAME: asn1_oid_value_decode [API]
866 * SYNOPSIS: int asn1_oid_value_decode
868 * ASN1_SCK *asn1,
869 * int enc_len,
870 * subid_t **oid,
871 * guint *len
873 * DESCRIPTION: Decodes value portion of Object Identifier.
874 * Parameters:
875 * asn1: pointer to ASN1 socket.
876 * enc_len: length of encoding of value.
877 * oid: pointer to variable we set to Object Identifier.
878 * len: Length of Object Identifier in gulongs.
879 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
882 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
884 int ret;
885 int eoc;
886 subid_t subid;
887 guint size;
888 subid_t *optr;
891 * First, make sure the entire string is in the tvbuff, and throw
892 * an exception if it isn't. If the length is bogus, this should
893 * keep us from trying to allocate an immensely large buffer.
894 * (It won't help if the length is *valid* but immensely large,
895 * but that's another matter; in any case, that would happen only
896 * if we had an immensely large tvbuff....)
898 if (enc_len < 1) {
899 *oid = NULL;
900 return ASN1_ERR_LENGTH_MISMATCH;
902 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
904 eoc = asn1->offset + enc_len;
906 size = enc_len + 1;
907 *oid = (guint32 *)g_malloc(size * sizeof(gulong));
908 optr = *oid;
910 ret = asn1_subid_decode (asn1, &subid);
911 if (ret != ASN1_ERR_NOERROR) {
912 g_free(*oid);
913 *oid = NULL;
914 return ret;
916 if (subid < 40) {
917 optr[0] = 0;
918 optr[1] = subid;
919 } else if (subid < 80) {
920 optr[0] = 1;
921 optr[1] = subid - 40;
922 } else {
923 optr[0] = 2;
924 optr[1] = subid - 80;
926 *len = 2;
927 optr += 2;
928 while (asn1->offset < eoc) {
929 if (++(*len) > size) {
930 g_free(*oid);
931 *oid = NULL;
932 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
934 ret = asn1_subid_decode (asn1, optr++);
935 if (ret != ASN1_ERR_NOERROR) {
936 g_free(*oid);
937 *oid = NULL;
938 return ret;
941 return ASN1_ERR_NOERROR;
945 * NAME: asn1_oid_decode [API]
946 * SYNOPSIS: int asn1_oid_decode
948 * ASN1_SCK *asn1,
949 * subid_t **oid,
950 * guint *len,
951 * guint *nbytes
953 * DESCRIPTION: Decodes Object Identifier.
954 * Parameters:
955 * asn1: pointer to ASN1 socket.
956 * oid: pointer to variable we set to Object Identifier.
957 * len: Length of Object Identifier in gulongs.
958 * nbytes: number of bytes used to encode.
959 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
962 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
964 int ret;
965 int start;
966 guint cls;
967 guint con;
968 guint tag;
969 gboolean def;
970 guint enc_len;
972 start = asn1->offset;
973 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
974 if (ret != ASN1_ERR_NOERROR)
975 goto done;
976 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
977 ret = ASN1_ERR_WRONG_TYPE;
978 goto done;
980 if (!def) {
981 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
982 goto done;
985 ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
987 done:
988 *nbytes = asn1->offset - start;
989 return ret;
993 * NAME: asn1_sequence_decode [API]
994 * SYNOPSIS: int asn1_sequence_decode
996 * ASN1_SCK *asn1,
997 * guint *seq_len,
998 * guint *nbytes
1000 * DESCRIPTION: Decodes header for SEQUENCE.
1001 * Parameters:
1002 * asn1: pointer to ASN1 socket.
1003 * seq_len: length of sequence.
1004 * nbytes: number of bytes used to encode header.
1005 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
1008 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
1010 int ret;
1011 int start;
1012 guint cls;
1013 guint con;
1014 guint tag;
1015 gboolean def;
1017 start = asn1->offset;
1018 ret = asn1_header_decode(asn1, &cls, &con, &tag,
1019 &def, seq_len);
1020 if (ret != ASN1_ERR_NOERROR)
1021 goto done;
1022 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
1023 ret = ASN1_ERR_WRONG_TYPE;
1024 goto done;
1026 if (!def) {
1027 /* XXX - might some sequences have an indefinite length? */
1028 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
1029 goto done;
1031 ret = ASN1_ERR_NOERROR;
1033 done:
1034 *nbytes = asn1->offset - start;
1035 return ret;
1039 * NAME: asn1_err_to_str [API]
1040 * SYNOPSIS: const char *asn1_err_to_str
1042 * int err
1044 * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
1045 * Parameters:
1046 * err: the error code
1047 * RETURNS: string for the error
1049 const char *
1050 asn1_err_to_str(int err)
1052 const char *errstr;
1053 char errstrbuf[14+1+1+11+1+1]; /* "Unknown error (%d)\0" */
1055 switch (err) {
1057 case ASN1_ERR_EOC_MISMATCH:
1058 errstr = "EOC mismatch";
1059 break;
1061 case ASN1_ERR_WRONG_TYPE:
1062 errstr = "Wrong type for that item";
1063 break;
1065 case ASN1_ERR_LENGTH_NOT_DEFINITE:
1066 errstr = "Length was indefinite";
1067 break;
1069 case ASN1_ERR_LENGTH_MISMATCH:
1070 errstr = "Length mismatch";
1071 break;
1073 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1074 errstr = "Wrong length for that item's type";
1075 break;
1077 default:
1078 g_snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);
1079 errstr = ep_strdup(errstrbuf);
1080 break;
1082 return errstr;