1 /** 2 Abstract Syntax Notation 1 is a high-level syntax specification created 3 by the $(LINK https://www.itu.int/en/pages/default.aspx, 4 International Telecommunications Union) in 5 $(LINK https://www.itu.int/rec/T-REC-X.680/en, 6 X.680 - Abstract Syntax Notation One (ASN.1)), that 7 abstractly defines data structures and protocol data units used by 8 programs and protocols. It defines an extensible system of data types, 9 modules, and data structures. 10 11 While described abstractly by ASN.1, the specified protocol data units 12 and data structures can be encoded via various encoding schemes, such as 13 the Basic Encoding Rules (BER), which are defined in the 14 $(LINK https://www.itu.int/en/pages/default.aspx, 15 International Telecommunications Union)'s 16 $(LINK http://www.itu.int/rec/T-REC-X.690/en, X.690 - ASN.1 encoding rules). 17 These encoding schemes uniformly relay data between systems that 18 can differ in endianness, bit-width, byte-size, operating system, 19 machine architecture, and so on. 20 21 The encoding schemata that inherit from ASN.1 are used widely in protocols 22 such as TLS, LDAP, SNMP, RDP, and many more. 23 24 Author: 25 $(LINK http://jonathan.wilbur.space, Jonathan M. Wilbur) 26 $(LINK mailto:jonathan@wilbur.space, jonathan@wilbur.space) 27 License: $(LINK https://mit-license.org/, MIT License) 28 Standards: 29 $(LINK https://www.itu.int/rec/T-REC-X.680/en, X.680 - Abstract Syntax Notation One (ASN.1)) 30 See_Also: 31 $(LINK https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One, The Wikipedia Page on ASN.1) 32 $(LINK https://www.strozhevsky.com/free_docs/asn1_in_simple_words.pdf, ASN.1 By Simple Words) 33 $(LINK http://www.oss.com/asn1/resources/books-whitepapers-pubs/dubuisson-asn1-book.PDF, ASN.1: Communication Between Heterogeneous Systems) 34 */ 35 module asn1; 36 37 /* 38 Done to avoid the problems associated with CVE-2009-0789. I don't know this 39 to be a bug with this code, but it is better to play on the safe side. 40 Remove at your own peril. 41 */ 42 static assert(!(long.sizeof < (void *).sizeof)); 43 44 debug (asn1) 45 { 46 public import std.stdio : write, writefln, writeln; 47 } 48 49 version (unittest) 50 { 51 public import core.exception : AssertError, RangeError; 52 public import std.exception : assertNotThrown, assertThrown; 53 public import std.math : approxEqual; 54 public import std.stdio : write, writefln, writeln; 55 } 56 57 // Check fundamental assumptions of this library. 58 static assert(char.sizeof == 1u); 59 static assert(wchar.sizeof == 2u); 60 static assert(dchar.sizeof == 4u); 61 static assert(double.sizeof > float.sizeof); 62 static assert(real.sizeof >= double.sizeof); 63 64 /// 65 public alias ASN1Exception = AbstractSyntaxNotation1Exception; 66 /// A Generic Exception from which all other ASN.1 Exceptions will inherit. 67 class AbstractSyntaxNotation1Exception : Exception 68 { 69 private import std.exception : basicExceptionCtors; 70 mixin basicExceptionCtors; 71 } 72 73 /// 74 public alias ASN1TagClass = AbstractSyntaxNotation1TagClass; 75 /// 76 immutable public 77 enum AbstractSyntaxNotation1TagClass : ubyte 78 { 79 universal = 0b00000000u, // Native to ASN.1 80 application = 0b01000000u, // Only valid for one specific application 81 contextSpecific = 0b10000000u, // Specific to a sequence, set, or choice 82 privatelyDefined = 0b11000000u// Defined in private specifications 83 } 84 85 /// 86 public alias ASN1Construction = AbstractSyntaxNotation1Construction; 87 /// 88 immutable public 89 enum AbstractSyntaxNotation1Construction : ubyte 90 { 91 primitive = 0b00000000u, // The content octets directly encode the element value 92 constructed = 0b00100000u // The content octets contain 0, 1, or more element encodings 93 } 94 95 /// 96 public alias ASN1UniversalType = AbstractSyntaxNotation1UniversalType; 97 /** 98 The data types, as well as their permitted construction and numeric 99 identifiers, according to the 100 $(LINK https://www.itu.int/en/pages/default.aspx, 101 International Telecommunications Union)'s 102 $(LINK http://www.itu.int/rec/T-REC-X.690/en, X.690 - ASN.1 encoding rules) 103 104 $(TABLE 105 $(TR $(TH Type) $(TH Construction) $(TH Hexadecimal Value)) 106 $(TR $(TD End-of-Content) $(TD Primitive) $(TD 0x00)) 107 $(TR $(TD BOOLEAN) $(TD Primitive) $(TD 0x01)) 108 $(TR $(TD INTEGER) $(TD Primitive) $(TD 0x02)) 109 $(TR $(TD BIT STRING) $(TD Both) $(TD 0x03)) 110 $(TR $(TD OCTET STRING) $(TD Both) $(TD 0x04)) 111 $(TR $(TD NULL) $(TD Primitive) $(TD 0x05)) 112 $(TR $(TD OBJECT IDENTIFIER) $(TD Primitive) $(TD 0x06)) 113 $(TR $(TD Object Descriptor) $(TD Both) $(TD 0x07)) 114 $(TR $(TD EXTERNAL) $(TD Constructed) $(TD 0x08)) 115 $(TR $(TD REAL) $(TD Primitive) $(TD 0x09)) 116 $(TR $(TD ENUMERATED) $(TD Primitive) $(TD 0x0A)) 117 $(TR $(TD EmbeddedPDV) $(TD Constructed) $(TD 0x0B)) 118 $(TR $(TD UTF8String) $(TD Both) $(TD 0x0C)) 119 $(TR $(TD RELATIVE-OID) $(TD Primitive) $(TD 0x0D)) 120 $(TR $(TD SEQUENCE) $(TD Constructed) $(TD 0x10)) 121 $(TR $(TD SET) $(TD Constructed) $(TD 0x11)) 122 $(TR $(TD NumericString) $(TD Both) $(TD 0x12)) 123 $(TR $(TD PrintableString) $(TD Both) $(TD 0x13)) 124 $(TR $(TD T61String) $(TD Both) $(TD 0x14)) 125 $(TR $(TD VideotexString) $(TD Both) $(TD 0x15)) 126 $(TR $(TD IA5String) $(TD Both) $(TD 0x16)) 127 $(TR $(TD UTCTime) $(TD Both) $(TD 0x17)) 128 $(TR $(TD GeneralizedTime) $(TD Both) $(TD 0x18)) 129 $(TR $(TD GraphicString) $(TD Both) $(TD 0x19)) 130 $(TR $(TD VisibleString) $(TD Both) $(TD 0x1A)) 131 $(TR $(TD GeneralString) $(TD Both) $(TD 0x1B)) 132 $(TR $(TD UniversalString) $(TD Both) $(TD 0x1C)) 133 $(TR $(TD CHARACTER STRING) $(TD Both) $(TD 0x1D)) 134 $(TR $(TD BMPString) $(TD Both) $(TD 0x1E)) 135 ) 136 */ 137 immutable public 138 enum AbstractSyntaxNotation1UniversalType : ubyte 139 { 140 endOfContent = 0x00u, 141 eoc = endOfContent, 142 boolean = 0x01u, 143 integer = 0x02u, 144 bitString = 0x03u, 145 octetString = 0x04u, 146 nill = 0x05u, 147 objectIdentifier = 0x06u, 148 oid = objectIdentifier, 149 objectDescriptor = 0x07u, 150 external = 0x08u, 151 ext = external, 152 realNumber = 0x09u, 153 enumerated = 0x0Au, 154 embeddedPresentationDataValue = 0x0Bu, 155 embeddedPDV = embeddedPresentationDataValue, 156 pdv = embeddedPresentationDataValue, 157 unicodeTransformationFormat8String = 0x0Cu, 158 utf8String = unicodeTransformationFormat8String, 159 utf8 = unicodeTransformationFormat8String, 160 relativeObjectIdentifier = 0x0Du, 161 relativeOID = relativeObjectIdentifier, 162 roid = relativeObjectIdentifier, 163 reserved14 = 0x0Eu, 164 reserved15 = 0x0Fu, 165 sequence = 0x10u, 166 set = 0x11u, 167 numericString = 0x12u, 168 numeric = numericString, 169 printableString = 0x13u, 170 printable = printableString, 171 teletexString = 0x14u, 172 t61String = teletexString, 173 videotexString = 0x15u, 174 internationalAlphabetNumber5String = 0x16u, 175 ia5String = internationalAlphabetNumber5String, 176 coordinatedUniversalTime = 0x17u, 177 utcTime = coordinatedUniversalTime, 178 generalizedTime = 0x18u, 179 graphicString = 0x19u, 180 graphic = graphicString, 181 visibleString = 0x1Au, 182 visible = visibleString, 183 generalString = 0x1Bu, 184 general = generalString, 185 universalString = 0x1Cu, 186 universal = universalString, 187 characterString = 0x1Du, 188 basicMultilingualPlaneString = 0x1Eu, 189 bmpString = basicMultilingualPlaneString 190 } 191 192 /// 193 public alias ASN1LengthEncoding = AbstractSyntaxNotation1LengthEncoding; 194 /// 195 public 196 enum AbstractSyntaxNotation1LengthEncoding : ubyte 197 { 198 definiteShort = 0b00000000u, // Least significant seven bits of length octet encode content length of 0 - 127 bytes 199 indefinite = 0b10000000u, // Content ends when two endOfContent bytes are encountered. 200 definiteLong = 0b10000001u, // Least significant seven bits of length octet encode how many more length octets 201 reserved = 0b11111111u 202 } 203 204 /// 205 public alias ASN1RealEncodingBase = AbstractSyntaxNotation1RealEncodingBase; 206 /// 207 immutable public 208 enum AbstractSyntaxNotation1RealEncodingBase : ubyte 209 { 210 base2 = 0x02u, 211 base8 = 0x08u, 212 base10 = 0x0Au, 213 base16 = 0x10u 214 } 215 216 /// 217 public alias ASN1RealEncodingScale = AbstractSyntaxNotation1RealEncodingScale; 218 /// 219 immutable public 220 enum AbstractSyntaxNotation1RealEncodingScale : ubyte 221 { 222 scale0 = 0x00u, 223 scale1 = 0x01u, 224 scale2 = 0x02u, 225 scale3 = 0x03u 226 } 227 228 /// 229 public alias ASN1RealExponentEncoding = AbstractSyntaxNotation1RealExponentEncoding; 230 /// 231 immutable public 232 enum AbstractSyntaxNotation1RealExponentEncoding : ubyte 233 { 234 followingOctet = 0b00000000u, 235 following2Octets = 0b00000001u, 236 following3Octets = 0b00000010u, 237 complicated = 0b00000011u // Just calling it as I see it. 238 } 239 240 /// 241 public alias ASN1SpecialRealValue = AbstractSyntaxNotation1SpecialRealValue; 242 /** 243 Special values for REALs, as assigned in section 8.5.9 of X.690. 244 245 Note that NOT-A-NUMBER and minus zero were added in the 2015 version. 246 */ 247 immutable public 248 enum AbstractSyntaxNotation1SpecialRealValue : ubyte 249 { 250 plusInfinity = 0b01000000u, 251 minusInfinity = 0b01000001u, 252 notANumber = 0b01000010u, 253 minusZero = 0b01000011u 254 } 255 256 /// 257 public alias ASN1Base10RealNumericalRepresentation = AbstractSyntaxNotation1Base10RealNumericalRepresentation; 258 /** 259 The standardized string representations of floating point numbers, as 260 specified in $(LINK https://www.iso.org/standard/12285.html, ISO 6093). 261 262 $(TABLE 263 $(TR $(TH Representation) $(TH Description) $(TH Examples)) 264 $(TR $(TD NR1) $(TD Implicit decimal point) $(TD "3", "-1", "+1000")) 265 $(TR $(TD NR2) $(TD Explicit decimal) $(TD "3.0", "-1.3", "-.3")) 266 $(TR $(TD NR3) $(TD Explicit exponent) $(TD "3.0E1", "123E+100")) 267 ) 268 269 Citations: 270 Dubuisson, Olivier. “Character String Types.” ASN.1: 271 Communication between Heterogeneous Systems, Morgan 272 Kaufmann, 2001, p. 143. 273 */ 274 immutable public 275 enum AbstractSyntaxNotation1Base10RealNumericalRepresentation : ubyte 276 { 277 nr1 = 0b00000001u, 278 nr2 = 0b00000010u, 279 nr3 = 0b00000011 280 } 281 282 /// The acceptable characters for a NumericString 283 immutable public string numericStringCharacters = "0123456789 "; 284 285 /** 286 The acceptable characters for a printableString. 287 288 The sorting of letters below is a slight optimization: 289 they are sorted in order of decreasing frequency in the English 290 language, so that canFind will usually have to iterate through 291 fewer letters before finding a match. 292 */ 293 immutable public string printableStringCharacters = 294 "etaoinsrhdlucmfywgpbvkxqjzETAOINSRHDLUCMFYWGPBVKXQJZ0123456789 '()+,-./:=?";