Coverage Report

Created: 2023-06-07 07:11

/src/common.cc
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
}