Botan  1.11.15
src/lib/asn1/asn1_oid.cpp
Go to the documentation of this file.
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 }