1 /* $OpenBSD: asn1_types.c,v 1.2 2022/09/03 18:52:18 jsing Exp $ */ 2 /* 3 * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stddef.h> 19 20 #include <openssl/asn1.h> 21 22 #define ASN1_ENCODING_CONSTRUCTED_ONLY 1 23 #define ASN1_ENCODING_PRIMITIVE_ONLY 2 24 25 struct asn1_type { 26 const char *name; 27 uint32_t bit_value; 28 int char_width; 29 int encoding; 30 }; 31 32 /* 33 * Universal class tag types - ITU X.680. 34 */ 35 static const struct asn1_type asn1_types[31] = { 36 [0] = { 37 /* Tag 0 (0x00) - Reserved for use by encoding rules */ 38 .name = "EOC", 39 .bit_value = 0, 40 .char_width = -1, 41 }, 42 [1] = { 43 /* Tag 1 (0x01) - Boolean */ 44 .name = "BOOLEAN", 45 .bit_value = 0, 46 .char_width = -1, 47 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 48 }, 49 [2] = { 50 /* Tag 2 (0x02) - Integer */ 51 .name = "INTEGER", 52 .bit_value = 0, 53 .char_width = -1, 54 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 55 }, 56 [3] = { 57 /* Tag 3 (0x03) - BitString */ 58 .name = "BIT STRING", 59 .bit_value = B_ASN1_BIT_STRING, 60 .char_width = -1, 61 }, 62 [4] = { 63 /* Tag 4 (0x04) - OctetString */ 64 .name = "OCTET STRING", 65 .bit_value = B_ASN1_OCTET_STRING, 66 .char_width = -1, 67 }, 68 [5] = { 69 /* Tag 5 (0x05) - Null */ 70 .name = "NULL", 71 .bit_value = 0, 72 .char_width = -1, 73 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 74 }, 75 [6] = { 76 /* Tag 6 (0x06) - Object Identifier */ 77 .name = "OBJECT", 78 .bit_value = 0, 79 .char_width = -1, 80 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 81 }, 82 [7] = { 83 /* Tag 7 (0x07) - Object Descriptor */ 84 .name = "OBJECT DESCRIPTOR", 85 .bit_value = B_ASN1_UNKNOWN, 86 .char_width = -1, 87 }, 88 [8] = { 89 /* Tag 8 (0x08) - External */ 90 .name = "EXTERNAL", 91 .bit_value = B_ASN1_UNKNOWN, 92 .char_width = -1, 93 }, 94 [9] = { 95 /* Tag 9 (0x09) - Real */ 96 .name = "REAL", 97 .bit_value = B_ASN1_UNKNOWN, 98 .char_width = -1, 99 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 100 }, 101 [10] = { 102 /* Tag 10 (0x0a) - Enumerated */ 103 .name = "ENUMERATED", 104 .bit_value = B_ASN1_UNKNOWN, 105 .char_width = -1, 106 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 107 }, 108 [11] = { 109 /* Tag 11 (0x0b) - Embedded PDV */ 110 .name = "<ASN1 11 EMBEDDED PDV>", 111 .bit_value = B_ASN1_UNKNOWN, 112 .char_width = -1, 113 }, 114 [12] = { 115 /* Tag 12 (0x0c) - UTF8String */ 116 .name = "UTF8STRING", 117 .bit_value = B_ASN1_UTF8STRING, 118 .char_width = 0, 119 }, 120 [13] = { 121 /* Tag 13 (0x0d) - Relative Object Identifier */ 122 .name = "<ASN1 13 RELATIVE OID>", 123 .bit_value = B_ASN1_UNKNOWN, 124 .char_width = -1, 125 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 126 }, 127 [14] = { 128 /* Tag 14 (0x0e) - Time */ 129 .name = "<ASN1 14 TIME>", 130 .bit_value = B_ASN1_UNKNOWN, 131 .char_width = -1, 132 .encoding = ASN1_ENCODING_PRIMITIVE_ONLY, 133 }, 134 [15] = { 135 /* Tag 15 (0x0f) - Reserved */ 136 .name = "<ASN1 15 RESERVED>", 137 .bit_value = B_ASN1_UNKNOWN, 138 .char_width = -1, 139 }, 140 [16] = { 141 /* Tag 16 (0x10)- Sequence */ 142 .name = "SEQUENCE", 143 .bit_value = B_ASN1_SEQUENCE, 144 .char_width = -1, 145 .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, 146 }, 147 [17] = { 148 /* Tag 17 (0x11) - Set */ 149 .name = "SET", 150 .bit_value = 0, 151 .char_width = -1, 152 .encoding = ASN1_ENCODING_CONSTRUCTED_ONLY, 153 }, 154 [18] = { 155 /* Tag 18 (0x12) - NumericString */ 156 .name = "NUMERICSTRING", 157 .bit_value = B_ASN1_NUMERICSTRING, 158 .char_width = -1, 159 }, 160 [19] = { 161 /* Tag 19 (0x13) - PrintableString */ 162 .name = "PRINTABLESTRING", 163 .bit_value = B_ASN1_PRINTABLESTRING, 164 .char_width = 1, 165 }, 166 [20] = { 167 /* Tag 20 (0x14) - TeletexString (T61String) */ 168 .name = "T61STRING", 169 .bit_value = B_ASN1_T61STRING, 170 .char_width = 1, 171 }, 172 [21] = { 173 /* Tag 21 (0x15) - VideotexString */ 174 .name = "VIDEOTEXSTRING", 175 .bit_value = B_ASN1_VIDEOTEXSTRING, 176 .char_width = -1, 177 }, 178 [22] = { 179 /* Tag 22 (0x16) - IA5String */ 180 .name = "IA5STRING", 181 .bit_value = B_ASN1_IA5STRING, 182 .char_width = 1, 183 }, 184 [23] = { 185 /* Tag 23 (0x17) - UTCTime */ 186 .name = "UTCTIME", 187 .bit_value = B_ASN1_UTCTIME, 188 .char_width = 1, 189 }, 190 [24] = { 191 /* Tag 24 (0x18) - GeneralizedTime */ 192 .name = "GENERALIZEDTIME", 193 .bit_value = B_ASN1_GENERALIZEDTIME, 194 .char_width = 1, 195 }, 196 [25] = { 197 /* Tag 25 (0x19) - GraphicString */ 198 .name = "GRAPHICSTRING", 199 .bit_value = B_ASN1_GRAPHICSTRING, 200 .char_width = -1, 201 }, 202 [26] = { 203 /* Tag 26 (0x1a) - VisibleString (ISO646String) */ 204 .name = "VISIBLESTRING", 205 .bit_value = B_ASN1_ISO64STRING, 206 .char_width = 1, 207 }, 208 [27] = { 209 /* Tag 27 (0x1b) - GeneralString */ 210 .name = "GENERALSTRING", 211 .bit_value = B_ASN1_GENERALSTRING, 212 .char_width = -1, 213 }, 214 [28] = { 215 /* Tag 28 (0x1c) - UniversalString */ 216 .name = "UNIVERSALSTRING", 217 .bit_value = B_ASN1_UNIVERSALSTRING, 218 .char_width = 4, 219 }, 220 [29] = { 221 /* Tag 29 (0x1d) - Unallocated */ 222 .name = "<ASN1 29>", 223 .bit_value = B_ASN1_UNKNOWN, 224 .char_width = -1, 225 }, 226 [30] = { 227 /* Tag 30 (0x1e) - BMPString */ 228 .name = "BMPSTRING", 229 .bit_value = B_ASN1_BMPSTRING, 230 .char_width = 2, 231 }, 232 }; 233 234 static const struct asn1_type * 235 asn1_type_by_tag(int tag) 236 { 237 if (tag < 0 || tag > 30) 238 return NULL; 239 240 return &asn1_types[tag]; 241 } 242 243 int 244 asn1_must_be_constructed(int tag) 245 { 246 const struct asn1_type *at; 247 248 if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) 249 tag &= ~V_ASN1_NEG; 250 if ((at = asn1_type_by_tag(tag)) != NULL) 251 return at->encoding == ASN1_ENCODING_CONSTRUCTED_ONLY; 252 253 return 0; 254 } 255 256 int 257 asn1_must_be_primitive(int tag) 258 { 259 const struct asn1_type *at; 260 261 if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) 262 tag &= ~V_ASN1_NEG; 263 if ((at = asn1_type_by_tag(tag)) != NULL) 264 return at->encoding == ASN1_ENCODING_PRIMITIVE_ONLY; 265 266 return 0; 267 } 268 269 int 270 asn1_tag2charwidth(int tag) 271 { 272 const struct asn1_type *at; 273 274 if ((at = asn1_type_by_tag(tag)) != NULL) 275 return at->char_width; 276 277 return -1; 278 } 279 280 unsigned long 281 ASN1_tag2bit(int tag) 282 { 283 const struct asn1_type *at; 284 285 if ((at = asn1_type_by_tag(tag)) != NULL) 286 return (unsigned long)at->bit_value; 287 288 return 0; 289 } 290 291 const char * 292 ASN1_tag2str(int tag) 293 { 294 const struct asn1_type *at; 295 296 if (tag == V_ASN1_NEG_INTEGER || tag == V_ASN1_NEG_ENUMERATED) 297 tag &= ~V_ASN1_NEG; 298 299 if ((at = asn1_type_by_tag(tag)) != NULL) 300 return at->name; 301 302 return "(unknown)"; 303 } 304