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 #ifdef NEED_SNPRINTF_H
70 # include "snprintf.h"
73 #include <epan/tvbuff.h>
77 * NAME: asn1_open [API]
78 * SYNOPSIS: void asn1_open
84 * DESCRIPTION: Opens an ASN1 socket.
86 * asn1: pointer to ASN1 socket.
87 * tvb: Tvbuff for encoding.
88 * offset: Current offset in tvbuff.
89 * Encoding starts at the end of the buffer, and
90 * proceeds to the beginning.
95 asn1_open(ASN1_SCK *asn1, tvbuff_t *tvb, int offset)
98 asn1->offset = offset;
102 * NAME: asn1_close [API]
103 * SYNOPSIS: void asn1_close
108 * DESCRIPTION: Closes an ASN1 socket.
110 * asn1: pointer to ASN1 socket.
111 * offset: pointer to variable into which current offset is
117 asn1_close(ASN1_SCK *asn1, int *offset)
119 *offset = asn1->offset;
123 * NAME: asn1_octet_decode
124 * SYNOPSIS: int asn1_octet_decode
129 * DESCRIPTION: Decodes an octet.
130 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
133 asn1_octet_decode(ASN1_SCK *asn1, guchar *ch)
135 *ch = tvb_get_guint8(asn1->tvb, asn1->offset);
137 return ASN1_ERR_NOERROR;
142 * SYNOPSIS: int asn1_tag_get
147 * DESCRIPTION: Decodes a tag number, combining it with existing tag bits.
148 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
151 asn1_tag_get(ASN1_SCK *asn1, guint *tag)
157 ret = asn1_octet_decode (asn1, &ch);
158 if (ret != ASN1_ERR_NOERROR)
162 } while ((ch & 0x80) == 0x80);
163 return ASN1_ERR_NOERROR;
167 * NAME: asn1_tag_decode
168 * SYNOPSIS: int asn1_tag_decode
173 * DESCRIPTION: Decodes a tag number.
174 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
177 asn1_tag_decode(ASN1_SCK *asn1, guint *tag)
180 return asn1_tag_get(asn1, tag);
184 * NAME: asn1_id_decode
185 * SYNOPSIS: int asn1_id_decode
192 * DESCRIPTION: Decodes an identifier.
193 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
196 asn1_id_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag)
202 ret = asn1_octet_decode (asn1, &ch);
203 if (ret != ASN1_ERR_NOERROR)
205 *cls = (ch & 0xC0) >> 6;
206 *con = (ch & 0x20) >> 5;
209 ret = asn1_tag_decode (asn1, tag);
210 if (ret != ASN1_ERR_NOERROR)
213 return ASN1_ERR_NOERROR;
217 * NAME: asn1_id_decode1
218 * SYNOPSIS: int asn1_id_decode1
223 * DESCRIPTION: Decodes an identifier.
224 * Like asn1_id_decode() except that the Class and Constructor
225 * bits are returned in the tag.
226 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
229 asn1_id_decode1(ASN1_SCK *asn1, guint *tag)
235 ret = asn1_octet_decode (asn1, &ch);
236 if (ret != ASN1_ERR_NOERROR)
240 if ((*tag & 0x1F) == 0x1F) { /* high-tag-number format */
241 *tag = ch >> 5; /* leave just the Class and Constructor bits */
242 ret = asn1_tag_get (asn1, tag);
243 if (ret != ASN1_ERR_NOERROR)
246 return ASN1_ERR_NOERROR;
250 * NAME: asn1_length_decode
251 * SYNOPSIS: int asn1_length_decode
257 * DESCRIPTION: Decodes an ASN1 length.
259 * asn1: pointer to ASN1 socket.
260 * def: Boolean - TRUE if length definite, FALSE if not
261 * len: length, if length is definite
262 * DESCRIPTION: Decodes a definite or indefinite length.
263 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
266 asn1_length_decode(ASN1_SCK *asn1, gboolean *def, guint *len)
271 ret = asn1_octet_decode (asn1, &ch);
272 if (ret != ASN1_ERR_NOERROR)
275 *def = FALSE; /* indefinite length */
277 *def = TRUE; /* definite length */
281 cnt = (guchar) (ch & 0x7F);
284 ret = asn1_octet_decode (asn1, &ch);
285 if (ret != ASN1_ERR_NOERROR)
293 return ASN1_ERR_NOERROR;
297 * NAME: asn1_header_decode [API]
298 * SYNOPSIS: int asn1_header_decode
307 * DESCRIPTION: Decodes an ASN1 header.
309 * asn1: pointer to ASN1 socket.
310 * cls: Class (see asn1.h)
311 * con: Primitive, Constructed (ASN1_PRI, ASN1_CON)
312 * tag: Tag (see asn1.h)
313 * defp: Boolean - TRUE if length definite, FALSE if not
314 * lenp: length, if length is definite
315 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
318 asn1_header_decode(ASN1_SCK *asn1, guint *cls, guint *con, guint *tag,
319 gboolean *defp, guint *lenp)
324 ret = asn1_id_decode (asn1, cls, con, tag);
325 if (ret != ASN1_ERR_NOERROR)
327 ret = asn1_length_decode (asn1, &def, &len);
328 if (ret != ASN1_ERR_NOERROR)
332 return ASN1_ERR_NOERROR;
337 * NAME: asn1_eoc [API]
338 * SYNOPSIS: gboolean asn1_eoc
343 * DESCRIPTION: Checks if decoding is at End Of Contents.
345 * asn1: pointer to ASN1 socket.
346 * eoc: offset of end of encoding, or -1 if indefinite.
347 * RETURNS: gboolean success
350 asn1_eoc ( ASN1_SCK *asn1, int eoc)
353 return (tvb_get_guint8(asn1->tvb, asn1->offset) == 0x00
354 && tvb_get_guint8(asn1->tvb, asn1->offset + 1) == 0x00);
356 return (asn1->offset >= eoc);
360 * NAME: asn1_eoc_decode [API]
361 * SYNOPSIS: int asn1_eoc_decode
366 * DESCRIPTION: Decodes End Of Contents.
368 * asn1: pointer to ASN1 socket.
369 * eoc: offset of end of encoding, or -1 if indefinite.
370 * If eoc is -1 it decodes an ASN1 End Of
371 * Contents (0x00 0x00), so it has to be an
372 * indefinite length encoding. If eoc is a non-negative
373 * integer, it probably was filled by asn1_header_decode,
374 * and should refer to the octet after the last of the encoding.
375 * It is checked if this offset refers to the octet to be
376 * decoded. This only takes place in decoding a
377 * definite length encoding.
378 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
381 asn1_eoc_decode (ASN1_SCK *asn1, int eoc)
387 ret = asn1_octet_decode (asn1, &ch);
388 if (ret != ASN1_ERR_NOERROR)
391 return ASN1_ERR_EOC_MISMATCH;
392 ret = asn1_octet_decode (asn1, &ch);
393 if (ret != ASN1_ERR_NOERROR)
396 return ASN1_ERR_EOC_MISMATCH;
397 return ASN1_ERR_NOERROR;
399 if (asn1->offset != eoc)
400 return ASN1_ERR_LENGTH_MISMATCH;
401 return ASN1_ERR_NOERROR;
406 * NAME: asn1_null_decode [API]
407 * SYNOPSIS: int asn1_null_decode
412 * DESCRIPTION: Decodes Null.
414 * asn1: pointer to ASN1 socket.
415 * enc_len: length of encoding of value.
416 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
419 asn1_null_decode ( ASN1_SCK *asn1, int enc_len)
421 int start_off = asn1->offset;
423 asn1->offset += enc_len;
425 * Check for integer overflows.
426 * XXX - ASN1_ERR_LENGTH_MISMATCH seemed like the most appropriate
427 * error from the ones available. Should we make a new one?
429 if (asn1->offset < 0 || asn1->offset < start_off)
430 return ASN1_ERR_LENGTH_MISMATCH;
432 return ASN1_ERR_NOERROR;
436 * NAME: asn1_bool_decode [API]
437 * SYNOPSIS: int asn1_bool_decode
443 * DESCRIPTION: Decodes Boolean.
445 * asn1: pointer to ASN1 socket.
446 * enc_len: length of encoding of value.
447 * bool: False, True (0, !0).
448 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
451 asn1_bool_decode ( ASN1_SCK *asn1, int enc_len, gboolean *boolean)
457 return ASN1_ERR_LENGTH_MISMATCH;
458 ret = asn1_octet_decode (asn1, &ch);
459 if (ret != ASN1_ERR_NOERROR)
461 *boolean = ch ? TRUE : FALSE;
462 return ASN1_ERR_NOERROR;
466 * NAME: asn1_int32_value_decode [API]
467 * SYNOPSIS: int asn1_int32_value_decode
473 * DESCRIPTION: Decodes value portion of Integer (which must be no more
476 * asn1: pointer to ASN1 socket.
477 * enc_len: length of encoding of value.
479 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
482 asn1_int32_value_decode ( ASN1_SCK *asn1, int enc_len, gint32 *integer)
489 eoc = asn1->offset + enc_len;
490 ret = asn1_octet_decode (asn1, &ch);
491 if (ret != ASN1_ERR_NOERROR)
493 *integer = (gint) ch;
495 while (asn1->offset < eoc) {
496 if (++len > sizeof (gint32))
497 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
498 ret = asn1_octet_decode (asn1, &ch);
499 if (ret != ASN1_ERR_NOERROR)
504 return ASN1_ERR_NOERROR;
508 * NAME: asn1_int32_decode [API]
509 * SYNOPSIS: int asn1_int32_decode
515 * DESCRIPTION: Decodes Integer (which must be no more than 32 bits).
517 * asn1: pointer to ASN1 socket.
519 * nbytes: number of bytes used to encode it.
520 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
523 asn1_int32_decode ( ASN1_SCK *asn1, gint32 *integer, guint *nbytes)
533 start = asn1->offset;
534 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
535 if (ret != ASN1_ERR_NOERROR)
537 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
538 ret = ASN1_ERR_WRONG_TYPE;
542 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
545 ret = asn1_int32_value_decode (asn1, enc_len, integer);
548 *nbytes = asn1->offset - start;
553 * NAME: asn1_uint32_value_decode [API]
554 * SYNOPSIS: int asn1_uint32_value_decode
560 * DESCRIPTION: Decodes value part of Unsigned Integer (which must be no
561 * more than 32 bits).
563 * asn1: pointer to ASN1 socket.
564 * enc_len: length of encoding of value.
566 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
569 asn1_uint32_value_decode ( ASN1_SCK *asn1, int enc_len, guint32 *integer)
576 eoc = asn1->offset + enc_len;
577 ret = asn1_octet_decode (asn1, &ch);
578 if (ret != ASN1_ERR_NOERROR)
585 while (asn1->offset < eoc) {
586 if (++len > sizeof (guint32))
587 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
588 ret = asn1_octet_decode (asn1, &ch);
589 if (ret != ASN1_ERR_NOERROR)
594 return ASN1_ERR_NOERROR;
598 * NAME: asn1_uint32_decode [API]
599 * SYNOPSIS: int asn1_uint32_decode
605 * DESCRIPTION: Decodes Unsigned Integer (which must be no more than 32 bits).
607 * asn1: pointer to ASN1 socket.
609 * nbytes: number of bytes used to encode it.
610 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
613 asn1_uint32_decode ( ASN1_SCK *asn1, guint32 *integer, guint *nbytes)
623 start = asn1->offset;
624 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
625 if (ret != ASN1_ERR_NOERROR)
627 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_INT) {
628 ret = ASN1_ERR_WRONG_TYPE;
632 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
635 ret = asn1_uint32_value_decode (asn1, enc_len, integer);
638 *nbytes = asn1->offset - start;
643 * NAME: asn1_bits_decode [API]
644 * SYNOPSIS: int asn1_bits_decode
653 * DESCRIPTION: Decodes Bit String.
655 * asn1: pointer to ASN1 socket.
656 * enc_len: length of value.
657 * bits: pointer to variable we set to point to strring
658 * len: Size of Bit String in characters.
659 * unused: Number of unused bits in last character.
660 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
663 asn1_bits_decode ( ASN1_SCK *asn1, int enc_len, guchar **bits,
664 guint *len, guchar *unused)
670 eoc = asn1->offset + enc_len;
672 ret = asn1_octet_decode (asn1, unused);
673 if (ret != ASN1_ERR_NOERROR)
678 * First, make sure the entire string is in the tvbuff, and throw
679 * an exception if it isn't. If the length is bogus, this should
680 * keep us from trying to allocate an immensely large buffer.
681 * (It won't help if the length is *valid* but immensely large,
682 * but that's another matter; in any case, that would happen only
683 * if we had an immensely large tvbuff....)
686 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
687 *bits = g_malloc (enc_len);
690 * If the length is 0, we allocate a 1-byte buffer, as
691 * "g_malloc()" returns NULL if passed 0 as an argument,
692 * and our caller expects us to return a pointer to a
695 *bits = g_malloc (1);
699 while (asn1->offset < eoc) {
700 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
701 if (ret != ASN1_ERR_NOERROR) {
708 return ASN1_ERR_NOERROR;
712 * NAME: asn1_string_value_decode [API]
713 * SYNOPSIS: int asn1_string_value_decode
719 * DESCRIPTION: Decodes value portion of string (Octet String, various
720 * character string types)
722 * asn1: pointer to ASN1 socket.
723 * enc_len: length of encoding of value.
724 * octets: pointer to variable we set to point to string,
725 * which is '\0' terminated for ease of use as C-string
726 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
729 asn1_string_value_decode ( ASN1_SCK *asn1, int enc_len, guchar **octets)
736 * First, make sure the entire string is in the tvbuff, and throw
737 * an exception if it isn't. If the length is bogus, this should
738 * keep us from trying to allocate an immensely large buffer.
739 * (It won't help if the length is *valid* but immensely large,
740 * but that's another matter; in any case, that would happen only
741 * if we had an immensely large tvbuff....)
744 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
745 *octets = g_malloc (enc_len+1);
747 eoc = asn1->offset + enc_len;
749 while (asn1->offset < eoc) {
750 ret = asn1_octet_decode (asn1, (guchar *)ptr++);
751 if (ret != ASN1_ERR_NOERROR) {
757 *(guchar *)ptr = '\0';
758 return ASN1_ERR_NOERROR;
762 * NAME: asn1_string_decode [API]
763 * SYNOPSIS: int asn1_string_decode
771 * DESCRIPTION: Decodes string (Octet String, various character string
774 * asn1: pointer to ASN1 socket.
775 * octets: pointer to variable we set to point to string.
776 * str_len: length of octet_string.
777 * nbytes: number of bytes used to encode.
778 * expected_tag: tag expected for this type of string.
779 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
782 asn1_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
783 guint *nbytes, guint expected_tag)
793 start = asn1->offset;
794 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
795 if (ret != ASN1_ERR_NOERROR)
797 if (cls != ASN1_UNI || con != ASN1_PRI || tag != expected_tag) {
798 /* XXX - handle the constructed encoding? */
799 ret = ASN1_ERR_WRONG_TYPE;
803 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
807 ret = asn1_string_value_decode (asn1, enc_len, octets);
811 *nbytes = asn1->offset - start;
816 * NAME: asn1_octet_string_decode [API]
817 * SYNOPSIS: int asn1_octet_string_decode
824 * DESCRIPTION: Decodes Octet String.
826 * asn1: pointer to ASN1 socket.
827 * octets: pointer to variable we set to point to string.
828 * str_len: length of octet_string.
829 * nbytes: number of bytes used to encode.
830 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
833 asn1_octet_string_decode ( ASN1_SCK *asn1, guchar **octets, guint *str_len,
836 return asn1_string_decode(asn1, octets, str_len, nbytes, ASN1_OTS);
840 * NAME: asn1_subid_decode
841 * SYNOPSIS: int asn1_subid_decode
846 * DESCRIPTION: Decodes Sub Identifier.
848 * asn1: pointer to ASN1 socket.
849 * subid: Sub Identifier.
850 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
853 asn1_subid_decode ( ASN1_SCK *asn1, subid_t *subid)
860 ret = asn1_octet_decode(asn1, &ch);
861 if (ret != ASN1_ERR_NOERROR)
865 } while ((ch & 0x80) == 0x80);
866 return ASN1_ERR_NOERROR;
870 * NAME: asn1_oid_value_decode [API]
871 * SYNOPSIS: int asn1_oid_value_decode
878 * DESCRIPTION: Decodes value portion of Object Identifier.
880 * asn1: pointer to ASN1 socket.
881 * enc_len: length of encoding of value.
882 * oid: pointer to variable we set to Object Identifier.
883 * len: Length of Object Identifier in gulongs.
884 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
887 asn1_oid_value_decode ( ASN1_SCK *asn1, int enc_len, subid_t **oid, guint *len)
896 * First, make sure the entire string is in the tvbuff, and throw
897 * an exception if it isn't. If the length is bogus, this should
898 * keep us from trying to allocate an immensely large buffer.
899 * (It won't help if the length is *valid* but immensely large,
900 * but that's another matter; in any case, that would happen only
901 * if we had an immensely large tvbuff....)
904 tvb_ensure_bytes_exist(asn1->tvb, asn1->offset, enc_len);
906 eoc = asn1->offset + enc_len;
909 *oid = g_malloc(size * sizeof(gulong));
912 ret = asn1_subid_decode (asn1, &subid);
913 if (ret != ASN1_ERR_NOERROR) {
921 } else if (subid < 80) {
923 optr[1] = subid - 40;
926 optr[1] = subid - 80;
930 while (asn1->offset < eoc) {
931 if (++(*len) > size) {
934 return ASN1_ERR_WRONG_LENGTH_FOR_TYPE;
936 ret = asn1_subid_decode (asn1, optr++);
937 if (ret != ASN1_ERR_NOERROR) {
943 return ASN1_ERR_NOERROR;
947 * NAME: asn1_oid_decode [API]
948 * SYNOPSIS: int asn1_oid_decode
955 * DESCRIPTION: Decodes Object Identifier.
957 * asn1: pointer to ASN1 socket.
958 * oid: pointer to variable we set to Object Identifier.
959 * len: Length of Object Identifier in gulongs.
960 * nbytes: number of bytes used to encode.
961 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
964 asn1_oid_decode ( ASN1_SCK *asn1, subid_t **oid, guint *len, guint *nbytes)
974 start = asn1->offset;
975 ret = asn1_header_decode (asn1, &cls, &con, &tag, &def, &enc_len);
976 if (ret != ASN1_ERR_NOERROR)
978 if (cls != ASN1_UNI || con != ASN1_PRI || tag != ASN1_OJI) {
979 ret = ASN1_ERR_WRONG_TYPE;
983 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
987 ret = asn1_oid_value_decode (asn1, enc_len, oid, len);
990 *nbytes = asn1->offset - start;
995 * NAME: asn1_sequence_decode [API]
996 * SYNOPSIS: int asn1_sequence_decode
1002 * DESCRIPTION: Decodes header for SEQUENCE.
1004 * asn1: pointer to ASN1 socket.
1005 * seq_len: length of sequence.
1006 * nbytes: number of bytes used to encode header.
1007 * RETURNS: ASN1_ERR value (ASN1_ERR_NOERROR on success)
1010 asn1_sequence_decode ( ASN1_SCK *asn1, guint *seq_len, guint *nbytes)
1019 start = asn1->offset;
1020 ret = asn1_header_decode(asn1, &cls, &con, &tag,
1022 if (ret != ASN1_ERR_NOERROR)
1024 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) {
1025 ret = ASN1_ERR_WRONG_TYPE;
1029 /* XXX - might some sequences have an indefinite length? */
1030 ret = ASN1_ERR_LENGTH_NOT_DEFINITE;
1033 ret = ASN1_ERR_NOERROR;
1036 *nbytes = asn1->offset - start;
1041 * NAME: asn1_err_to_str [API]
1042 * SYNOPSIS: char *asn1_err_to_str
1046 * DESCRIPTION: Returns the string corresponding to an ASN.1 library error.
1048 * err: the error code
1049 * RETURNS: string for the error
1052 asn1_err_to_str(int err)
1055 char errstrbuf[14+1+1+11+1+1]; /* "Unknown error (%d)\0" */
1059 case ASN1_ERR_EOC_MISMATCH:
1060 errstr = "EOC mismatch";
1063 case ASN1_ERR_WRONG_TYPE:
1064 errstr = "Wrong type for that item";
1067 case ASN1_ERR_LENGTH_NOT_DEFINITE:
1068 errstr = "Length was indefinite";
1071 case ASN1_ERR_LENGTH_MISMATCH:
1072 errstr = "Length mismatch";
1075 case ASN1_ERR_WRONG_LENGTH_FOR_TYPE:
1076 errstr = "Wrong length for that item's type";
1080 snprintf(errstrbuf, sizeof errstrbuf, "Unknown error (%d)", err);