#ifndef _H_CDSA_UTILITIES_CSSMDATA
#define _H_CDSA_UTILITIES_CSSMDATA
#include <security_utilities/alloc.h>
#include <security_utilities/refcount.h>
#include <security_cdsa_utilities/cssmerrors.h>
#include <Security/cssmerr.h>
#include <CoreFoundation/CoreFoundation.h>
namespace Security {
class CssmData : public PodWrapper<CssmData, CSSM_DATA> {
public:
CssmData() { Data = 0; Length = 0; }
size_t length() const { return Length; }
void *data() const { return Data; }
void *end() const { return Data + Length; }
CssmData(void *data, size_t length)
{ Data = reinterpret_cast<UInt8 *>(data); Length = length; }
CssmData(char *data, size_t length)
{ Data = reinterpret_cast<UInt8 *>(data); Length = length; }
CssmData(unsigned char *data, size_t length)
{ Data = reinterpret_cast<UInt8 *>(data); Length = length; }
CssmData(signed char *data, size_t length)
{ Data = reinterpret_cast<UInt8 *>(data); Length = length; }
CssmData(CFDataRef cf)
{ Data = const_cast<UInt8 *>(CFDataGetBytePtr(cf)); Length = CFDataGetLength(cf); }
private: template <class T> CssmData(T *, size_t); public:
template <class T>
explicit CssmData(const T &obj)
{ Data = (UInt8 *)obj.data(); Length = obj.length(); }
template <class T>
static CssmData wrap(const T &it)
{ return CssmData(const_cast<void *>(reinterpret_cast<const void *>(&it)), sizeof(it)); }
template <class T>
static CssmData wrap(T *data, size_t length)
{ return CssmData(const_cast<void *>(static_cast<const void *>(data)), length); }
operator signed char * () const { return reinterpret_cast<signed char *>(Data); }
operator unsigned char * () const { return reinterpret_cast<unsigned char *>(Data); }
operator char * () const { return reinterpret_cast<char *>(Data); }
operator void * () const { return reinterpret_cast<void *>(Data); }
template <class T>
T *interpretedAs() const { return reinterpret_cast<T *>(Data); }
template <class T>
T *interpretedAs(CSSM_RETURN error) const
{ return interpretedAs<T>(sizeof(T), error); }
template <class T>
T *interpretedAs(size_t len, CSSM_RETURN error) const
{
if (data() == NULL || length() != len) CssmError::throwMe(error);
return interpretedAs<T>();
}
public:
void length(size_t newLength) { assert(newLength <= Length); Length = newLength; }
void *at(off_t offset) const
{ assert(offset >= 0 && (CSSM_SIZE)offset <= Length); return Data + offset; }
void *at(off_t offset, size_t size) const { assert(offset >= 0 && (CSSM_SIZE)offset + size <= Length); return Data + offset; }
template <class T> T *at(off_t offset) const { return reinterpret_cast<T *>(at(offset)); }
template <class T> T *at(off_t offset, size_t size) const
{ return reinterpret_cast<T *>(at(offset, size)); }
unsigned char byte(off_t offset) const { return *at<unsigned char>(offset); }
unsigned char &byte(off_t offset) { return *at<unsigned char>(offset); }
void *use(size_t taken) { assert(taken <= Length); void *r = Data; Length -= taken; Data += taken; return r; }
void clear()
{ Data = NULL; Length = 0; }
string toString () const; string toHex() const; string toOid() const; void fromHex(const char *digits);
operator bool () const { return Data != NULL; }
bool operator ! () const { return Data == NULL; }
bool operator < (const CssmData &other) const;
bool operator == (const CssmData &other) const
{ return length() == other.length() && !memcmp(data(), other.data(), length()); }
bool operator != (const CssmData &other) const
{ return !(*this == other); }
template <class T>
void extract(T &destination, CSSM_RETURN error = CSSM_ERRCODE_INVALID_DATA) const
{
if (length() != sizeof(destination) || data() == NULL)
CssmError::throwMe(error);
memcpy(&destination, data(), sizeof(destination));
}
};
inline bool CssmData::operator < (const CssmData &other) const
{
if (Length != other.Length) return Length < other.Length;
if (Length == 0) return false;
if (Data == NULL || other.Data == NULL) return Data < other.Data;
return memcmp(Data, other.Data, Length) < 0; }
typedef CssmData CssmOid;
class StringData : public CssmData {
public:
StringData(const char *s) : CssmData(const_cast<char *>(s), strlen(s)) { }
StringData(const std::string &s) : CssmData(const_cast<char *>(s.c_str()), s.size()) { }
};
template <size_t size>
struct DataBuffer : public CssmData {
unsigned char buffer[size];
DataBuffer() : CssmData(buffer, size) { }
};
bool operator == (const CSSM_DATA &d1, const CSSM_DATA &d2);
inline bool operator != (const CSSM_DATA &d1, const CSSM_DATA &d2)
{ return !(d1 == d2); }
class CssmManagedData {
public:
CssmManagedData(Allocator &alloc) : allocator(alloc) { }
virtual ~CssmManagedData();
Allocator &allocator;
virtual operator const CssmData & () const { return get(); }
template <class T> T *data() const { return reinterpret_cast<T *>(data()); }
void *data() const { return get().data(); }
size_t length() const { return get().length(); }
virtual CssmData &get() const throw() = 0; virtual CssmData release() = 0; virtual void reset() = 0; };
inline bool operator == (const CssmManagedData &d1, const CssmData &d2)
{ return d1.get() == d2; }
inline bool operator == (const CssmData &d1, const CssmManagedData &d2)
{ return d1 == d2.get(); }
inline bool operator == (const CssmManagedData &d1, const CssmManagedData &d2)
{ return d1.get() == d2.get(); }
inline bool operator != (const CssmManagedData &d1, const CssmData &d2)
{ return d1.get() != d2; }
inline bool operator != (const CssmData &d1, const CssmManagedData &d2)
{ return d1 != d2.get(); }
inline bool operator != (const CssmManagedData &d1, const CssmManagedData &d2)
{ return d1.get() != d2.get(); }
class CssmOwnedData : public CssmManagedData {
public:
CssmOwnedData(Allocator &alloc, CssmData &mine) : CssmManagedData(alloc), referent(mine) { }
CssmOwnedData(Allocator &alloc, CSSM_DATA &mine)
: CssmManagedData(alloc), referent(CssmData::overlay(mine)) { referent.clear(); }
operator void * () const { return referent; }
operator char * () const { return referent; }
operator signed char * () const { return referent; }
operator unsigned char * () const { return referent; }
operator bool () const { return referent; }
bool operator ! () const { return !referent; }
size_t length() const { return referent.length(); }
void *malloc(size_t len)
{
CssmAutoPtr<uint8> alloc(allocator, allocator.malloc<uint8>(len));
reset();
return referent = CssmData(alloc.release(), len);
}
void *realloc(size_t newLen)
{
return referent = CssmData(allocator.realloc<uint8>(referent.data(), newLen), newLen);
}
void length(size_t len) { realloc(len); }
void *append(const void *addData, size_t addLength)
{
size_t oldLength = length();
realloc(oldLength + addLength);
return memcpy(referent.at(oldLength), addData, addLength);
}
void *append(const CssmData &data)
{ return append(data.data(), data.length()); }
template <class T>
void set(T *data, size_t length)
{
reset();
referent = CssmData(data, length);
}
void set(CssmManagedData &source);
void set(const CSSM_DATA &source) { set(source.Data, source.Length); }
template <class T>
void copy(const T *data, size_t length)
{
CssmAutoPtr<void> newData(allocator, memcpy(allocator.malloc(length), data, length));
reset();
referent = CssmData(newData.release(), length);
}
void copy(const CssmData &source)
{ if (&source != &referent) copy(source.data(), source.length()); }
void copy(const CSSM_DATA &source)
{ if (&source != &referent) copy(source.Data, source.Length); }
void copy(CssmManagedData &source) { copy(source.get()); }
template <class Data>
void copy(const Data &source) { copy(source.data(), source.length()); }
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (const CSSM_DATA &source) { copy(source); }
CssmData &get() const throw();
public:
void fromOid(const char *oid);
protected:
CssmData &referent;
};
class CssmAutoData : public CssmOwnedData {
public:
CssmAutoData(Allocator &alloc) : CssmOwnedData(alloc, mData) { }
template <class Data>
CssmAutoData(Allocator &alloc, const Data &source) : CssmOwnedData(alloc, mData)
{ *this = source; }
CssmAutoData(CssmAutoData &source) : CssmOwnedData(source.allocator, mData)
{ set(source); }
explicit CssmAutoData(CssmManagedData &source) : CssmOwnedData(source.allocator, mData)
{ set(source); }
CssmAutoData(Allocator &alloc, const void *data, size_t length)
: CssmOwnedData(alloc, mData) { copy(data, length); }
~CssmAutoData() { allocator.free(mData); }
CssmData release();
void reset();
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (CssmAutoData &source) { set(source); }
template <class Data>
void operator = (const Data &source) { copy(source); }
private:
CssmData mData;
};
class CssmRemoteData : public CssmOwnedData {
public:
CssmRemoteData(Allocator &alloc, CssmData &mine)
: CssmOwnedData(alloc, mine), iOwnTheData(true) { }
CssmRemoteData(Allocator &alloc, CSSM_DATA &mine)
: CssmOwnedData(alloc, mine), iOwnTheData(true) { }
~CssmRemoteData()
{ if (iOwnTheData) allocator.free(referent); }
CssmData release();
void reset();
void operator = (CssmManagedData &source) { set(source); }
void operator = (CssmOwnedData &source) { set(source); }
void operator = (CssmAutoData &source) { set(source); }
template <class Data>
void operator = (const Data &source) { copy(source); }
private:
bool iOwnTheData;
};
class CssmPolyData : public CssmData {
template <class T>
uint8 *set(const T &it)
{ return const_cast<uint8 *>(reinterpret_cast<const uint8 *>(&it)); }
public:
template <class char_T>
CssmPolyData(const char_T *s) : CssmData(const_cast<char_T *>(s), strlen(s)) {}
CssmPolyData(const string &s) : CssmData(const_cast<char *>(s.c_str()), s.size()) {}
CssmPolyData(const CSSM_DATA &data) : CssmData(data.Data, data.Length) {}
CssmPolyData(const bool &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const uint32 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const sint32 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const sint64 &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const double &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const unsigned long &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const CSSM_GUID &t) : CssmData(set(t), sizeof(t)) { }
CssmPolyData(const StringPtr s) : CssmData (reinterpret_cast<char*>(s + 1), uint32 (s[0])) {}
};
class CssmDateData : public CssmData
{
public:
CssmDateData(const CSSM_DATE &date);
private:
uint8 buffer[8];
};
class CssmDataContainer : public CssmData, public RefCount
{
public:
CssmDataContainer(Allocator &inAllocator = Allocator::standard()) :
CssmData(), mAllocator(inAllocator) {}
template <class T>
CssmDataContainer(const T *data, size_t length, Allocator &inAllocator = Allocator::standard()) :
CssmData(inAllocator.malloc(length), length), mAllocator(inAllocator)
{ if (length) ::memcpy(Data, data, length); }
void clear() { if (Data) { mAllocator.free(Data); Data = NULL; Length = 0; } }
void invalidate () {Data = NULL; Length = 0;}
~CssmDataContainer() { if (Data) mAllocator.free(Data); }
void append(const CssmPolyData &data)
{
size_t newLength = Length + data.Length;
Data = reinterpret_cast<uint8 *>(mAllocator.realloc(Data, newLength));
memcpy(Data + Length, data.Data, data.Length);
Length = newLength;
}
CssmDataContainer(const CssmDataContainer &other)
: mAllocator(other.mAllocator)
{
Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
memcpy(Data, other.Data, other.Length);
Length = other.Length;
}
CssmDataContainer & operator = (const CSSM_DATA &other)
{
clear();
Data = reinterpret_cast<uint8 *>(mAllocator.malloc(other.Length));
memcpy(Data, other.Data, other.Length);
Length = other.Length;
return *this;
}
public:
Allocator &mAllocator;
private:
operator CssmDataContainer * () const; };
typedef CssmDataContainer CssmOidContainer;
template <class Container>
class CssmBuffer : public RefPointer<Container>
{
public:
CssmBuffer() : RefPointer<Container>(new Container()) {} template <class T>
CssmBuffer(const T *data, size_t length, Allocator &inAllocator = Allocator::standard()) :
RefPointer<Container>(new Container(data, length, inAllocator)) {}
CssmBuffer(const CSSM_DATA &data, Allocator &inAllocator = Allocator::standard()) :
RefPointer<Container>(new Container(data.Data, data.Length, inAllocator)) {}
CssmBuffer(const CssmBuffer& other) : RefPointer<Container>(other) {}
CssmBuffer(Container *p) : RefPointer<Container>(p) {}
bool operator < (const CssmBuffer &other) const { return (**this) < (*other); }
};
}
#endif // _H_CDSA_UTILITIES_CSSMDATA