2 * Routines for ASN.1 BER dissection
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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., 675 Mass Ave, Cambridge, MA 02139, USA.
34 * SYSTEM NAME: ASN1 Basic Encoding
35 * ORIGINAL AUTHOR(S): Dirk Wisse
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.
69 #include <epan/tvbuff.h>
70 #include <epan/asn1.h>
73 * NAME: asn1_open [API]
74 * SYNOPSIS: void asn1_open
80 * DESCRIPTION: Opens an ASN1 socket.
82 * asn1: pointer to ASN1 socket.
83 * tvb: Tvbuff for encoding.
84 * offset: Current offset in tvbuff.
85 * Encoding starts at the end of the buffer, and
86 * proceeds to the beginning.
91 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
94 asn1->offset = offset;
98 * NAME: asn1_close [API]
99 * SYNOPSIS: void asn1_close
104 * DESCRIPTION: Closes an ASN1 socket.
106 * asn1: pointer to ASN1 socket.
107 * offset: pointer to variable into which current offset is
113 asn1_close(ASN1_SCK *asn1, int *offset)
115 *offset = asn1->offset;
119 * NAME: asn1_octet_decode
120 * SYNOPSIS: int asn1_octet_decode
125 * DESCRIPTION: Decodes an octet.
126 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
129 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
131 *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
133 return ASN1_ERR_NOERROR;
138 * SYNOPSIS: int asn1_tag_get
143 * DESCRIPTION: Decodes a tag number, combining it with existing tag bits.
144 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
147 asn1_tag_get(ASN1_SCK *asn1, guint *tag)
153 ret = asn1_octet_decode (asn1, &ch);
154 if (ret != ASN1_ERR_NOERROR)
158 } while ((ch & 0x80) == 0x80);
159 return ASN1_ERR_NOERROR;
163 * NAME: asn1_tag_decode
164 * SYNOPSIS: int asn1_tag_decode
169 * DESCRIPTION: Decodes a tag number.
170 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
173 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
176 return asn1_tag_get(asn1, tag);
180 * NAME: asn1_id_decode
181 * SYNOPSIS: int asn1_id_decode
188 * DESCRIPTION: Decodes an identifier.
189 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
192 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
198 ret = asn1_octet_decode (asn1, &ch);
199 if (ret != ASN1_ERR_NOERROR)
201 *cls = (ch & 0xC0) >> 6;
202 *con = (ch & 0x20) >> 5;
205 ret = asn1_tag_decode (asn1, tag);
206 if (ret != ASN1_ERR_NOERROR)
209 return ASN1_ERR_NOERROR;
213 * NAME: asn1_id_decode1
214 * SYNOPSIS: int asn1_id_decode1
219 * DESCRIPTION: Decodes an identifier.
220 * Like asn1_id_decode() except that the Class and Constructor
221 * bits are returned in the tag.
222 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
225 asn1_id_decode1(ASN1_SCK *asn1, guint *tag)
231 ret = asn1_octet_decode (asn1, &ch);
232 if (ret != ASN1_ERR_NOERROR)
236 if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */
237 *tag = ch >> 5; /* leave just the Class and Constructor bits */
238 ret = asn1_tag_get (asn1, tag);
239 if (ret != ASN1_ERR_NOERROR)
242 return ASN1_ERR_NOERROR;
246 * NAME: asn1_length_decode
247 * SYNOPSIS: int asn1_length_decode
253 * DESCRIPTION: Decodes an ASN1 length.
255 * asn1: pointer to ASN1 socket.
256 * def: Boolean - TRUE if length definite, FALSE if not
257 * len: length, if length is definite
258 * DESCRIPTION: Decodes a definite or indefinite length.
259 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
262 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
267 ret = asn1_octet_decode (asn1, &ch);
268 if (ret != ASN1_ERR_NOERROR)
271 *def = FALSE; /* indefinite length */
273 *def = TRUE; /* definite length */
277 cnt = (guchar) (ch & 0x7F);
280 ret = asn1_octet_decode (asn1, &ch);
281 if (ret != ASN1_ERR_NOERROR)
289 return ASN1_ERR_NOERROR;
293 * NAME: asn1_header_decode [API]
294 * SYNOPSIS: int asn1_header_decode
303 * DESCRIPTION: Decodes an ASN1 header.
305 * asn1: pointer to ASN1 socket.
306 * cls: Class (see asn1.h)
307 * con: Primitive, Constructed (ASN1_PRI, ASN1_CON)
308 * tag: Tag (see asn1.h)
309 * defp: Boolean - TRUE if length definite, FALSE if not
310 * lenp: length, if length is definite
311 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
314 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
315 gboolean *defp, guint *lenp)
320 ret = asn1_id_decode (asn1, cls, con, tag);
321 if (ret != ASN1_ERR_NOERROR)
323 ret = asn1_length_decode (asn1, &def, &len);
324 if (ret != ASN1_ERR_NOERROR)
328 return ASN1_ERR_NOERROR;
333 * NAME: asn1_eoc [API]
334 * SYNOPSIS: gboolean asn1_eoc
339 * DESCRIPTION: Checks if decoding is at End Of Contents.
341 * asn1: pointer to ASN1 socket.
342 * eoc: offset of end of encoding, or -1 if indefinite.
343 * RETURNS: gboolean success
346 asn1_eoc ( ASN1_SCK *asn1, int eoc)
349 return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
350 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
352 return (asn1->offset >= eoc);
356 * NAME: asn1_eoc_decode [API]
357 * SYNOPSIS: int asn1_eoc_decode
362 * DESCRIPTION: Decodes End Of Contents.
364 * asn1: pointer to ASN1 socket.
365 * eoc: offset of end of encoding, or -1 if indefinite.
366 * If eoc is -1 it decodes an ASN1 End Of
367 * Contents (0x00 0x00), so it has to be an
368 * indefinite length encoding. If eoc is a non-negative
369 * integer, it probably was filled by asn1_header_decode,
370 * and should refer to the octet after the last of the encoding.
371 * It is checked if this offset refers to the octet to be
372 * decoded. This only takes place in decoding a
373 * definite length encoding.
374 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
377 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
383 ret = asn1_octet_decode (asn1, &ch);
384 if (ret != ASN1_ERR_NOERROR)
387 return ASN1_ERR_EOC_MISMATCH;
388 ret = asn1_octet_decode (asn1, &ch);
389 if (ret != ASN1_ERR_NOERROR)
392 return ASN1_ERR_EOC_MISMATCH;
393 return ASN1_ERR_NOERROR;
395 if (asn1->offset != eoc)
396 return ASN1_ERR_LENGTH_MISMATCH;
397 return ASN1_ERR_NOERROR;
402 * NAME: asn1_null_decode [API]
403 * SYNOPSIS: int asn1_null_decode
408 * DESCRIPTION: Decodes Null.
410 * asn1: pointer to ASN1 socket.
411 * enc_len: length of encoding of value.
412 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
415 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
417 int start_off = asn1->offset;
419 asn1->offset += enc_len;
421 * Check for integer overflows.
422 * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
423 * error from the ones available. Should we make a new one?
425 if (asn1->offset < 0 || asn1->offset < start_off)
426 return ASN1_ERR_LENGTH_MISMATCH;
428 return ASN1_ERR_NOERROR;
432 * NAME: asn1_bool_decode [API]
433 * SYNOPSIS: int asn1_bool_decode
439 * DESCRIPTION: Decodes Boolean.
441 * asn1: pointer to ASN1 socket.
442 * enc_len: length of encoding of value.
443 * bool: False, True (0, !0).
444 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
447 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *boolean)
453 return ASN1_ERR_LENGTH_MISMATCH;
454 ret = asn1_octet_decode (asn1, &ch);
455 if (ret != ASN1_ERR_NOERROR)
457 *boolean = ch ? TRUE : FALSE;
458 return ASN1_ERR_NOERROR;
462 * NAME: asn1_int32_value_decode [API]
463 * SYNOPSIS: int asn1_int32_value_decode
469 * DESCRIPTION: Decodes value portion of Integer (which must be no more
472 * asn1: pointer to ASN1 socket.
473 * enc_len: length of encoding of value.
475 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
478 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
485 eoc = asn1->offset + enc_len;
486 ret = asn1_octet_decode (asn1, &ch);
487 if (ret != ASN1_ERR_NOERROR)
489 *integer = (gint) ch;
491 while (asn1->offset < eoc) {
492 if (++len > sizeof (gint32))
493 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
494 ret = asn1_octet_decode (asn1, &ch);
495 if (ret != ASN1_ERR_NOERROR)
500 return ASN1_ERR_NOERROR;
504 * NAME: asn1_int32_decode [API]
505 * SYNOPSIS: int asn1_int32_decode
511 * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
513 * asn1: pointer to ASN1 socket.
515 * nbytes: number of bytes used to encode it.
516 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
519 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
529 start = asn1->offset;
530 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
531 if (ret != ASN1_ERR_NOERROR)
533 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
534 ret = ASN1_ERR_WRONG_TYPE;
538 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
541 ret = asn1_int32_value_decode (asn1, enc_len, integer);
544 *nbytes = asn1->offset - start;
549 * NAME: asn1_uint32_value_decode [API]
550 * SYNOPSIS: int asn1_uint32_value_decode
556 * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
557 * more than 32 bits).
559 * asn1: pointer to ASN1 socket.
560 * enc_len: length of encoding of value.
562 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
565 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer)
572 eoc = asn1->offset + enc_len;
573 ret = asn1_octet_decode (asn1, &ch);
574 if (ret != ASN1_ERR_NOERROR)
581 while (asn1->offset < eoc) {
582 if (++len > sizeof (guint32))
583 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
584 ret = asn1_octet_decode (asn1, &ch);
585 if (ret != ASN1_ERR_NOERROR)
590 return ASN1_ERR_NOERROR;
594 * NAME: asn1_uint32_decode [API]
595 * SYNOPSIS: int asn1_uint32_decode
601 * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
603 * asn1: pointer to ASN1 socket.
605 * nbytes: number of bytes used to encode it.
606 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
609 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
619 start = asn1->offset;
620 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
621 if (ret != ASN1_ERR_NOERROR)
623 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
624 ret = ASN1_ERR_WRONG_TYPE;
628 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
631 ret = asn1_uint32_value_decode (asn1, enc_len, integer);
634 *nbytes = asn1->offset - start;
639 * NAME: asn1_bits_decode [API]
640 * SYNOPSIS: int asn1_bits_decode
649 * DESCRIPTION: Decodes Bit String.
651 * asn1: pointer to ASN1 socket.
652 * enc_len: length of value.
653 * bits: pointer to variable we set to point to strring
654 * len: Size of Bit String in characters.
655 * unused: Number of unused bits in last character.
656 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
659 asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits,
660 guint *len, guchar *unused)
666 eoc = asn1->offset + enc_len;
668 ret = asn1_octet_decode (asn1, unused);
669 if (ret != ASN1_ERR_NOERROR)
674 * First, make sure the entire string is in the tvbuff, and throw
675 * an exception if it isn't. If the length is bogus, this should
676 * keep us from trying to allocate an immensely large buffer.
677 * (It won't help if the length is *valid* but immensely large,
678 * but that's another matter; in any case, that would happen only
679 * if we had an immensely large tvbuff....)
682 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
683 *bits = g_malloc (enc_len);
686 * If the length is 0, we allocate a 1-byte buffer, as
687 * "g_malloc()" returns NULL if passed 0 as an argument,
688 * and our caller expects us to return a pointer to a
691 *bits = g_malloc (1);
695 while (asn1->offset < eoc) {
696 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
697 if (ret != ASN1_ERR_NOERROR) {
704 return ASN1_ERR_NOERROR;
708 * NAME: asn1_string_value_decode [API]
709 * SYNOPSIS: int asn1_string_value_decode
715 * DESCRIPTION: Decodes value portion of string (Octet String, various
716 * character string types)
718 * asn1: pointer to ASN1 socket.
719 * enc_len: length of encoding of value.
720 * octets: pointer to variable we set to point to string,
721 * which is '\0' terminated for ease of use as C-string
722 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
725 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
732 * First, make sure the entire string is in the tvbuff, and throw
733 * an exception if it isn't. If the length is bogus, this should
734 * keep us from trying to allocate an immensely large buffer.
735 * (It won't help if the length is *valid* but immensely large,
736 * but that's another matter; in any case, that would happen only
737 * if we had an immensely large tvbuff....)
740 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
741 *octets = g_malloc (enc_len+1);
743 eoc = asn1->offset + enc_len;
745 while (asn1->offset < eoc) {
746 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
747 if (ret != ASN1_ERR_NOERROR) {
753 *(guchar *)ptr = '\0';
754 return ASN1_ERR_NOERROR;
758 * NAME: asn1_string_decode [API]
759 * SYNOPSIS: int asn1_string_decode
767 * DESCRIPTION: Decodes string (Octet String, various character string
770 * asn1: pointer to ASN1 socket.
771 * octets: pointer to variable we set to point to string.
772 * str_len: length of octet_string.
773 * nbytes: number of bytes used to encode.
774 * expected_tag: tag expected for this type of string.
775 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
778 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
779 guint *nbytes, guint expected_tag)
789 start = asn1->offset;
790 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
791 if (ret != ASN1_ERR_NOERROR)
793 if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
794 /* XXX - handle the constructed encoding? */
795 ret = ASN1_ERR_WRONG_TYPE;
799 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
803 ret = asn1_string_value_decode (asn1, enc_len, octets);
807 *nbytes = asn1->offset - start;
812 * NAME: asn1_octet_string_decode [API]
813 * SYNOPSIS: int asn1_octet_string_decode
820 * DESCRIPTION: Decodes Octet String.
822 * asn1: pointer to ASN1 socket.
823 * octets: pointer to variable we set to point to string.
824 * str_len: length of octet_string.
825 * nbytes: number of bytes used to encode.
826 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
829 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
832 return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
836 * NAME: asn1_subid_decode
837 * SYNOPSIS: int asn1_subid_decode
842 * DESCRIPTION: Decodes Sub Identifier.
844 * asn1: pointer to ASN1 socket.
845 * subid: Sub Identifier.
846 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
849 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
856 ret = asn1_octet_decode(asn1, &ch);
857 if (ret != ASN1_ERR_NOERROR)
861 } while ((ch & 0x80) == 0x80);
862 return ASN1_ERR_NOERROR;
866 * NAME: asn1_oid_value_decode [API]
867 * SYNOPSIS: int asn1_oid_value_decode
874 * DESCRIPTION: Decodes value portion of Object Identifier.
876 * asn1: pointer to ASN1 socket.
877 * enc_len: length of encoding of value.
878 * oid: pointer to variable we set to Object Identifier.
879 * len: Length of Object Identifier in gulongs.
880 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
883 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
892 * First, make sure the entire string is in the tvbuff, and throw
893 * an exception if it isn't. If the length is bogus, this should
894 * keep us from trying to allocate an immensely large buffer.
895 * (It won't help if the length is *valid* but immensely large,
896 * but that's another matter; in any case, that would happen only
897 * if we had an immensely large tvbuff....)
901 return ASN1_ERR_LENGTH_MISMATCH;
903 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
905 eoc = asn1->offset + enc_len;
908 *oid = g_malloc(size * sizeof(gulong));
911 ret = asn1_subid_decode (asn1, &subid);
912 if (ret != ASN1_ERR_NOERROR) {
920 } else if (subid < 80) {
922 optr[1] = subid - 40;
925 optr[1] = subid - 80;
929 while (asn1->offset < eoc) {
930 if (++(*len) > size) {
933 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
935 ret = asn1_subid_decode (asn1, optr++);
936 if (ret != ASN1_ERR_NOERROR) {
942 return ASN1_ERR_NOERROR;
946 * NAME: asn1_oid_decode [API]
947 * SYNOPSIS: int asn1_oid_decode
954 * DESCRIPTION: Decodes Object Identifier.
956 * asn1: pointer to ASN1 socket.
957 * oid: pointer to variable we set to Object Identifier.
958 * len: Length of Object Identifier in gulongs.
959 * nbytes: number of bytes used to encode.
960 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
963 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
973 start = asn1->offset;
974 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
975 if (ret != ASN1_ERR_NOERROR)
977 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
978 ret = ASN1_ERR_WRONG_TYPE;
982 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
986 ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
989 *nbytes = asn1->offset - start;
994 * NAME: asn1_sequence_decode [API]
995 * SYNOPSIS: int asn1_sequence_decode
1001 * DESCRIPTION: Decodes header for SEQUENCE.
1003 * asn1: pointer to ASN1 socket.
1004 * seq_len: length of sequence.
1005 * nbytes: number of bytes used to encode header.
1006 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
1009 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
1018 start = asn1->offset;
1019 ret = asn1_header_decode(asn1, &cls, &con, &tag,
1021 if (ret != ASN1_ERR_NOERROR)
1023 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
1024 ret = ASN1_ERR_WRONG_TYPE;
1028 /* XXX - might some sequences have an indefinite length? */
1029 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
1032 ret = ASN1_ERR_NOERROR;
1035 *nbytes = asn1->offset - start;
1040 * NAME: asn1_err_to_str [API]
1041 * SYNOPSIS: const char *asn1_err_to_str
1045 * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
1047 * err: the error code
1048 * RETURNS: string for the error
1051 asn1_err_to_str(int err)
1054 char errstrbuf[14+1+1+11+1+1]; /* "Unknown error (%d)\0" */
1058 case ASN1_ERR_EOC_MISMATCH:
1059 errstr = "EOC mismatch";
1062 case ASN1_ERR_WRONG_TYPE:
1063 errstr = "Wrong type for that item";
1066 case ASN1_ERR_LENGTH_NOT_DEFINITE:
1067 errstr = "Length was indefinite";
1070 case ASN1_ERR_LENGTH_MISMATCH:
1071 errstr = "Length mismatch";
1074 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1075 errstr = "Wrong length for that item's type";
1079 g_snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);