Coverage Report

Created: 2020-09-16 07:52

/src/botan/src/lib/math/bigint/big_code.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* BigInt Encoding/Decoding
3
* (C) 1999-2010,2012,2019 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/bigint.h>
9
#include <botan/divide.h>
10
#include <botan/charset.h>
11
#include <botan/hex.h>
12
13
namespace Botan {
14
15
std::string BigInt::to_dec_string() const
16
0
   {
17
0
   BigInt copy = *this;
18
0
   copy.set_sign(Positive);
19
0
20
0
   uint8_t remainder;
21
0
   std::vector<uint8_t> digits;
22
0
23
0
   while(copy > 0)
24
0
      {
25
0
      ct_divide_u8(copy, 10, copy, remainder);
26
0
      digits.push_back(remainder);
27
0
      }
28
0
29
0
   std::string s;
30
0
31
0
   for(auto i = digits.rbegin(); i != digits.rend(); ++i)
32
0
      {
33
0
      s.push_back(Charset::digit2char(*i));
34
0
      }
35
0
36
0
   if(s.empty())
37
0
      s += "0";
38
0
39
0
   return s;
40
0
   }
41
42
std::string BigInt::to_hex_string() const
43
0
   {
44
0
   const std::vector<uint8_t> bits = BigInt::encode(*this);
45
0
   if(bits.empty())
46
0
      return "00";
47
0
   else
48
0
      return hex_encode(bits);
49
0
   }
50
51
/*
52
* Encode a BigInt
53
*/
54
void BigInt::encode(uint8_t output[], const BigInt& n, Base base)
55
0
   {
56
0
   secure_vector<uint8_t> enc = n.encode_locked(base);
57
0
   copy_mem(output, enc.data(), enc.size());
58
0
   }
59
60
namespace {
61
62
std::vector<uint8_t> str_to_vector(const std::string& s)
63
0
   {
64
0
   std::vector<uint8_t> v(s.size());
65
0
   std::memcpy(v.data(), s.data(), s.size());
66
0
   return v;
67
0
   }
68
69
secure_vector<uint8_t> str_to_lvector(const std::string& s)
70
0
   {
71
0
   secure_vector<uint8_t> v(s.size());
72
0
   std::memcpy(v.data(), s.data(), s.size());
73
0
   return v;
74
0
   }
75
76
}
77
78
/*
79
* Encode a BigInt
80
*/
81
std::vector<uint8_t> BigInt::encode(const BigInt& n, Base base)
82
0
   {
83
0
   if(base == Binary)
84
0
      return BigInt::encode(n);
85
0
   else if(base == Hexadecimal)
86
0
      return str_to_vector(n.to_hex_string());
87
0
   else if(base == Decimal)
88
0
      return str_to_vector(n.to_dec_string());
89
0
   else
90
0
      throw Invalid_Argument("Unknown BigInt encoding base");
91
0
   }
92
93
/*
94
* Encode a BigInt
95
*/
96
secure_vector<uint8_t> BigInt::encode_locked(const BigInt& n, Base base)
97
0
   {
98
0
   if(base == Binary)
99
0
      return BigInt::encode_locked(n);
100
0
   else if(base == Hexadecimal)
101
0
      return str_to_lvector(n.to_hex_string());
102
0
   else if(base == Decimal)
103
0
      return str_to_lvector(n.to_dec_string());
104
0
   else
105
0
      throw Invalid_Argument("Unknown BigInt encoding base");
106
0
   }
107
108
/*
109
* Encode a BigInt, with leading 0s if needed
110
*/
111
secure_vector<uint8_t> BigInt::encode_1363(const BigInt& n, size_t bytes)
112
20.1k
   {
113
20.1k
   if(n.bytes() > bytes)
114
22
      throw Encoding_Error("encode_1363: n is too large to encode properly");
115
20.1k
116
20.1k
   secure_vector<uint8_t> output(bytes);
117
20.1k
   n.binary_encode(output.data(), output.size());
118
20.1k
   return output;
119
20.1k
   }
120
121
//static
122
void BigInt::encode_1363(uint8_t output[], size_t bytes, const BigInt& n)
123
40.7k
   {
124
40.7k
   if(n.bytes() > bytes)
125
0
      throw Encoding_Error("encode_1363: n is too large to encode properly");
126
40.7k
127
40.7k
   n.binary_encode(output, bytes);
128
40.7k
   }
129
130
/*
131
* Encode two BigInt, with leading 0s if needed, and concatenate
132
*/
133
secure_vector<uint8_t> BigInt::encode_fixed_length_int_pair(const BigInt& n1, const BigInt& n2, size_t bytes)
134
0
   {
135
0
   if(n1.bytes() > bytes || n2.bytes() > bytes)
136
0
      throw Encoding_Error("encode_fixed_length_int_pair: values too large to encode properly");
137
0
   secure_vector<uint8_t> output(2 * bytes);
138
0
   n1.binary_encode(output.data()        , bytes);
139
0
   n2.binary_encode(output.data() + bytes, bytes);
140
0
   return output;
141
0
   }
142
143
/*
144
* Decode a BigInt
145
*/
146
BigInt BigInt::decode(const uint8_t buf[], size_t length, Base base)
147
18.2k
   {
148
18.2k
   BigInt r;
149
18.2k
   if(base == Binary)
150
0
      {
151
0
      r.binary_decode(buf, length);
152
0
      }
153
18.2k
   else if(base == Hexadecimal)
154
18.2k
      {
155
18.2k
      secure_vector<uint8_t> binary;
156
18.2k
157
18.2k
      if(length % 2)
158
7.68k
         {
159
         // Handle lack of leading 0
160
7.68k
         const char buf0_with_leading_0[2] =
161
7.68k
            { '0', static_cast<char>(buf[0]) };
162
7.68k
163
7.68k
         binary = hex_decode_locked(buf0_with_leading_0, 2);
164
7.68k
165
7.68k
         binary += hex_decode_locked(cast_uint8_ptr_to_char(&buf[1]),
166
7.68k
                                     length - 1,
167
7.68k
                                     false);
168
7.68k
         }
169
10.5k
      else
170
10.5k
         binary = hex_decode_locked(cast_uint8_ptr_to_char(buf),
171
10.5k
                                    length, false);
172
18.2k
173
18.2k
      r.binary_decode(binary.data(), binary.size());
174
18.2k
      }
175
0
   else if(base == Decimal)
176
0
      {
177
0
      for(size_t i = 0; i != length; ++i)
178
0
         {
179
0
         if(Charset::is_space(buf[i]))
180
0
            continue;
181
0
182
0
         if(!Charset::is_digit(buf[i]))
183
0
            throw Invalid_Argument("BigInt::decode: "
184
0
                                   "Invalid character in decimal input");
185
0
186
0
         const uint8_t x = Charset::char2digit(buf[i]);
187
0
188
0
         if(x >= 10)
189
0
            throw Invalid_Argument("BigInt: Invalid decimal string");
190
0
191
0
         r *= 10;
192
0
         r += x;
193
0
         }
194
0
      }
195
0
   else
196
0
      throw Invalid_Argument("Unknown BigInt decoding method");
197
18.2k
   return r;
198
18.2k
   }
199
200
}