Botan  2.8.0
Crypto and TLS for C++11
asn1_oid.cpp
Go to the documentation of this file.
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 
14 namespace Botan {
15 
16 /*
17 * ASN.1 OID Constructor
18 */
19 OID::OID(const std::string& oid_str)
20  {
21  if(!oid_str.empty())
22  {
23  try
24  {
25  m_id = parse_asn1_oid(oid_str);
26  }
27  catch(...)
28  {
29  throw Invalid_OID(oid_str);
30  }
31 
32  if(m_id.size() < 2 || m_id[0] > 2)
33  throw Invalid_OID(oid_str);
34  if((m_id[0] == 0 || m_id[0] == 1) && m_id[1] > 39)
35  throw Invalid_OID(oid_str);
36  }
37  }
38 
39 /*
40 * Clear the current OID
41 */
42 void OID::clear()
43  {
44  m_id.clear();
45  }
46 
47 /*
48 * Return this OID as a string
49 */
50 std::string OID::to_string() const
51  {
52  std::string oid_str;
53  for(size_t i = 0; i != m_id.size(); ++i)
54  {
55  oid_str += std::to_string(m_id[i]);
56  if(i != m_id.size() - 1)
57  oid_str += ".";
58  }
59  return oid_str;
60  }
61 
62 /*
63 * OID equality comparison
64 */
65 bool OID::operator==(const OID& oid) const
66  {
67  if(m_id.size() != oid.m_id.size())
68  return false;
69  for(size_t i = 0; i != m_id.size(); ++i)
70  if(m_id[i] != oid.m_id[i])
71  return false;
72  return true;
73  }
74 
75 /*
76 * Append another component to the OID
77 */
78 OID& OID::operator+=(uint32_t component)
79  {
80  m_id.push_back(component);
81  return (*this);
82  }
83 
84 /*
85 * Append another component to the OID
86 */
87 OID operator+(const OID& oid, uint32_t component)
88  {
89  OID new_oid(oid);
90  new_oid += component;
91  return new_oid;
92  }
93 
94 /*
95 * OID inequality comparison
96 */
97 bool operator!=(const OID& a, const OID& b)
98  {
99  return !(a == b);
100  }
101 
102 /*
103 * Compare two OIDs
104 */
105 bool operator<(const OID& a, const OID& b)
106  {
107  const std::vector<uint32_t>& oid1 = a.get_id();
108  const std::vector<uint32_t>& oid2 = b.get_id();
109 
110  if(oid1.size() < oid2.size())
111  return true;
112  if(oid1.size() > oid2.size())
113  return false;
114  for(size_t i = 0; i != oid1.size(); ++i)
115  {
116  if(oid1[i] < oid2[i])
117  return true;
118  if(oid1[i] > oid2[i])
119  return false;
120  }
121  return false;
122  }
123 
124 /*
125 * DER encode an OBJECT IDENTIFIER
126 */
128  {
129  if(m_id.size() < 2)
130  throw Invalid_Argument("OID::encode_into: OID is invalid");
131 
132  std::vector<uint8_t> encoding;
133 
134  if(m_id[0] > 2 || m_id[1] >= 40)
135  throw Encoding_Error("Invalid OID prefix, cannot encode");
136 
137  encoding.push_back(static_cast<uint8_t>(40 * m_id[0] + m_id[1]));
138 
139  for(size_t i = 2; i != m_id.size(); ++i)
140  {
141  if(m_id[i] == 0)
142  encoding.push_back(0);
143  else
144  {
145  size_t blocks = high_bit(m_id[i]) + 6;
146  blocks = (blocks - (blocks % 7)) / 7;
147 
148  BOTAN_ASSERT(blocks > 0, "Math works");
149 
150  for(size_t j = 0; j != blocks - 1; ++j)
151  encoding.push_back(0x80 | ((m_id[i] >> 7*(blocks-j-1)) & 0x7F));
152  encoding.push_back(m_id[i] & 0x7F);
153  }
154  }
155  der.add_object(OBJECT_ID, UNIVERSAL, encoding);
156  }
157 
158 /*
159 * Decode a BER encoded OBJECT IDENTIFIER
160 */
162  {
163  BER_Object obj = decoder.get_next_object();
164  if(obj.tagging() != OBJECT_ID)
165  throw BER_Bad_Tag("Error decoding OID, unknown tag", obj.tagging());
166 
167  const size_t length = obj.length();
168  const uint8_t* bits = obj.bits();
169 
170  if(length < 2 && !(length == 1 && bits[0] == 0))
171  {
172  throw BER_Decoding_Error("OID encoding is too short");
173  }
174 
175  clear();
176  m_id.push_back(bits[0] / 40);
177  m_id.push_back(bits[0] % 40);
178 
179  size_t i = 0;
180  while(i != length - 1)
181  {
182  uint32_t component = 0;
183  while(i != length - 1)
184  {
185  ++i;
186 
187  if(component >> (32-7))
188  throw Decoding_Error("OID component overflow");
189 
190  component = (component << 7) + (bits[i] & 0x7F);
191 
192  if(!(bits[i] & 0x80))
193  break;
194  }
195  m_id.push_back(component);
196  }
197  }
198 
199 }
ASN1_Tag tagging() const
Definition: asn1_obj.h:113
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
Definition: alg_id.cpp:90
DER_Encoder & add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const uint8_t rep[], size_t length)
Definition: der_enc.cpp:249
void encode_into(class DER_Encoder &) const override
Definition: asn1_oid.cpp:127
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
void clear()
Definition: asn1_oid.cpp:42
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
std::string to_string() const
Definition: asn1_oid.cpp:50
bool operator<(const OID &a, const OID &b)
Definition: asn1_oid.cpp:105
OID(const std::string &str="")
Definition: asn1_oid.cpp:19
void decode_from(class BER_Decoder &) override
Definition: asn1_oid.cpp:161
size_t high_bit(T n)
Definition: bit_ops.h:37
size_t length() const
Definition: asn1_obj.h:120
Definition: alg_id.cpp:13
BER_Object get_next_object()
Definition: ber_dec.cpp:237
const uint8_t * bits() const
Definition: asn1_obj.h:118
OID operator+(const OID &oid, uint32_t component)
Definition: asn1_oid.cpp:87
const std::vector< uint32_t > & get_id() const
Definition: asn1_oid.h:42
bool operator==(const OID &) const
Definition: asn1_oid.cpp:65
std::vector< uint32_t > parse_asn1_oid(const std::string &oid)
Definition: parsing.cpp:195
OID & operator+=(uint32_t new_comp)
Definition: asn1_oid.cpp:78