#include <stddef.h>
#include <openssl/asn1.h>
#define ASN1_ENCODING_CONSTRUCTED_ONLY 1
#define ASN1_ENCODING_PRIMITIVE_ONLY 2
struct asn1_type {
const char *name;
uint32_t bit_value;
int char_width;
int encoding;
};
static const struct asn1_type asn1_types[31] = {
[0] = {
.name = "EOC",
.bit_value = 0,
.char_width = -1,
},
[1] = {
.name = "BOOLEAN",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[2] = {
.name = "INTEGER",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[3] = {
.name = "BIT STRING",
.bit_value = B_ASN1_BIT_STRING,
.char_width = -1,
},
[4] = {
.name = "OCTET STRING",
.bit_value = B_ASN1_OCTET_STRING,
.char_width = -1,
},
[5] = {
.name = "NULL",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[6] = {
.name = "OBJECT",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[7] = {
.name = "OBJECT DESCRIPTOR",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[8] = {
.name = "EXTERNAL",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[9] = {
.name = "REAL",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[10] = {
.name = "ENUMERATED",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[11] = {
.name = "<ASN1 11 EMBEDDED PDV>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[12] = {
.name = "UTF8STRING",
.bit_value = B_ASN1_UTF8STRING,
.char_width = 0,
},
[13] = {
.name = "<ASN1 13 RELATIVE OID>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[14] = {
.name = "<ASN1 14 TIME>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
.encoding = ASN1_ENCODING_PRIMITIVE_ONLY,
},
[15] = {
.name = "<ASN1 15 RESERVED>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[16] = {
.name = "SEQUENCE",
.bit_value = B_ASN1_SEQUENCE,
.char_width = -1,
.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
},
[17] = {
.name = "SET",
.bit_value = 0,
.char_width = -1,
.encoding = ASN1_ENCODING_CONSTRUCTED_ONLY,
},
[18] = {
.name = "NUMERICSTRING",
.bit_value = B_ASN1_NUMERICSTRING,
.char_width = -1,
},
[19] = {
.name = "PRINTABLESTRING",
.bit_value = B_ASN1_PRINTABLESTRING,
.char_width = 1,
},
[20] = {
.name = "T61STRING",
.bit_value = B_ASN1_T61STRING,
.char_width = 1,
},
[21] = {
.name = "VIDEOTEXSTRING",
.bit_value = B_ASN1_VIDEOTEXSTRING,
.char_width = -1,
},
[22] = {
.name = "IA5STRING",
.bit_value = B_ASN1_IA5STRING,
.char_width = 1,
},
[23] = {
.name = "UTCTIME",
.bit_value = B_ASN1_UTCTIME,
.char_width = 1,
},
[24] = {
.name = "GENERALIZEDTIME",
.bit_value = B_ASN1_GENERALIZEDTIME,
.char_width = 1,
},
[25] = {
.name = "GRAPHICSTRING",
.bit_value = B_ASN1_GRAPHICSTRING,
.char_width = -1,
},
[26] = {
.name = "VISIBLESTRING",
.bit_value = B_ASN1_ISO64STRING,
.char_width = 1,
},
[27] = {
.name = "GENERALSTRING",
.bit_value = B_ASN1_GENERALSTRING,
.char_width = -1,
},
[28] = {
.name = "UNIVERSALSTRING",
.bit_value = B_ASN1_UNIVERSALSTRING,
.char_width = 4,
},
[29] = {
.name = "<ASN1 29>",
.bit_value = B_ASN1_UNKNOWN,
.char_width = -1,
},
[30] = {
.name = "BMPSTRING",
.bit_value = B_ASN1_BMPSTRING,
.char_width = 2,
},
};
static const struct asn1_type *
asn1_type_by_tag(int tag)
{
if (tag < 0 || tag > 30)
return NULL;
return &asn1_types[tag];
}
int
asn1_must_be_constructed(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY;
return 0;
}
int
asn1_must_be_primitive(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY;
return 0;
}
int
asn1_tag2charwidth(int tag)
{
const struct asn1_type *at;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->char_width;
return -1;
}
unsigned long
ASN1_tag2bit(int tag)
{
const struct asn1_type *at;
if ((at = asn1_type_by_tag(tag)) != NULL)
return (unsigned long)at->bit_value;
return 0;
}
LCRYPTO_ALIAS(ASN1_tag2bit);
const char *
ASN1_tag2str(int tag)
{
const struct asn1_type *at;
if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED)
tag &= ~V_ASN1_NEG;
if ((at = asn1_type_by_tag(tag)) != NULL)
return at->name;
return "(unknown)";
}
LCRYPTO_ALIAS(ASN1_tag2str);