// 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 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) 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 &result) const { for(int i=0; iClass()==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 &result) const { for(int i=0; iClass()==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; iLast) 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; iOctetSize(); DataSize -=oct->OctetSize(); } } }