|
|
// BEROctet.cpp - Implementation of BEROctet class
//
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
// 1999. This computer program includes Confidential, Proprietary
// Information and is a Trade Secret of Schlumberger Technology Corp. All
// use, disclosure, and/or reproduction is prohibited unless authorized
// in writing. All Rights Reserved.
//////////////////////////////////////////////////////////////////////
#include "pkiBEROctet.h"
using namespace pki;
BEROctet::BEROctet() : m_Octet(0) { }
BEROctet::BEROctet(const BEROctet &oct) { m_Octet = 0; *this = oct; }
BEROctet::BEROctet(const unsigned char *Buffer, const unsigned long Size) { m_Octet = new unsigned char[Size]; memcpy(m_Octet,Buffer,Size); m_OctetSize = Size; Decode(); }
BEROctet::~BEROctet(void) { for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i]; if(m_Octet) delete[] m_Octet; }
BEROctet& BEROctet::operator=(const BEROctet &Oct) {
if(m_Octet) delete[] m_Octet; for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i]; m_SubOctetList.resize(0);
if(Oct.m_Octet) { m_Octet = new unsigned char[Oct.m_OctetSize]; memcpy(m_Octet,Oct.m_Octet,Oct.m_OctetSize); m_OctetSize = Oct.m_OctetSize; Decode(); } else { m_Octet = 0; }
return *this; }
// Returns the octet data
unsigned char *BEROctet::Octet() const { return m_Octet; }
unsigned long BEROctet::OctetSize() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_OctetSize; }
// Returns true if the octet is constructet, false otherwise
bool BEROctet::Constructed() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_PrimConst ? true : false; }
// Returns the class of the octet
unsigned long BEROctet::Class() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Class; }
// Returns the tag of the octet
unsigned long BEROctet::Tag() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Tag; }
// Returns a the data part of the octet
unsigned char *BEROctet::Data() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_Data; }
// Returns a the size of the data part of the octet
unsigned long BEROctet::DataSize() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_DataSize; }
// If the octet is a constructed type, this returns list of sub-octets
std::vector<BEROctet*> BEROctet::SubOctetList() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
return m_SubOctetList; }
// If the octet is an OID, this returns the decoded version, otherwise an empty string
std::string BEROctet::ObjectID() const {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
std::string OID;
if(m_Class==0 && m_Tag==6) {
char text[40]; unsigned long subid; unsigned char *c = m_Data; unsigned char *Last = m_Octet + m_OctetSize; bool First = true;
while(c<Last) { subid = (*c)&0x7F; while((*c)&0x80) { c++; if(c>=Last) throw Exception(ccBERUnexpectedEndOfOctet); if(subid>0x01FFFFFF) throw Exception(ccBEROIDSubIdentifierOverflow); subid = (subid<<7) | ((*c)&0x7F); } if(First) { unsigned long X,Y; if(subid<40) X=0; else if(subid<80) X=1; else X=2; Y = subid-X*40; sprintf(text,"%d %d",X,Y); OID = text; First = false; } else { sprintf(text," %d",subid); OID += text; } c++; } }
return OID; }
// SearchOID returns all the constructed octets that contain a particular OID
void BEROctet::SearchOID(std::string const &OID, std::vector<BEROctet const*> &result) const {
for(int i=0; i<m_SubOctetList.size(); i++) {
if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) { if(OID==m_SubOctetList[i]->ObjectID()) { result.push_back(this); } } else if(m_SubOctetList[i]->Constructed()) { m_SubOctetList[i]->SearchOID(OID,result); } }
return;
}
// SearchOIDNext returns all the octets following a particular OID
void BEROctet::SearchOIDNext(std::string const &OID, std::vector<BEROctet const*> &result) const { for(int i=0; i<m_SubOctetList.size(); i++) {
if(m_SubOctetList[i]->Class()==0 && m_SubOctetList[i]->Tag()==6) { if(OID==m_SubOctetList[i]->ObjectID()) { if((i+1) < m_SubOctetList.size()) result.push_back(m_SubOctetList[i+1]); } } else if(m_SubOctetList[i]->Constructed()) { m_SubOctetList[i]->SearchOIDNext(OID,result); } }
return;
}
// Decodes recursively a BER octet.
void BEROctet::Decode() {
if(!m_Octet) throw Exception(ccBEREmptyOctet);
long BufferSize = m_OctetSize;
m_PrimConst = (m_Octet[0]>>5) & 0x1; m_Class = (m_Octet[0]>>6) & 0x3; unsigned char *c = m_Octet; unsigned char *Last = c + BufferSize - 1; m_Tag = *c & 0x1F;
if(m_Tag>30) { m_Tag = 0;
c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
while (*c & 0x80) { m_Tag = (m_Tag << 7) | ((*c) & 0x7F); c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet); }
if(m_Tag > 0x01FFFFFF) throw Exception(ccBERTagValueOverflow);
m_Tag = (m_Tag << 7) | ((*c) & 0x7F);
}
c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet);
long DataSize;
if((*c)&0x80) { int n = (*c) & 0x7F; if(n) { DataSize = 0; for(int i=0; i<n; i++) { c++; if(c>Last) throw Exception(ccBERUnexpectedEndOfOctet); if(DataSize>0x007FFFFF) throw Exception(ccBERDataLengthOverflow); DataSize = (DataSize<<8) | (*c); } } else throw Exception(ccBERUnexpectedIndefiniteLength); } else DataSize = *c;
c++; m_Data = c; m_DataSize = DataSize; unsigned long OctetSize = DataSize + (m_Data-m_Octet); if(OctetSize>BufferSize) throw Exception(ccBERInconsistentDataLength); m_OctetSize = OctetSize;
for(int i=0; i<m_SubOctetList.size(); i++) delete m_SubOctetList[i]; m_SubOctetList.resize(0);
if(m_PrimConst) {
// Constructed type
unsigned char *TmpData = m_Data; unsigned long TmpDataSize = m_DataSize;
while(TmpDataSize) {
BEROctet *oct = new BEROctet(TmpData,TmpDataSize);
m_SubOctetList.push_back(oct);
TmpData += oct->OctetSize(); TmpDataSize -=oct->OctetSize(); } } }
|