• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 6187089116

14 Sep 2023 02:42PM CUT coverage: 91.716% (-0.005%) from 91.721%
6187089116

push

github

web-flow
Merge pull request #3696 from randombit/raw_ops_span

rsa, raw_op using std::span view for raw_kem_decrypt to avoid

79098 of 86242 relevant lines covered (91.72%)

8640988.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.58
/src/lib/math/bigint/big_code.cpp
1
/*
2
* BigInt Encoding/Decoding
3
* (C) 1999-2010,2012,2019,2021 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/bigint.h>
9

10
#include <botan/hex.h>
11
#include <botan/internal/divide.h>
12

13
namespace Botan {
14

15
std::string BigInt::to_dec_string() const {
58✔
16
   // Use the largest power of 10 that fits in a word
17
#if(BOTAN_MP_WORD_BITS == 64)
18
   const word conversion_radix = 10000000000000000000U;
58✔
19
   const word radix_digits = 19;
58✔
20
#else
21
   const word conversion_radix = 1000000000U;
22
   const word radix_digits = 9;
23
#endif
24

25
   // (over-)estimate of the number of digits needed; log2(10) ~ 3.3219
26
   const size_t digit_estimate = static_cast<size_t>(1 + (this->bits() / 3.32));
58✔
27

28
   // (over-)estimate of db such that conversion_radix^db > *this
29
   const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
58✔
30

31
   BigInt value = *this;
58✔
32
   value.set_sign(Positive);
58✔
33

34
   // Extract groups of digits into words
35
   std::vector<word> digit_groups(digit_blocks);
58✔
36

37
   for(size_t i = 0; i != digit_blocks; ++i) {
127✔
38
      word remainder = 0;
69✔
39
      ct_divide_word(value, conversion_radix, value, remainder);
69✔
40
      digit_groups[i] = remainder;
69✔
41
   }
42

43
   BOTAN_ASSERT_NOMSG(value.is_zero());
116✔
44

45
   // Extract digits from the groups
46
   std::vector<uint8_t> digits(digit_blocks * radix_digits);
58✔
47

48
   for(size_t i = 0; i != digit_blocks; ++i) {
127✔
49
      word remainder = digit_groups[i];
69✔
50
      for(size_t j = 0; j != radix_digits; ++j) {
1,380✔
51
         // Compiler should convert div/mod by 10 into mul by magic constant
52
         const word digit = remainder % 10;
1,311✔
53
         remainder /= 10;
1,311✔
54
         digits[radix_digits * i + j] = static_cast<uint8_t>(digit);
1,311✔
55
      }
56
   }
57

58
   // remove leading zeros
59
   while(!digits.empty() && digits.back() == 0) {
939✔
60
      digits.pop_back();
946✔
61
   }
62

63
   BOTAN_ASSERT_NOMSG(digit_estimate >= digits.size());
58✔
64

65
   // Reverse the digits to big-endian and format to text
66
   std::string s;
58✔
67
   s.reserve(1 + digits.size());
58✔
68

69
   if(is_negative()) {
58✔
70
      s += "-";
5✔
71
   }
72

73
   // Reverse and convert to textual digits
74
   for(auto i = digits.rbegin(); i != digits.rend(); ++i) {
481✔
75
      s.push_back(*i + '0');  // assumes ASCII
423✔
76
   }
77

78
   if(s.empty()) {
58✔
79
      s += "0";
7✔
80
   }
81

82
   return s;
58✔
83
}
171✔
84

85
std::string BigInt::to_hex_string() const {
84✔
86
   const size_t this_bytes = this->bytes();
84✔
87
   std::vector<uint8_t> bits(std::max<size_t>(1, this_bytes));
141✔
88

89
   if(this_bytes > 0) {
84✔
90
      this->binary_encode(bits.data());
82✔
91
   }
92

93
   std::string hrep;
84✔
94
   if(is_negative()) {
84✔
95
      hrep += "-";
5✔
96
   }
97
   hrep += "0x";
84✔
98
   hrep += hex_encode(bits);
168✔
99
   return hrep;
84✔
100
}
84✔
101

102
/*
103
* Encode a BigInt, with leading 0s if needed
104
*/
105
secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes) {
21,789✔
106
   if(n.bytes() > bytes) {
21,789✔
107
      throw Encoding_Error("encode_1363: n is too large to encode properly");
224✔
108
   }
109

110
   secure_vector<uint8_t> output(bytes);
21,565✔
111
   n.binary_encode(output.data(), output.size());
21,565✔
112
   return output;
21,565✔
113
}
×
114

115
void BigInt::encode_1363(std::span<uint8_t> output, const BigInt& n) {
4,837✔
116
   if(n.bytes() > output.size()) {
4,837✔
117
      throw Encoding_Error("encode_1363: n is too large to encode properly");
×
118
   }
119

120
   n.binary_encode(output.data(), output.size());
4,837✔
121
}
4,837✔
122

123
//static
124
void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n) {
4,198✔
125
   if(n.bytes() > bytes) {
4,198✔
126
      throw Encoding_Error("encode_1363: n is too large to encode properly");
×
127
   }
128

129
   n.binary_encode(output, bytes);
4,198✔
130
}
4,198✔
131

132
/*
133
* Encode two BigInt, with leading 0s if needed, and concatenate
134
*/
135
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes) {
633✔
136
   if(n1.is_negative() || n2.is_negative()) {
633✔
137
      throw Encoding_Error("encode_fixed_length_int_pair: values must be positive");
×
138
   }
139
   if(n1.bytes() > bytes || n2.bytes() > bytes) {
633✔
140
      throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
×
141
   }
142
   secure_vector<uint8_t> output(2 * bytes);
633✔
143
   n1.binary_encode(output.data(), bytes);
633✔
144
   n2.binary_encode(output.data() + bytes, bytes);
633✔
145
   return output;
633✔
146
}
×
147

148
/*
149
* Decode a BigInt
150
*/
151
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base) {
45,735✔
152
   BigInt r;
45,735✔
153
   if(base == Binary) {
45,735✔
154
      r.binary_decode(buf, length);
×
155
   } else if(base == Hexadecimal) {
45,735✔
156
      secure_vector<uint8_t> binary;
40,771✔
157

158
      if(length % 2) {
40,771✔
159
         // Handle lack of leading 0
160
         const char buf0_with_leading_0[2] = {'0', static_cast<char>(buf[0])};
3,592✔
161

162
         binary = hex_decode_locked(buf0_with_leading_0, 2);
7,184✔
163

164
         binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]), length - 1, false);
7,184✔
165
      } else {
166
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf), length, false);
74,358✔
167
      }
168

169
      r.binary_decode(binary.data(), binary.size());
40,771✔
170
   } else if(base == Decimal) {
45,735✔
171
      // This could be made faster using the same trick as to_dec_string
172
      for(size_t i = 0; i != length; ++i) {
395,289✔
173
         const char c = buf[i];
390,325✔
174

175
         if(c < '0' || c > '9') {
390,325✔
176
            throw Invalid_Argument("BigInt::decode: invalid decimal char");
×
177
         }
178

179
         const uint8_t x = c - '0';
390,325✔
180
         BOTAN_ASSERT_NOMSG(x < 10);
390,325✔
181

182
         r *= 10;
390,325✔
183
         r += x;
390,325✔
184
      }
185
   } else {
186
      throw Invalid_Argument("Unknown BigInt decoding method");
×
187
   }
188
   return r;
45,735✔
189
}
×
190

191
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc