4 static std::string cer_encode_length(
size_t len) {
8 res.push_back(
static_cast<char>(len));
14 res.push_back(
static_cast<char>(len & 0xFF));
18 res.push_back(
static_cast<char>(res.length() | 0x80));
19 std::reverse(res.begin(), res.end());
25 constexpr int32_t shr8(int32_t arg) {
26 return static_cast<int32_t
>((
static_cast<uint32_t
>(arg) >> 8) | ((arg < 0) ? 0xff000000 : 0x00000000));
29 std::string cer_encode_integer(int32_t number) {
33 res.push_back(
static_cast<char>(number & 0xFF));
34 number = shr8(number);
35 }
while ((number != 0) && (
static_cast<uint32_t
>(number) != 0xffffffff));
37 if (((res[0] & 0x80) != 0) && (number == 0)) {
39 }
else if (((res[0] & 0x80) == 0) && (
static_cast<uint32_t
>(number) == 0xffffffff)) {
40 res.push_back(
static_cast<char>(0xFF));
43 res.push_back(
static_cast<char>(res.length()));
44 std::reverse(res.begin(), res.end());
48 std::string cer_encode_string(
const std::string& contents, ASN1_UniversalTag tag) {
49 size_t len = contents.length();
53 if (len <= CER_MAX_PRIMITIVESTRING) {
54 res += cer_encode_length(len);
59 res.push_back(
static_cast<char>(0x80));
60 std::string contents_copy = contents;
61 while (!contents_copy.empty()) {
62 res.push_back(
static_cast<char>(tag));
64 (contents_copy.length() > CER_MAX_PRIMITIVESTRING) ? CER_MAX_PRIMITIVESTRING : contents_copy.length();
65 res += cer_encode_string(contents_copy.substr(0, chunk_size), tag);
66 contents_copy = contents_copy.substr(chunk_size);
73 static int32_t cer_decode_length(
const std::string& content, int32_t* endpos) {
74 if ((
static_cast<uint8_t
>(content[0])) == 0x80) {
79 if (((
static_cast<uint8_t
>(content[0])) & 0x80) == 0) {
84 int32_t len_len = (
static_cast<uint8_t
>(content[0])) & 0x7F;
85 *endpos = len_len + 1;
91 for (uint32_t i = 0; i < static_cast<uint32_t>(len_len); i++) {
93 res |=
static_cast<int32_t
>(content[i + 1UL] & 0xFF);
105 uint8_t cer_decode_token(
const std::string& ber, int32_t* endpos, int32_t* int_param, std::string* string_param) {
107 if (ber.length() < 2) {
111 auto type_class =
static_cast<ASN1_Class
>(ber[0] & 0xC0);
112 auto tag =
static_cast<ASN1_UniversalTag
>(ber[0] & 0x1F);
113 bool constructed = !((ber[0] & 0x20) == 0);
115 int32_t token_len = cer_decode_length(ber.substr(1), &len_endpos);
118 if (token_len < -1) {
123 if (token_len == -1) {
124 content = ber.substr(2);
126 content = ber.substr(
static_cast<uint32_t
>(1L + len_endpos),
static_cast<uint32_t
>(token_len));
129 if (type_class == kAsn1Universal) {
136 if (int_param !=
nullptr) {
137 *int_param = token_len;
139 *endpos = len_endpos + 1;
140 return kAsn1Sequence;
142 case kAsn1EndSequence:
143 if (token_len != 0) {
146 return kAsn1EndSequence;
152 if (constructed || token_len == -1) {
157 if (content.length() > 4 || content.length() < 1) {
161 bool sign = !((content[0] & 0x80) == 0);
164 for (
size_t i = 0; i < content.length(); i++) {
170 for (
int i = token_len; i < 4; i++) {
171 res |= (0xff << (i << 3));
175 if (int_param !=
nullptr) {
178 *endpos = 1 + len_endpos + token_len;
181 case kAsn1OctetString:
182 case kAsn1Utf8String:
183 case kAsn1NumericString:
184 case kAsn1PrintableString:
185 case kAsn1TeletexString:
186 case kAsn1VideotexString:
188 case kAsn1GeneralizedTime:
189 case kAsn1GraphicString:
190 case kAsn1VisibleString:
191 case kAsn1GeneralString:
192 case kAsn1UniversalString:
193 case kAsn1CharacterString:
194 case kAsn1BMPString: {
195 if (token_len >= 0) {
196 if (string_param !=
nullptr) {
197 *string_param = content;
199 *endpos = 1 + len_endpos + token_len;
201 int32_t position = 1 + len_endpos;
202 if (string_param !=
nullptr) {
203 *string_param = std::string();
206 int32_t internal_endpos;
207 std::string internal_string_param;
208 uint8_t token = cer_decode_token(ber.substr(
static_cast<size_t>(position)), &internal_endpos,
nullptr,
209 &internal_string_param);
210 if (token == kAsn1EndSequence) {
218 if (string_param !=
nullptr) {
219 *string_param += internal_string_param;
221 position += internal_endpos;
235 if (int_param !=
nullptr) {
236 *int_param = token_len;
238 *endpos = len_endpos + 1;
240 return static_cast<uint8_t
>(
static_cast<uint8_t
>(tag) |
static_cast<uint8_t
>(type_class));