Botan
1.11.15
|
00001 /* 00002 * ASN.1 OID 00003 * (C) 1999-2007 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/asn1_oid.h> 00009 #include <botan/der_enc.h> 00010 #include <botan/ber_dec.h> 00011 #include <botan/internal/bit_ops.h> 00012 #include <botan/parsing.h> 00013 00014 namespace Botan { 00015 00016 /* 00017 * ASN.1 OID Constructor 00018 */ 00019 OID::OID(const std::string& oid_str) 00020 { 00021 if(oid_str != "") 00022 { 00023 try 00024 { 00025 id = parse_asn1_oid(oid_str); 00026 } 00027 catch(...) 00028 { 00029 throw Invalid_OID(oid_str); 00030 } 00031 00032 if(id.size() < 2 || id[0] > 2) 00033 throw Invalid_OID(oid_str); 00034 if((id[0] == 0 || id[0] == 1) && id[1] > 39) 00035 throw Invalid_OID(oid_str); 00036 } 00037 } 00038 00039 /* 00040 * Clear the current OID 00041 */ 00042 void OID::clear() 00043 { 00044 id.clear(); 00045 } 00046 00047 /* 00048 * Return this OID as a string 00049 */ 00050 std::string OID::as_string() const 00051 { 00052 std::string oid_str; 00053 for(size_t i = 0; i != id.size(); ++i) 00054 { 00055 oid_str += std::to_string(id[i]); 00056 if(i != id.size() - 1) 00057 oid_str += '.'; 00058 } 00059 return oid_str; 00060 } 00061 00062 /* 00063 * OID equality comparison 00064 */ 00065 bool OID::operator==(const OID& oid) const 00066 { 00067 if(id.size() != oid.id.size()) 00068 return false; 00069 for(size_t i = 0; i != id.size(); ++i) 00070 if(id[i] != oid.id[i]) 00071 return false; 00072 return true; 00073 } 00074 00075 /* 00076 * Append another component to the OID 00077 */ 00078 OID& OID::operator+=(u32bit component) 00079 { 00080 id.push_back(component); 00081 return (*this); 00082 } 00083 00084 /* 00085 * Append another component to the OID 00086 */ 00087 OID operator+(const OID& oid, u32bit component) 00088 { 00089 OID new_oid(oid); 00090 new_oid += component; 00091 return new_oid; 00092 } 00093 00094 /* 00095 * OID inequality comparison 00096 */ 00097 bool operator!=(const OID& a, const OID& b) 00098 { 00099 return !(a == b); 00100 } 00101 00102 /* 00103 * Compare two OIDs 00104 */ 00105 bool operator<(const OID& a, const OID& b) 00106 { 00107 const std::vector<u32bit>& oid1 = a.get_id(); 00108 const std::vector<u32bit>& oid2 = b.get_id(); 00109 00110 if(oid1.size() < oid2.size()) 00111 return true; 00112 if(oid1.size() > oid2.size()) 00113 return false; 00114 for(size_t i = 0; i != oid1.size(); ++i) 00115 { 00116 if(oid1[i] < oid2[i]) 00117 return true; 00118 if(oid1[i] > oid2[i]) 00119 return false; 00120 } 00121 return false; 00122 } 00123 00124 /* 00125 * DER encode an OBJECT IDENTIFIER 00126 */ 00127 void OID::encode_into(DER_Encoder& der) const 00128 { 00129 if(id.size() < 2) 00130 throw Invalid_Argument("OID::encode_into: OID is invalid"); 00131 00132 std::vector<byte> encoding; 00133 encoding.push_back(40 * id[0] + id[1]); 00134 00135 for(size_t i = 2; i != id.size(); ++i) 00136 { 00137 if(id[i] == 0) 00138 encoding.push_back(0); 00139 else 00140 { 00141 size_t blocks = high_bit(id[i]) + 6; 00142 blocks = (blocks - (blocks % 7)) / 7; 00143 00144 for(size_t j = 0; j != blocks - 1; ++j) 00145 encoding.push_back(0x80 | ((id[i] >> 7*(blocks-j-1)) & 0x7F)); 00146 encoding.push_back(id[i] & 0x7F); 00147 } 00148 } 00149 der.add_object(OBJECT_ID, UNIVERSAL, encoding); 00150 } 00151 00152 /* 00153 * Decode a BER encoded OBJECT IDENTIFIER 00154 */ 00155 void OID::decode_from(BER_Decoder& decoder) 00156 { 00157 BER_Object obj = decoder.get_next_object(); 00158 if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL) 00159 throw BER_Bad_Tag("Error decoding OID, unknown tag", 00160 obj.type_tag, obj.class_tag); 00161 if(obj.value.size() < 2) 00162 throw BER_Decoding_Error("OID encoding is too short"); 00163 00164 00165 clear(); 00166 id.push_back(obj.value[0] / 40); 00167 id.push_back(obj.value[0] % 40); 00168 00169 size_t i = 0; 00170 while(i != obj.value.size() - 1) 00171 { 00172 u32bit component = 0; 00173 while(i != obj.value.size() - 1) 00174 { 00175 ++i; 00176 00177 if(component >> (32-7)) 00178 throw Decoding_Error("OID component overflow"); 00179 00180 component = (component << 7) + (obj.value[i] & 0x7F); 00181 00182 if(!(obj.value[i] & 0x80)) 00183 break; 00184 } 00185 id.push_back(component); 00186 } 00187 } 00188 00189 }