blob: 1e623a5058db78c977e9c3ada375fa17c33bdd63 [file] [log] [blame]
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
* Copyright (c) 2013-2014 Regents of the University of California.
*
* This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
*
* ndn-cxx library is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received copies of the GNU General Public License and GNU Lesser
* General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
* <http://www.gnu.org/licenses/>.
*
* See AUTHORS.md for complete list of ndn-cxx authors and contributors.
*
*/
#include "common.hpp"
#include "oid.hpp"
#include "../security/cryptopp.hpp"
#include <sstream>
namespace ndn {
using std::string;
using std::vector;
static const int OID_MAGIC_NUMBER = 40;
OID::OID(const char* oid)
{
construct(oid);
}
OID::OID(const string& oid)
{
construct(oid);
}
void
OID::construct(const std::string& oid)
{
string str = oid + ".";
size_t pos = 0;
size_t ppos = 0;
while (string::npos != pos) {
ppos = pos;
pos = str.find_first_of('.', pos);
if (pos == string::npos)
break;
m_oid.push_back(atoi(str.substr(ppos, pos - ppos).c_str()));
pos++;
}
}
string
OID::toString() const
{
std::ostringstream convert;
for (vector<int>::const_iterator it = m_oid.begin(); it != m_oid.end(); ++it) {
if (it != m_oid.begin())
convert << ".";
convert << *it;
}
return convert.str();
}
bool
OID::equal(const OID& oid) const
{
vector<int>::const_iterator i = m_oid.begin();
vector<int>::const_iterator j = oid.m_oid.begin();
for (; i != m_oid.end() && j != oid.m_oid.end(); i++, j++) {
if (*i != *j)
return false;
}
return (i == m_oid.end() && j == oid.m_oid.end()); // keep parenthesis for readability.
}
inline void
encodeValue(CryptoPP::BufferedTransformation& bt, CryptoPP::word32 v)
{
using namespace CryptoPP;
for (unsigned int i = RoundUpToMultipleOf(STDMAX(7U, BitPrecision(v)), 7U) - 7; i != 0; i -= 7)
bt.Put(static_cast<byte>(0x80 | ((v >> i) & 0x7f)));
bt.Put(static_cast<byte>(v & 0x7f));
}
inline size_t
decodeValue(CryptoPP::BufferedTransformation& bt, CryptoPP::word32& v)
{
using namespace CryptoPP;
v = 0;
size_t i = 0;
while (true)
{
byte b;
if (!bt.Get(b))
BERDecodeError();
i++;
if (v >> (8 * sizeof(v) - 7)) // v about to overflow
BERDecodeError();
v <<= 7;
v += b & 0x7f;
if ((b & 0x80) == 0)
return i;
}
}
void
OID::encode(CryptoPP::BufferedTransformation& out) const
{
using namespace CryptoPP;
BOOST_ASSERT(m_oid.size() >= 2);
ByteQueue temp;
temp.Put(byte(m_oid[0] * OID_MAGIC_NUMBER + m_oid[1]));
for (size_t i = 2; i < m_oid.size(); i++)
encodeValue(temp, m_oid[i]);
out.Put(OBJECT_IDENTIFIER);
DERLengthEncode(out, temp.CurrentSize());
temp.TransferTo(out);
}
void
OID::decode(CryptoPP::BufferedTransformation& in)
{
using namespace CryptoPP;
byte b;
if (!in.Get(b) || b != OBJECT_IDENTIFIER)
BERDecodeError();
size_t length;
if (!BERLengthDecode(in, length) || length < 1)
BERDecodeError();
if (!in.Get(b))
BERDecodeError();
length--;
m_oid.resize(2);
m_oid[0] = b / OID_MAGIC_NUMBER;
m_oid[1] = b % OID_MAGIC_NUMBER;
while (length > 0)
{
word32 v;
size_t valueLen = decodeValue(in, v);
if (valueLen > length)
BERDecodeError();
m_oid.push_back(v);
length -= valueLen;
}
}
namespace oid {
const OID RSA("1.2.840.113549.1.1.1");
const OID ECDSA("1.2.840.10045.2.1");
const OID ATTRIBUTE_NAME("2.5.4.41");
}
} // namespace ndn