Coverage Report

Created: 2022-06-23 06:44

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