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); |