src/lib/BasicASN1Reader.h
branchv_0
changeset 22 9b6f86760384
parent 21 705036445672
child 23 8941a679299f
equal deleted inserted replaced
21:705036445672 22:9b6f86760384
    47 	enum class PC : uint8_t {
    47 	enum class PC : uint8_t {
    48 		Primitive = 0,
    48 		Primitive = 0,
    49 		Constructed = 1
    49 		Constructed = 1
    50 	};
    50 	};
    51 
    51 
       
    52 	enum UniversalType : uint64_t {
       
    53 		EndOfContent = 0x00,
       
    54 		Boolean = 0x01,
       
    55 		Integer = 0x02,
       
    56 		BitString = 0x03,
       
    57 		OctetString = 0x04,
       
    58 		Null = 0x05,
       
    59 		ObjectIdentifier = 0x06,
       
    60 		ObjectDescriptor = 0x07,
       
    61 		External = 0x08,
       
    62 		Real = 0x09,
       
    63 		Enumerated = 0xA,
       
    64 		Embedded = 0xB,
       
    65 		UTF8String = 0xC,
       
    66 		RelativeObjectIdentifier = 0xD,
       
    67 		Time = 0xE,
       
    68 		Reserved = 0xF,
       
    69 		Sequence = 0x10,
       
    70 		Set = 0x11,
       
    71 		NumericString = 0x12,
       
    72 		PrintableString = 0x13,
       
    73 		T61String = 0x14,
       
    74 		VideotexString = 0x15,
       
    75 		IA5String = 0x16,
       
    76 		UTCTime = 0x17,
       
    77 		GeneralizedTime = 0x18,
       
    78 		GraphicString = 0x19,
       
    79 		VisibleString = 0x1A,
       
    80 		GeneralString = 0x1B,
       
    81 		UniversalString = 0x1C,
       
    82 		CharacterString = 0x1D,
       
    83 		BMPString = 0x1E,
       
    84 		Date = 0x1F,
       
    85 		TimeOfDay = 0x20,
       
    86 		DateTime = 0x21,
       
    87 		Duration = 0x22,
       
    88 		ObjectIdentifierIRI = 0x23,
       
    89 		RelativeObjectIdentifierIRI = 0x24,
       
    90 	};
       
    91 
    52 	class Header {
    92 	class Header {
    53 	public:
    93 	public:
    54 		TagClass tagClass;
    94 		TagClass tagClass;
    55 		PC pc;
    95 		PC pc;
    56 		uint64_t tag;
    96 		uint64_t tag;
   134 		}
   174 		}
   135 
   175 
   136 		// TODO: check tagClass and pc
   176 		// TODO: check tagClass and pc
   137 
   177 
   138 		// TODO: constants, more types
   178 		// TODO: constants, more types
   139 		if (typeHeader.tag == 0 && typeHeader.tagClass == TagClass::Universal && typeHeader.pc == PC::Primitive) {
   179 		if (typeHeader.tag == UniversalType::EndOfContent && typeHeader.tagClass == TagClass::Universal && typeHeader.pc == PC::Primitive) {
   140 			handlers.writeCollectionEnd();
   180 			handlers.writeCollectionEnd();
   141 		} else if (typeHeader.tag == 16) {
   181 		} else if (typeHeader.tag == UniversalType::Sequence) {
   142 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   182 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   143 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
   183 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Sequence);
   144 		} else if (typeHeader.tag == 17) {
   184 		} else if (typeHeader.tag == UniversalType::Set) {
   145 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   185 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   146 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Set);
   186 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Set);
   147 		} else if (typeHeader.pc == PC::Constructed) {
   187 		} else if (typeHeader.pc == PC::Constructed) {
   148 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   188 			level.push_back({typeHeader.definiteLength, typeHeader.length, getBytesRead()}); // TODO: transaction
   149 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Constructed);
   189 			handlers.writeCollectionStart(ASN1ContentHandler::CollectionType::Constructed);
   150 		} else if (typeHeader.tag == 5 && typeHeader.length == 0) {
   190 		} else if (typeHeader.tag == UniversalType::Null && typeHeader.length == 0) {
   151 			handlers.writeNull();
   191 			handlers.writeNull();
   152 		} else if (typeHeader.tag == 1) {
   192 		} else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) {
   153 			bool value;
   193 			bool value;
   154 			read((uint8_t*) & value, 1);
   194 			read((uint8_t*) & value, 1);
   155 			handlers.writeBoolean(value);
   195 			handlers.writeBoolean(value);
   156 		} else if (typeHeader.tag == 2 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   196 		} else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   157 			// TODO: check available bytes before allocating buffer
   197 			// TODO: check available bytes before allocating buffer
   158 			std::vector<uint8_t> value(typeHeader.length, 0x00);
   198 			std::vector<uint8_t> value(typeHeader.length, 0x00);
   159 			read(value.data(), typeHeader.length);
   199 			read(value.data(), typeHeader.length);
   160 			handlers.writeInteger(ASN1ContentHandler::Integer(value));
   200 			handlers.writeInteger(ASN1ContentHandler::Integer(value));
   161 		} else if (typeHeader.tag == 6 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   201 		} else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   162 			std::vector<uint8_t> value(typeHeader.length, 0x00);
   202 			std::vector<uint8_t> value(typeHeader.length, 0x00);
   163 			read(value.data(), typeHeader.length);
   203 			read(value.data(), typeHeader.length);
   164 			handlers.writeOID({value});
   204 			handlers.writeOID({value});
   165 		} else if (typeHeader.tag == 12 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   205 		} else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   166 			// TODO: check available bytes before allocating buffer
   206 			// TODO: check available bytes before allocating buffer
   167 			std::string s;
   207 			std::string s;
   168 			s.resize(typeHeader.length);
   208 			s.resize(typeHeader.length);
   169 			read((uint8_t*) s.data(), typeHeader.length);
   209 			read((uint8_t*) s.data(), typeHeader.length);
   170 			handlers.writeString(ASN1ContentHandler::StringType::UTF8String, s);
   210 			handlers.writeString(ASN1ContentHandler::StringType::UTF8String, s);
   171 		} else if (typeHeader.tag == 19 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   211 		} else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   172 			// TODO: check encoding
   212 			// TODO: check encoding
   173 			// TODO: check available bytes before allocating buffer
   213 			// TODO: check available bytes before allocating buffer
   174 			std::string s;
   214 			std::string s;
   175 			s.resize(typeHeader.length);
   215 			s.resize(typeHeader.length);
   176 			read((uint8_t*) s.data(), typeHeader.length);
   216 			read((uint8_t*) s.data(), typeHeader.length);
   177 			handlers.writeString(ASN1ContentHandler::StringType::PrintableString, s);
   217 			handlers.writeString(ASN1ContentHandler::StringType::PrintableString, s);
   178 		} else if (typeHeader.tag == 0x17 && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   218 		} else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   179 			// TODO: check available bytes before allocating buffer
   219 			// TODO: check available bytes before allocating buffer
   180 			std::string s;
   220 			std::string s;
   181 			s.resize(typeHeader.length);
   221 			s.resize(typeHeader.length);
   182 			read((uint8_t*) s.data(), typeHeader.length);
   222 			read((uint8_t*) s.data(), typeHeader.length);
   183 
   223 
   184 			ASN1ContentHandler::DateTime dateTime;
   224 			ASN1ContentHandler::DateTime dateTime;
   185 
   225 
   186 			std::smatch match;
   226 			std::smatch match;
   187 			if (std::regex_match(s, match, std::regex("([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})Z"))) {
   227 			if (std::regex_match(s, match, std::regex("([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})?(Z|([+-][0-9]{2})'?([0-9]{2})'?)"))) {
       
   228 				// Supported UTCTime formats:
       
   229 				// YYMMDDhhmmZ
       
   230 				// YYMMDDhhmmssZ
       
   231 				// YYMMDDhhmm+hhmm
       
   232 				// YYMMDDhhmm-hhmm
       
   233 				// YYMMDDhhmmss+hhmm
       
   234 				// YYMMDDhhmmss-hhmm
   188 				int i = 1;
   235 				int i = 1;
   189 				uint32_t year = std::stoi(match[i++]);
   236 				uint32_t year = std::stoi(match[i++]);
   190 				dateTime.year = year < 50 ? 2000 + year : 1900 + year;
   237 				dateTime.year = year < 50 ? 2000 + year : 1900 + year;
   191 				dateTime.month = std::stoi(match[i++]);
   238 				dateTime.month = std::stoi(match[i++]);
   192 				dateTime.day = std::stoi(match[i++]);
   239 				dateTime.day = std::stoi(match[i++]);
   193 				dateTime.hour = std::stoi(match[i++]);
   240 				dateTime.hour = std::stoi(match[i++]);
   194 				dateTime.minute = std::stoi(match[i++]);
   241 				dateTime.minute = std::stoi(match[i++]);
   195 				dateTime.precision = ASN1ContentHandler::DateTime::Precision::Second;
   242 				dateTime.precision = match[i].length() ? ASN1ContentHandler::DateTime::Precision::Second : ASN1ContentHandler::DateTime::Precision::Minute;
       
   243 				dateTime.second = match[i].length() ? std::stoi(match[i++]) : 0;
       
   244 				if (match[i++] != "Z") {
       
   245 					dateTime.timezoneHour = std::stoi(match[i++]);
       
   246 					dateTime.timezoneMinute = std::stoi(match[i++]);
       
   247 				}
   196 				handlers.writeDateTime(ASN1ContentHandler::DateTimeType::UTCTime, dateTime);
   248 				handlers.writeDateTime(ASN1ContentHandler::DateTimeType::UTCTime, dateTime);
   197 			} else {
   249 			} else {
   198 				// FIXME: decode more UTCTime formats:
   250 				throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception
   199 				// YYMMDDhhmmZ
   251 			}
   200 				// YYMMDDhhmm+hh'mm'
   252 
   201 				// YYMMDDhhmm-hh'mm'
   253 		} else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) {
   202 				// YYMMDDhhmmssZ
   254 			// TODO: check available bytes before allocating buffer
   203 				// YYMMDDhhmmss+hh'mm'
   255 			std::string s;
   204 				// YYMMDDhhmmss-hh'mm'
   256 			s.resize(typeHeader.length);
   205 				handlers.writeString(ASN1ContentHandler::StringType::UTF8String, "FIXME: UTCTime format not yet supported: " + s);
   257 			read((uint8_t*) s.data(), typeHeader.length);
       
   258 
       
   259 			ASN1ContentHandler::DateTime dateTime;
       
   260 
       
   261 			std::smatch match;
       
   262 			if (std::regex_match(s, match, std::regex("([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\\.([0-9]{1,3}))?(Z|([+-][0-9]{2})'?([0-9]{2})'?)"))) {
       
   263 				int i = 1;
       
   264 				dateTime.year = std::stoi(match[i++]);
       
   265 				dateTime.month = std::stoi(match[i++]);
       
   266 				dateTime.day = std::stoi(match[i++]);
       
   267 				dateTime.hour = std::stoi(match[i++]);
       
   268 				dateTime.minute = std::stoi(match[i++]);
       
   269 				dateTime.second = match[i].length() ? std::stoi(match[i++]) : 0;
       
   270 				dateTime.precision = match[i++].length() ? ASN1ContentHandler::DateTime::Precision::Nanosecond : ASN1ContentHandler::DateTime::Precision::Second;
       
   271 				if (match[i].length() == 1) dateTime.nanosecond = std::stoi(match[i++]) * 100 * 1000000;
       
   272 				else if (match[i].length() == 2) dateTime.nanosecond = std::stoi(match[i++]) * 10 * 1000000;
       
   273 				else if (match[i].length() == 3) dateTime.nanosecond = std::stoi(match[i++]) * 1000000;
       
   274 				else i++;
       
   275 				if (match[i++] != "Z") {
       
   276 					dateTime.timezoneHour = std::stoi(match[i++]);
       
   277 					dateTime.timezoneMinute = std::stoi(match[i++]);
       
   278 				}
       
   279 				handlers.writeDateTime(ASN1ContentHandler::DateTimeType::GeneralizedTime, dateTime);
       
   280 			} else {
       
   281 				throw std::invalid_argument("Unsupported GeneralizedTime format: " + s); // TODO: better exception
   206 			}
   282 			}
   207 
   283 
   208 		} else {
   284 		} else {
   209 			// TODO: do not skip, parse
   285 			// TODO: do not skip, parse
   210 			std::vector<uint8_t> temp(typeHeader.length, 0);
   286 			std::vector<uint8_t> temp(typeHeader.length, 0);