#include <security_cdsa_utilities/cssmdata.h>
#include <security_utilities/utilities.h>
#include <cstring>
#include <algorithm>
namespace Security {
bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2)
{
if (&d1 == &d2)
return true; if (d1.Length != d2.Length)
return false; if (d1.Data == d2.Data)
return true; return !memcmp(d1.Data, d2.Data, d1.Length);
}
string CssmData::toString() const
{
return data() ?
string(reinterpret_cast<const char *>(data()), length())
:
string();
}
string CssmData::toHex() const
{
static const char digits[] = "0123456789abcdef";
string result;
unsigned char *p = Data;
for (uint32 n = 0; n < length(); n++) {
result.push_back(digits[p[n] >> 4]);
result.push_back(digits[p[n] & 0xf]);
}
return result;
}
static unsigned char hexValue(char c)
{
static const char digits[] = "0123456789abcdef";
if (const char *p = strchr(digits, tolower(c)))
return p - digits;
else
return 0;
}
void CssmData::fromHex(const char *hexDigits)
{
size_t bytes = strlen(hexDigits) / 2; length(bytes); for (size_t n = 0; n < bytes; n++) {
Data[n] = hexValue(hexDigits[2*n]) << 4 | hexValue(hexDigits[2*n+1]);
}
}
static unsigned long getOid(const CssmData &data, unsigned int &pos)
{
unsigned long q = 0;
do {
q = q * 128 + (data.byte(pos) & ~0x80);
} while (pos < data.length() && data.byte(pos++) & 0x80);
return q;
}
string CssmData::toOid() const
{
if (length() == 0)
return "";
unsigned int pos = 0;
char buffer[10];
unsigned long oid1 = getOid(*this, pos);
unsigned int q1 = min(oid1 / 40, 2ul);
snprintf(buffer, sizeof(buffer), "%u.%lu", q1, oid1 - q1 * 40);
string s = buffer;
while (pos < length()) {
char buffer[20];
snprintf(buffer, sizeof(buffer), ".%lu", getOid(*this, pos));
s += buffer;
}
return s;
}
static void putOid(CssmOwnedData &data, unsigned long id)
{
unsigned char buffer[sizeof(unsigned long) * 2]; unsigned char *p = buffer + sizeof(buffer);
do {
*--p = 0x80 | (id & 0x7F); } while ((id >>= 7) > 0);
buffer[sizeof(buffer) - 1] &= ~0x80; data.append(p, buffer + sizeof(buffer) - p); }
void CssmOwnedData::fromOid(const char *oid)
{
this->length(0);
unsigned long q1 = strtoul(oid, (char **)&oid, 10);
if (*oid++ != '.')
return;
unsigned long q2 = strtoul(oid, (char **)&oid, 10);
putOid(*this, 40 * q1 + q2);
while (oid[0] == '.') {
oid++;
putOid(*this, strtoul(oid, (char **)&oid, 10));
}
}
CssmManagedData::~CssmManagedData()
{ }
void CssmOwnedData::set(CssmManagedData &source)
{
if (source.length() == 0) { reset(); } else if (allocator == source.allocator) { if (referent.data() == source.data()) { assert(this == &source); } else { reset(); referent = source.release(); }
} else { copy(source); source.reset(); }
}
CssmData CssmAutoData::release()
{
CssmData result = mData;
mData.clear();
return result;
}
void CssmAutoData::reset()
{
allocator.free(mData);
mData.clear();
}
CssmData CssmRemoteData::release()
{
iOwnTheData = false;
return referent;
}
void CssmRemoteData::reset()
{
if (iOwnTheData)
allocator.free(referent);
referent.clear();
}
CssmDateData::CssmDateData(const CSSM_DATE &date)
: CssmData(buffer, sizeof(buffer))
{
memcpy(buffer, date.Year, 4);
memcpy(buffer + 4, date.Month, 2);
memcpy(buffer + 6, date.Day, 2);
}
CssmData& CssmOwnedData::get() const throw()
{
return referent;
}
}