110 } |
110 } |
111 |
111 |
112 return h; |
112 return h; |
113 } |
113 } |
114 |
114 |
115 void readNext() { |
115 const std::string readString(size_t length) { |
|
116 std::string result; |
|
117 |
|
118 for (size_t remaining = length; remaining;) { |
|
119 size_t current = std::min(remaining, (size_t) 3); |
|
120 result.resize(result.size() + current); |
|
121 read((uint8_t*) result.data() + result.size() - current, current); |
|
122 remaining -= current; |
|
123 } |
|
124 |
|
125 return result; |
|
126 } |
|
127 |
|
128 const std::vector<uint8_t> readVector(size_t length) { |
|
129 std::vector<uint8_t> result; |
|
130 std::string s = readString(length); // TODO: read directly to the vector |
|
131 result.resize(length); |
|
132 for (size_t i = 0; i < length; i++) result[i] = (uint8_t) s[i]; |
|
133 return result; |
|
134 } |
|
135 |
|
136 void processNext() { |
116 using TagClass = ASN1ContentHandler::TagClass; |
137 using TagClass = ASN1ContentHandler::TagClass; |
117 using PC = ASN1ContentHandler::PC; |
138 using PC = ASN1ContentHandler::PC; |
118 |
139 |
119 checkRemainingItems(); |
140 checkRemainingItems(); |
120 BasicHeader typeHeader = readHeader(); |
141 BasicHeader typeHeader = readHeader(); |
144 } else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) { |
165 } else if (typeHeader.tag == UniversalType::Boolean && typeHeader.definiteLength && typeHeader.length == 1) { |
145 bool value; |
166 bool value; |
146 read((uint8_t*) & value, 1); |
167 read((uint8_t*) & value, 1); |
147 handlers->writeBoolean(typeHeader, value); |
168 handlers->writeBoolean(typeHeader, value); |
148 } else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
169 } else if (typeHeader.tag == UniversalType::Integer && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
149 // TODO: check available bytes before allocating buffer |
170 std::vector<uint8_t> value = readVector(typeHeader.length); |
150 std::vector<uint8_t> value(typeHeader.length, 0x00); |
|
151 read(value.data(), typeHeader.length); |
|
152 handlers->writeInteger(typeHeader, ASN1ContentHandler::Integer(value)); |
171 handlers->writeInteger(typeHeader, ASN1ContentHandler::Integer(value)); |
153 } else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
172 } else if (typeHeader.tag == UniversalType::ObjectIdentifier && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
154 std::vector<uint8_t> value(typeHeader.length, 0x00); |
173 std::vector<uint8_t> value(typeHeader.length, 0x00); |
155 read(value.data(), typeHeader.length); |
174 read(value.data(), typeHeader.length); |
156 handlers->writeOID(typeHeader,{value}); |
175 handlers->writeOID(typeHeader,{value}); |
157 } else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
176 } else if (typeHeader.tag == UniversalType::UTF8String && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
158 // TODO: check available bytes before allocating buffer |
177 std::string s = readString(typeHeader.length); |
159 std::string s; |
|
160 s.resize(typeHeader.length); |
|
161 read((uint8_t*) s.data(), typeHeader.length); |
|
162 handlers->writeTextString(typeHeader, s); |
178 handlers->writeTextString(typeHeader, s); |
163 } else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
179 } else if (typeHeader.tag == UniversalType::PrintableString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
164 // TODO: check encoding |
180 // TODO: check encoding |
165 // TODO: check available bytes before allocating buffer |
181 std::string s = readString(typeHeader.length); |
166 std::string s; |
|
167 s.resize(typeHeader.length); |
|
168 read((uint8_t*) s.data(), typeHeader.length); |
|
169 handlers->writeTextString(typeHeader, s); |
182 handlers->writeTextString(typeHeader, s); |
170 } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
183 } else if (typeHeader.tag == UniversalType::OctetString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
171 // TODO: check available bytes before allocating buffer |
184 std::string s = readString(typeHeader.length); |
172 std::string s; |
|
173 s.resize(typeHeader.length); |
|
174 read((uint8_t*) s.data(), typeHeader.length); |
|
175 if (processEncapsulatedContent(typeHeader, s) == false) handlers->writeOctetString(typeHeader, s); |
185 if (processEncapsulatedContent(typeHeader, s) == false) handlers->writeOctetString(typeHeader, s); |
176 } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
186 } else if (typeHeader.tag == UniversalType::BitString && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
177 // TODO: check available bytes before allocating buffer |
187 std::string s = readString(typeHeader.length); |
178 std::string s; |
|
179 s.resize(typeHeader.length); |
|
180 read((uint8_t*) s.data(), typeHeader.length); |
|
181 if (processEncapsulatedContent(typeHeader, s) == false) { |
188 if (processEncapsulatedContent(typeHeader, s) == false) { |
182 std::vector<bool> bits; |
189 std::vector<bool> bits; |
183 // TODO: throw exception on wrong padding or insufficient length? |
190 // TODO: throw exception on wrong padding or insufficient length? |
184 if (s.size() > 1) { |
191 if (s.size() > 1) { |
185 uint8_t padding = s[0]; |
192 uint8_t padding = s[0]; |
187 for (size_t i = s.size() - 2; i > 0; i--) for (uint8_t j = 0; j < 8; j++) bits.push_back(s[i] & 1 << j); |
194 for (size_t i = s.size() - 2; i > 0; i--) for (uint8_t j = 0; j < 8; j++) bits.push_back(s[i] & 1 << j); |
188 } |
195 } |
189 handlers->writeBitString(typeHeader, bits); |
196 handlers->writeBitString(typeHeader, bits); |
190 } |
197 } |
191 } else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
198 } else if (typeHeader.tag == UniversalType::UTCTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
192 // TODO: check available bytes before allocating buffer |
|
193 // TODO: check encoding |
199 // TODO: check encoding |
194 std::string s; |
200 std::string s = readString(typeHeader.length); |
195 s.resize(typeHeader.length); |
|
196 read((uint8_t*) s.data(), typeHeader.length); |
|
197 |
201 |
198 ASN1ContentHandler::DateTime dateTime; |
202 ASN1ContentHandler::DateTime dateTime; |
199 |
203 |
200 std::smatch match; |
204 std::smatch match; |
201 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}))"))) { |
205 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}))"))) { |
217 } else { |
221 } else { |
218 throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception |
222 throw std::invalid_argument("Unsupported UTCTime format: " + s); // TODO: better exception |
219 } |
223 } |
220 |
224 |
221 } else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
225 } else if (typeHeader.tag == UniversalType::GeneralizedTime && typeHeader.tagClass == TagClass::Universal && typeHeader.definiteLength) { |
222 // TODO: check available bytes before allocating buffer |
226 std::string s = readString(typeHeader.length); |
223 std::string s; |
|
224 s.resize(typeHeader.length); |
|
225 read((uint8_t*) s.data(), typeHeader.length); |
|
226 |
227 |
227 ASN1ContentHandler::DateTime dateTime; |
228 ASN1ContentHandler::DateTime dateTime; |
228 |
229 |
229 std::smatch match; |
230 std::smatch match; |
230 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}))"))) { |
231 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}))"))) { |