Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2020 Google Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | //////////////////////////////////////////////////////////////////////////////// |
16 | | |
17 | | #include "common.h" |
18 | | |
19 | | #include <limits.h> |
20 | | #include <math.h> |
21 | | |
22 | 40.5k | uint8_t GetVariableIntLen(uint64_t value, size_t base) { |
23 | 40.5k | uint8_t base_bits = log2(base); |
24 | 302k | for (uint8_t num_bits = (sizeof(value) - 1) * CHAR_BIT; num_bits >= base_bits; |
25 | 278k | num_bits -= base_bits) { |
26 | 278k | if (value >> num_bits) { |
27 | 17.0k | return ceil(static_cast<double>(num_bits) / base_bits) + 1; |
28 | 17.0k | } |
29 | 278k | } |
30 | | // Special-case: zero requires one, not zero bytes. |
31 | 23.4k | return 1; |
32 | 40.5k | } |
33 | | |
34 | | void InsertVariableIntBase128(uint64_t value, |
35 | | size_t pos, |
36 | 1.59k | std::vector<uint8_t>& der) { |
37 | 1.59k | std::vector<uint8_t> variable_int; |
38 | 5.35k | for (uint8_t i = GetVariableIntLen(value, 128) - 1; i != 0; --i) { |
39 | | // If it's not the last byte, the high bit is set to 1. |
40 | 3.75k | variable_int.push_back((0x01 << 7) | ((value >> (i * 7)) & 0x7F)); |
41 | 3.75k | } |
42 | 1.59k | variable_int.push_back(value & 0x7F); |
43 | 1.59k | der.insert(der.begin() + pos, variable_int.begin(), variable_int.end()); |
44 | 1.59k | } |
45 | | |
46 | | void InsertVariableIntBase256(uint64_t value, |
47 | | size_t pos, |
48 | 28.6k | std::vector<uint8_t>& der) { |
49 | 28.6k | std::vector<uint8_t> variable_int; |
50 | 67.2k | for (uint8_t shift = GetVariableIntLen(value, 256); shift != 0; --shift) { |
51 | 38.5k | variable_int.push_back((value >> ((shift - 1) * CHAR_BIT)) & 0xFF); |
52 | 38.5k | } |
53 | 28.6k | der.insert(der.begin() + pos, variable_int.begin(), variable_int.end()); |
54 | 28.6k | } |
55 | | |
56 | | void EncodeTagAndLength(uint8_t tag_byte, |
57 | | size_t len, |
58 | | size_t pos, |
59 | 0 | std::vector<uint8_t>& der) { |
60 | 0 | InsertVariableIntBase256(len, pos, der); |
61 | | // X.690 (2015), 8.1.3.3: The long-form is used when the length is |
62 | | // larger than 127. |
63 | | // Note: |len_num_bytes| is not checked here, because it will equal |
64 | | // 1 for values [128..255], but those require the long-form length. |
65 | 0 | if (len > 127) { |
66 | | // See X.690 (2015) 8.1.3.5. |
67 | | // Long-form length is encoded as a byte with the high-bit set to indicate |
68 | | // the long-form, while the remaining bits indicate how many bytes are used |
69 | | // to encode the length. |
70 | 0 | size_t len_num_bytes = GetVariableIntLen(len, 256); |
71 | 0 | der.insert(der.begin() + pos, (0x80 | len_num_bytes)); |
72 | 0 | } |
73 | 0 | der.insert(der.begin() + pos, tag_byte); |
74 | 0 | } |
75 | | |
76 | | void ReplaceTag(uint8_t tag_byte, |
77 | | size_t pos_of_tag, |
78 | 0 | std::vector<uint8_t>& der) { |
79 | 0 | if (der.size() <= pos_of_tag) { |
80 | 0 | return; |
81 | 0 | } |
82 | 0 | auto start = der.begin() + pos_of_tag; |
83 | 0 | auto end = start + 1; |
84 | | // Check to see if it's a high tag (multi-byte) |
85 | 0 | if ((*start & 0x1F) == 0x1F) { |
86 | | // High-tag will have 0x80 set if there is >1 byte remaining |
87 | 0 | while (end != der.end() && (*end & 0x80)) |
88 | 0 | ++end; |
89 | 0 | start = der.erase(start, end); |
90 | 0 | } |
91 | 0 | *start = tag_byte; |
92 | 0 | } |