Coverage Report

Created: 2020-06-30 13:58

/src/botan/src/lib/asn1/asn1_oid.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* ASN.1 OID
3
* (C) 1999-2007 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7
8
#include <botan/asn1_oid.h>
9
#include <botan/der_enc.h>
10
#include <botan/ber_dec.h>
11
#include <botan/internal/bit_ops.h>
12
#include <botan/parsing.h>
13
#include <botan/oids.h>
14
#include <algorithm>
15
#include <sstream>
16
17
namespace Botan {
18
19
namespace {
20
21
// returns empty on invalid
22
std::vector<uint32_t> parse_oid_str(const std::string& oid)
23
532k
   {
24
532k
   try
25
532k
      {
26
532k
      std::string elem;
27
532k
      std::vector<uint32_t> oid_elems;
28
532k
29
532k
      for(char c : oid)
30
5.06M
         {
31
5.06M
         if(c == '.')
32
1.76M
            {
33
1.76M
            if(elem.empty())
34
0
               return std::vector<uint32_t>();
35
1.76M
            oid_elems.push_back(to_u32bit(elem));
36
1.76M
            elem.clear();
37
1.76M
            }
38
3.30M
         else
39
3.30M
            {
40
3.30M
            elem += c;
41
3.30M
            }
42
5.06M
         }
43
532k
44
532k
      if(elem.empty())
45
0
         return std::vector<uint32_t>();
46
532k
      oid_elems.push_back(to_u32bit(elem));
47
532k
48
532k
      if(oid_elems.size() < 2)
49
0
         return std::vector<uint32_t>();
50
532k
51
532k
      return oid_elems;
52
532k
      }
53
6
   catch(Invalid_Argument&) // thrown by to_u32bit
54
6
      {
55
6
      return std::vector<uint32_t>();
56
6
      }
57
532k
   }
58
59
}
60
61
//static
62
OID OID::from_string(const std::string& str)
63
19.0k
   {
64
19.0k
   if(str.empty())
65
0
      throw Invalid_Argument("OID::from_string argument must be non-empty");
66
19.0k
67
19.0k
   const OID o = OIDS::str2oid_or_empty(str);
68
19.0k
   if(o.has_value())
69
19.0k
      return o;
70
6
71
6
   std::vector<uint32_t> raw = parse_oid_str(str);
72
6
73
6
   if(raw.size() > 0)
74
0
      return OID(std::move(raw));
75
6
76
6
   throw Lookup_Error("No OID associated with name " + str);
77
6
   }
78
79
/*
80
* ASN.1 OID Constructor
81
*/
82
OID::OID(const std::string& oid_str)
83
532k
   {
84
532k
   if(!oid_str.empty())
85
532k
      {
86
532k
      m_id = parse_oid_str(oid_str);
87
532k
88
532k
      if(m_id.size() < 2 || m_id[0] > 2)
89
0
         throw Invalid_OID(oid_str);
90
532k
      if((m_id[0] == 0 || m_id[0] == 1) && m_id[1] > 39)
91
0
         throw Invalid_OID(oid_str);
92
532k
      }
93
532k
   }
94
95
/*
96
* Return this OID as a string
97
*/
98
std::string OID::to_string() const
99
174k
   {
100
174k
   std::ostringstream oss;
101
1.26M
   for(size_t i = 0; i != m_id.size(); ++i)
102
1.09M
      {
103
1.09M
      oss << m_id[i];
104
1.09M
      if(i != m_id.size() - 1)
105
919k
         oss << ".";
106
1.09M
      }
107
174k
   return oss.str();
108
174k
   }
109
110
std::string OID::to_formatted_string() const
111
100k
   {
112
100k
   const std::string s = OIDS::oid2str_or_empty(*this);
113
100k
   if(!s.empty())
114
89.8k
      return s;
115
10.9k
   return this->to_string();
116
10.9k
   }
117
118
/*
119
* Append another component to the OID
120
*/
121
OID operator+(const OID& oid, uint32_t new_component)
122
0
   {
123
0
   std::vector<uint32_t> val = oid.get_components();
124
0
   val.push_back(new_component);
125
0
   return OID(std::move(val));
126
0
   }
127
128
/*
129
* Compare two OIDs
130
*/
131
bool operator<(const OID& a, const OID& b)
132
698k
   {
133
698k
   const std::vector<uint32_t>& oid1 = a.get_components();
134
698k
   const std::vector<uint32_t>& oid2 = b.get_components();
135
698k
136
698k
   return std::lexicographical_compare(oid1.begin(), oid1.end(),
137
698k
                                       oid2.begin(), oid2.end());
138
698k
   }
139
140
/*
141
* DER encode an OBJECT IDENTIFIER
142
*/
143
void OID::encode_into(DER_Encoder& der) const
144
12.0k
   {
145
12.0k
   if(m_id.size() < 2)
146
0
      throw Invalid_Argument("OID::encode_into: OID is invalid");
147
12.0k
148
12.0k
   std::vector<uint8_t> encoding;
149
12.0k
150
12.0k
   if(m_id[0] > 2 || m_id[1] >= 40)
151
19
      throw Encoding_Error("Invalid OID prefix, cannot encode");
152
12.0k
153
12.0k
   encoding.push_back(static_cast<uint8_t>(40 * m_id[0] + m_id[1]));
154
12.0k
155
70.4k
   for(size_t i = 2; i != m_id.size(); ++i)
156
58.4k
      {
157
58.4k
      if(m_id[i] == 0)
158
35
         encoding.push_back(0);
159
58.3k
      else
160
58.3k
         {
161
58.3k
         size_t blocks = high_bit(m_id[i]) + 6;
162
58.3k
         blocks = (blocks - (blocks % 7)) / 7;
163
58.3k
164
58.3k
         BOTAN_ASSERT(blocks > 0, "Math works");
165
58.3k
166
89.9k
         for(size_t j = 0; j != blocks - 1; ++j)
167
31.5k
            encoding.push_back(0x80 | ((m_id[i] >> 7*(blocks-j-1)) & 0x7F));
168
58.3k
         encoding.push_back(m_id[i] & 0x7F);
169
58.3k
         }
170
58.4k
      }
171
12.0k
   der.add_object(OBJECT_ID, UNIVERSAL, encoding);
172
12.0k
   }
173
174
/*
175
* Decode a BER encoded OBJECT IDENTIFIER
176
*/
177
void OID::decode_from(BER_Decoder& decoder)
178
245k
   {
179
245k
   BER_Object obj = decoder.get_next_object();
180
245k
   if(obj.tagging() != OBJECT_ID)
181
1.05k
      throw BER_Bad_Tag("Error decoding OID, unknown tag", obj.tagging());
182
244k
183
244k
   const size_t length = obj.length();
184
244k
   const uint8_t* bits = obj.bits();
185
244k
186
244k
   if(length < 2 && !(length == 1 && bits[0] == 0))
187
668
      {
188
668
      throw BER_Decoding_Error("OID encoding is too short");
189
668
      }
190
243k
191
243k
   m_id.clear();
192
243k
   m_id.push_back(bits[0] / 40);
193
243k
   m_id.push_back(bits[0] % 40);
194
243k
195
243k
   size_t i = 0;
196
1.35M
   while(i != length - 1)
197
1.11M
      {
198
1.11M
      uint32_t component = 0;
199
1.36M
      while(i != length - 1)
200
1.34M
         {
201
1.34M
         ++i;
202
1.34M
203
1.34M
         if(component >> (32-7))
204
414
            throw Decoding_Error("OID component overflow");
205
1.34M
206
1.34M
         component = (component << 7) + (bits[i] & 0x7F);
207
1.34M
208
1.34M
         if(!(bits[i] & 0x80))
209
1.08M
            break;
210
1.34M
         }
211
1.11M
      m_id.push_back(component);
212
1.11M
      }
213
243k
   }
214
215
}